diff --git a/sql/install/30-cnm_annotation.sql b/sql/install/30-cnm_annotation.sql deleted file mode 100644 index b69a0abf40d8326676a5746204b5bd83050a32db..0000000000000000000000000000000000000000 --- a/sql/install/30-cnm_annotation.sql +++ /dev/null @@ -1,65 +0,0 @@ --- --- PostgreSQL database dump --- - - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - -SET default_tablespace = ''; - -SET default_with_oids = false; - --- --- Name: cnm_annotation; Type: TABLE; Schema: public; Owner: icnml --- - -CREATE TABLE public.cnm_annotation ( - id integer NOT NULL, - uuid uuid NOT NULL, - folder uuid NOT NULL, - annotation_data character varying NOT NULL, - fpc integer NOT NULL -); - - -ALTER TABLE public.cnm_annotation OWNER TO icnml; - --- --- Name: cnm_annotation_id_seq; Type: SEQUENCE; Schema: public; Owner: icnml --- - -CREATE SEQUENCE public.cnm_annotation_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.cnm_annotation_id_seq OWNER TO icnml; - --- --- Name: cnm_annotation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: icnml --- - -ALTER SEQUENCE public.cnm_annotation_id_seq OWNED BY public.cnm_annotation.id; - - --- --- Name: cnm_annotation id; Type: DEFAULT; Schema: public; Owner: icnml --- - -ALTER TABLE ONLY public.cnm_annotation ALTER COLUMN id SET DEFAULT nextval('public.cnm_annotation_id_seq'::regclass); - - - diff --git a/sql/install/31-cnm_data.sql b/sql/install/31-cnm_data.sql deleted file mode 100644 index 6734fb9b977572e615c3d6b04c172f6012928909..0000000000000000000000000000000000000000 --- a/sql/install/31-cnm_data.sql +++ /dev/null @@ -1,67 +0,0 @@ --- --- PostgreSQL database dump --- - - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - -SET default_tablespace = ''; - -SET default_with_oids = false; - --- --- Name: cnm_data; Type: TABLE; Schema: public; Owner: icnml --- - -CREATE TABLE public.cnm_data ( - id integer NOT NULL, - uuid uuid NOT NULL, - folder uuid NOT NULL, - user_id integer NOT NULL, - fpc integer NOT NULL, - cnm_type integer, - db_size integer, - cnm_data character varying -); - - -ALTER TABLE public.cnm_data OWNER TO icnml; - --- --- Name: cnm_data_id_seq; Type: SEQUENCE; Schema: public; Owner: icnml --- - -CREATE SEQUENCE public.cnm_data_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.cnm_data_id_seq OWNER TO icnml; - --- --- Name: cnm_data_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: icnml --- - -ALTER SEQUENCE public.cnm_data_id_seq OWNED BY public.cnm_data.id; - - --- --- Name: cnm_data id; Type: DEFAULT; Schema: public; Owner: icnml --- - -ALTER TABLE ONLY public.cnm_data ALTER COLUMN id SET DEFAULT nextval('public.cnm_data_id_seq'::regclass); - - diff --git a/sql/install/32-cnm_folder.sql b/sql/install/32-cnm_folder.sql deleted file mode 100644 index cfe68c12487fdc879c5bc7d93e571cd83292b5c3..0000000000000000000000000000000000000000 --- a/sql/install/32-cnm_folder.sql +++ /dev/null @@ -1,62 +0,0 @@ --- --- PostgreSQL database dump --- - - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - -SET default_tablespace = ''; - -SET default_with_oids = false; - --- --- Name: cnm_folder; Type: TABLE; Schema: public; Owner: icnml --- - -CREATE TABLE public.cnm_folder ( - id integer NOT NULL, - donor uuid NOT NULL, - uuid uuid NOT NULL -); - - -ALTER TABLE public.cnm_folder OWNER TO icnml; - --- --- Name: cnm_folder_id_seq; Type: SEQUENCE; Schema: public; Owner: icnml --- - -CREATE SEQUENCE public.cnm_folder_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.cnm_folder_id_seq OWNER TO icnml; - --- --- Name: cnm_folder_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: icnml --- - -ALTER SEQUENCE public.cnm_folder_id_seq OWNED BY public.cnm_folder.id; - - --- --- Name: cnm_folder id; Type: DEFAULT; Schema: public; Owner: icnml --- - -ALTER TABLE ONLY public.cnm_folder ALTER COLUMN id SET DEFAULT nextval('public.cnm_folder_id_seq'::regclass); - - diff --git a/sql/install/33-cnm_segments.sql b/sql/install/33-cnm_segments.sql deleted file mode 100644 index e33e6bcdedbf01a4672bba0cd578e5c6a9867390..0000000000000000000000000000000000000000 --- a/sql/install/33-cnm_segments.sql +++ /dev/null @@ -1,64 +0,0 @@ --- --- PostgreSQL database dump --- - - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - -SET default_tablespace = ''; - -SET default_with_oids = false; - --- --- Name: cnm_segments; Type: TABLE; Schema: public; Owner: icnml --- - -CREATE TABLE public.cnm_segments ( - id integer NOT NULL, - uuid uuid NOT NULL, - fpc integer NOT NULL, - folder_uuid uuid NOT NULL -); - - -ALTER TABLE public.cnm_segments OWNER TO icnml; - --- --- Name: cnm_segments_id_seq; Type: SEQUENCE; Schema: public; Owner: icnml --- - -CREATE SEQUENCE public.cnm_segments_id_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.cnm_segments_id_seq OWNER TO icnml; - --- --- Name: cnm_segments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: icnml --- - -ALTER SEQUENCE public.cnm_segments_id_seq OWNED BY public.cnm_segments.id; - - --- --- Name: cnm_segments id; Type: DEFAULT; Schema: public; Owner: icnml --- - -ALTER TABLE ONLY public.cnm_segments ALTER COLUMN id SET DEFAULT nextval('public.cnm_segments_id_seq'::regclass); - - - diff --git a/templates/navigations/administrator.html b/templates/navigations/administrator.html index 64150c99ec2141a1324ad3c4257700699c978b72..f4e3a9fd92f8c192090df74cf01292efb86f6bfe 100644 --- a/templates/navigations/administrator.html +++ b/templates/navigations/administrator.html @@ -11,9 +11,6 @@
Trainer folders
-
- AFIS -
PiAnoS
diff --git a/utils/__init__.py b/utils/__init__.py index 5098b20324e4edd84044c98fe59ae6f27dcdeaec..1e1b9232de225f1028eca0c722675c07a5374dd6 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -4,6 +4,7 @@ from . import aes from . import decorator from . import encryption +from . import fingers from . import hash from . import images from . import mail diff --git a/utils/fingers.py b/utils/fingers.py new file mode 100644 index 0000000000000000000000000000000000000000..3bc8c4b99df3eb9f4f844ba27226d9a07a63bedd --- /dev/null +++ b/utils/fingers.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +def get_multi_img_fpc( fpc ): + multi_img_fpc = { + 1: [ 1, 11 ], + 2: [ 2, 13 ], + 3: [ 3, 13 ], + 4: [ 4, 13 ], + 5: [ 5, 13 ], + 6: [ 6, 12 ], + 7: [ 7, 14 ], + 8: [ 8, 14 ], + 9: [ 9, 14 ], + 10: [ 10, 14 ] + } + fpc = int( fpc ) + fpcs = multi_img_fpc.get( fpc, [ fpc ] ) + + return fpcs + diff --git a/views/afis/__init__.py b/views/afis/__init__.py index 88a44bd3e62f03c5dbbc6c99f2b24cffb919fb04..987a47cba940589bc95a7ab9eef12839724ae2f8 100644 --- a/views/afis/__init__.py +++ b/views/afis/__init__.py @@ -1,9 +1,11 @@ #!/usr/bin/env python # -*- coding: UTF-8 -*- +from cStringIO import StringIO +from flask import Blueprint, session, current_app, request, jsonify, send_file, url_for, abort, redirect +from uuid import uuid4 import base64 import json -import os import zipfile from cStringIO import StringIO from uuid import uuid4 @@ -23,578 +25,439 @@ segments_position_code = dict( FINGER_POSITION_CODE, **PALM_POSITION_CODE ) afis_view = Blueprint( "afis", __name__, template_folder = "templates" ) -@afis_view.route( "/admin/afis/list" ) -@utils.decorator.admin_required -def admin_list_folders(): - return list_folders_inner( True ) - @afis_view.route( "/afis/list" ) @utils.decorator.login_required def list_folders(): - return list_folders_inner( False ) - -def list_folders_inner( isadmin ): - if isadmin: - sql = """ - SELECT - cnm_folder.uuid, - users.username - FROM cnm_folder - INNER JOIN submissions ON submissions.uuid = cnm_folder.donor - INNER JOIN users ON submissions.donor_id = users.id - ORDER BY users.id DESC - """ - else: - sql = """ - SELECT DISTINCT ON ( users.id ) - cnm_folder.uuid, - users.username - FROM cnm_folder - INNER JOIN cnm_folder_users ON cnm_folder.uuid = cnm_folder_users.folder_id - INNER JOIN submissions ON submissions.uuid = cnm_folder.donor - INNER JOIN users ON submissions.donor_id = users.id - WHERE cnm_folder_users.user_id = %s - ORDER BY users.id DESC - """ - folders = config.db.query_fetchall( sql, ( session.get( "user_id" ), ) ) + user_id = session.get( "user_id", None ) sql = """ SELECT - submissions.uuid, - users.username - FROM submissions - LEFT JOIN users ON submissions.donor_id = users.id - LEFT JOIN cnm_folder ON submissions.uuid = cnm_folder.donor - WHERE cnm_folder.uuid IS NULL - ORDER BY users.id ASC + cnm_assignment.folder_uuid, + tmp.* + FROM cnm_assignment + LEFT JOIN cnm_folder ON cnm_assignment.folder_uuid = cnm_folder.uuid + LEFT JOIN ( + SELECT DISTINCT ON ( donor_id, pc ) * + FROM donor_segments_v + ) AS tmp ON cnm_folder.donor_id = tmp.donor_id AND cnm_folder.pc = tmp.pc + + WHERE cnm_assignment.user_id = %s + + ORDER BY + tmp.donor_id ASC, + tmp.pc ASC """ - donors = config.db.query_fetchall( sql ) + folder_list = config.db.query_fetchall( sql, ( user_id, ) ) return utils.template.my_render_template( - "afis/shared/list.html", - folders = folders, - donors = donors + "afis/user/folder_list.html", + folder_list = folder_list ) -@afis_view.route( "/admin/afis/new_folder", methods = [ "POST" ] ) +@afis_view.route( "/admin/target///new" ) @utils.decorator.admin_required -def admin_add_new_folder(): - try: - donor_uuid = request.form.get( "donor_uuid", False ) - - sql = "SELECT count( * ) AS nb FROM cnm_folder WHERE donor = %s" - nb = config.db.query_fetchone( sql, ( donor_uuid, ) )[ "nb" ] - - if nb == 0: - sql = utils.sql.sql_insert_generate( "cnm_folder", [ "donor", "uuid" ], "id" ) - config.db.query_fetchone( sql, ( donor_uuid, str( uuid4() ) ) ) - config.db.commit() - - return jsonify( { - "error": False - } ) +def admin_create_new_target_and_redirect( submission_id, pc ): + sql = "SELECT donor_id FROM submissions WHERE uuid = %s" + donor_id = config.db.query_fetchone( sql, ( submission_id, ) )[ "donor_id" ] + pc = int( pc ) - except: - return jsonify( { - "error": True - } ) - -@afis_view.route( "/admin/afis//delete" ) -@utils.decorator.admin_required -def admin_delete_folder( folder_id ): - try: - sql = "DELETE FROM cnm_annotation WHERE folder = %s" - config.db.query( sql, ( folder_id, ) ) - - sql = "DELETE FROM cnm_segments WHERE folder_uuid = %s" - config.db.query( sql, ( folder_id, ) ) - - sql = "DELETE FROM cnm_folder WHERE uuid = %s" - config.db.query( sql, ( folder_id, ) ) - - config.db.commit() - - return jsonify( { - "error": False - } ) - except: - return jsonify( { - "error": True - } ) - + target_uuid = str( uuid4() ) + + sql = utils.sql.sql_insert_generate( "cnm_folder", [ "uuid", "pc", "donor_id" ], "id" ) + config.db.query_fetchone( sql, ( target_uuid, pc, donor_id, ) ) + config.db.commit() + + return redirect( url_for( "afis.admin_show_target", uuid = target_uuid ) ) -@afis_view.route( "/admin/afis/" ) +@afis_view.route( "/admin/target/" ) @utils.decorator.admin_required -def admin_folder_show( folder_id ): - return folder_show_inner( folder_id ) +def admin_show_target( uuid ): + return show_folder_inner( uuid, True ) -@afis_view.route( "/afis/" ) +@afis_view.route( "/afis/" ) @utils.decorator.login_required -def folder_show( folder_id ): - return folder_show_inner( folder_id ) - -def folder_show_inner( folder_id ): - admin = session.get( "account_type_name", None ) == "Administrator" +def show_folder( uuid ): + return show_folder_inner( uuid, False ) +def get_segment_list_for_target_folder( uuid, admin = True ): + if not admin: + sql = """ + SELECT count(*) AS count + FROM cnm_assignment + LEFT JOIN cnm_assignment_type ON cnm_assignment.assignment_type = cnm_assignment_type.id + WHERE + folder_uuid = %s AND + user_id = %s AND + cnm_assignment_type.name = 'reference' + """ + if config.db.query_fetchone( sql, ( uuid, session.get( "user_id", False ), ) )[ "count" ] == 0: + return None + sql = """ SELECT - segments_locations.fpc - FROM segments_locations - INNER JOIN files ON segments_locations.tenprint_id = files.uuid - INNER JOIN submissions ON files.folder = submissions.id - INNER JOIN cnm_folder ON submissions.uuid = cnm_folder.donor - WHERE - cnm_folder.uuid = %s AND - ( - fpc <= 10 OR - fpc = 22 OR - fpc = 24 OR - fpc = 25 OR - fpc = 27 - ) - GROUP BY fpc - ORDER BY fpc ASC - """ - segment_list = config.db.query_fetchall( sql, ( folder_id, ) ) - - sql = """ - SELECT * - FROM cnm_segments - WHERE folder_uuid = %s - ORDER BY fpc ASC - """ - segment_list_in_folder = config.db.query_fetchall( sql, ( folder_id, ) ) - - sql = """ - SELECT - files_segments.tenprint, - files_segments.pc + cnm_folder.uuid AS folder_uuid, + donor_segments_v.* FROM cnm_folder - INNER JOIN submissions ON cnm_folder.donor = submissions.uuid - INNER JOIN files ON submissions.id = files.folder - INNER JOIN files_segments ON files.uuid = files_segments.tenprint - WHERE cnm_folder.uuid = %s - """ - tpid = config.db.query_fetchall( sql, ( folder_id, ) ) - sql = """ - SELECT username - FROM users - INNER JOIN submissions ON users.id = submissions.donor_id - INNER JOIN cnm_folder ON submissions.uuid = cnm_folder.donor - WHERE cnm_folder.uuid = %s - """ - username = config.db.query_fetchone( sql, ( folder_id, ) )[ "username" ] + LEFT JOIN fingers_same ON cnm_folder.pc = fingers_same.base_finger + RIGHT JOIN donor_segments_v ON + cnm_folder.donor_id = donor_segments_v.donor_id AND + fingers_same.target = donor_segments_v.pc - # Users assigned to this folder - sql = "SELECT id, username FROM users WHERE type = 5" - users = config.db.query_fetchall( sql ) + WHERE cnm_folder.uuid = %s - sql = """ - SELECT - users.id, - users.username - FROM cnm_folder_users - INNER JOIN users ON cnm_folder_users.user_id = users.id - WHERE - folder_id = %s AND - img_type = 1 + ORDER BY + donor_segments_v.donor_id ASC, + donor_segments_v.pc ASC """ - users_assigned_refs = config.db.query_fetchall( sql, ( folder_id, ) ) - - sql = """ - SELECT - users.id, - users.username - FROM cnm_folder_users - INNER JOIN users ON cnm_folder_users.user_id = users.id - WHERE - folder_id = %s AND - img_type = 2 - """ - users_assigned_marks = config.db.query_fetchall( sql, ( folder_id, ) ) - - return utils.template.my_render_template( - "afis/shared/folder.html", - segment_list = segment_list, - segment_list_in_folder = segment_list_in_folder, - tpid = tpid, - username = username, - users = users, - users_assigned_refs = users_assigned_refs, - users_assigned_marks = users_assigned_marks, - folder_id = folder_id, - segments_position_code = segments_position_code - ) + return config.db.query_fetchall( sql, ( uuid, ) ) -@afis_view.route( "/admin/afis//add/segment", methods = [ "POST" ] ) -@utils.decorator.admin_required -def admin_add_segment_to_cnmfolder( folder_id ): - try: - fpc = request.form.get( "fpc" ) - - sql = "SELECT count( * ) AS nb FROM cnm_segments WHERE folder_uuid = %s AND fpc = %s" - nb = config.db.query_fetchone( sql, ( folder_id, fpc, ) )[ "nb" ] - - if nb == 0: - sql = utils.sql.sql_insert_generate( "cnm_segments", [ "uuid", "folder_uuid", "fpc" ], "uuid" ) - config.db.query_fetchone( sql, ( str( uuid4() ), folder_id, fpc, ) ) - config.db.commit() +def get_marks_list_for_target_folder( uuid, admin = True ): + if not admin: + sql = """ + SELECT count(*) AS count + FROM cnm_assignment + LEFT JOIN cnm_assignment_type ON cnm_assignment.assignment_type = cnm_assignment_type.id + WHERE + folder_uuid = %s AND + user_id = %s AND + cnm_assignment_type.name = 'mark' + """ + if config.db.query_fetchone( sql, ( uuid, session.get( "user_id", False ), ) )[ "count" ] == 0: + return None - return jsonify( { - "error": False - } ) - - except: - return jsonify( { - "error": True - } ) - -@afis_view.route( "/admin/afis//segment/" ) -@utils.decorator.admin_required -def admin_view_segment( folder_id, fpc ): - return view_segment_inner( folder_id, fpc, True ) - -@afis_view.route( "/afis//segment/" ) -@utils.decorator.login_required -def view_segment( folder_id, fpc ): - return view_segment_inner( folder_id, fpc, False ) - -def view_segment_mark_ref_anno_lists( folder_id, fpc, isadmin ): - mark_list = view_segment_mark_ref_anno_lists_marks( folder_id, fpc, isadmin ) - tenprints_list = view_segment_mark_ref_anno_lists_ref( folder_id, fpc, isadmin ) - annotations = view_segment_mark_ref_anno_lists_annotations( folder_id, fpc, isadmin ) - - return { - "mark_list": mark_list, - "tenprints_list": tenprints_list, - "annotations": annotations - } - -def view_segment_anno_list( folder_id, isadmin ): - annotations = view_segment_mark_ref_anno_lists_annotations( folder_id, "all", isadmin ) - - return { - "mark_list": [], - "tenprints_list": [], - "annotations": annotations - } - -def get_multi_img_fpc( fpc ): - multi_img_fpc = { - 1: [ 1, 11 ], - 2: [ 2, 13 ], - 3: [ 3, 13 ], - 4: [ 4, 13 ], - 5: [ 5, 13 ], - 6: [ 6, 12 ], - 7: [ 7, 14 ], - 8: [ 8, 14 ], - 9: [ 9, 14 ], - 10: [ 10, 14 ] - } - fpc = int( fpc ) - fpcs = multi_img_fpc.get( fpc, [ fpc ] ) - - return fpcs - -def view_segment_mark_ref_anno_lists_ref( folder_id, fpc, isadmin ): - fpcs = get_multi_img_fpc( fpc ) - - tmp_sql = [ "files_segments.pc = %s" ] * len( fpcs ) - tmp_sql = " OR ".join( tmp_sql ) - sql = """ SELECT - files_segments.tenprint, - files_segments.pc, - files_segments.uuid + files_v.uuid, + mark_info.pfsp FROM cnm_folder - INNER JOIN submissions ON cnm_folder.donor = submissions.uuid - INNER JOIN files ON submissions.id = files.folder - INNER JOIN files_segments ON files.uuid = files_segments.tenprint + LEFT JOIN submissions ON cnm_folder.donor_id = submissions.donor_id + LEFT JOIN files_v ON submissions.id = files_v.folder + LEFT JOIN files_type ON files_v.type = files_type.id + LEFT JOIN mark_info ON files_v.uuid = mark_info.uuid WHERE cnm_folder.uuid = %s AND - ( {} ) - ORDER BY pc ASC - """.format( tmp_sql ) - - data = [ folder_id, ] - data.extend( fpcs ) - tenprints_list = config.db.query_fetchall( sql, data ) - - if not isadmin: - sql = "SELECT count( * ) FROM cnm_folder_users WHERE user_id = %s AND folder_id = %s AND img_type = 1" - r = config.db.query_fetchone( sql, ( session.get( "user_id" ), folder_id, ) )[ "count" ] - if r == 0: - tenprints_list = [] + files_type.name = 'mark_target' + """ + return config.db.query_fetchall( sql, ( uuid, ) ) - return tenprints_list - -def view_segment_mark_ref_anno_lists_marks( folder_id, fpc, isadmin ): - fpcs = get_multi_img_fpc( fpc ) - +def get_annotation_list_for_target_folder( uuid, admin = True ): sql = """ - SELECT - files.id, - files.uuid - FROM files - INNER JOIN mark_info ON files.uuid = mark_info.uuid - INNER JOIN submissions ON files.folder = submissions.id - INNER JOIN cnm_folder ON submissions.uuid = cnm_folder.donor + SELECT uuid + FROM cnm_data + LEFT JOIN cnm_data_type ON cnm_data.type_id = cnm_data_type.id WHERE - cnm_folder.uuid = %s AND - ( files.type = 3 OR files.type = 4 ) + folder_uuid = %s AND + cnm_data_type.name = 'annotation' """ + return config.db.query_fetchall( sql, ( uuid, ) ) + +def show_folder_inner( uuid, admin ): + if not admin: + sql = "SELECT count(*) FROM cnm_assignment WHERE folder_uuid = %s AND user_id = %s" + if config.db.query_fetchone( sql, ( uuid, session.get( "user_id" ), ) )[ "count" ] == 0: + return redirect( url_for( "base.home" ) ) - sql_where = [] - for f in fpcs: - for q in fpc2pfsp[ f ]: - sql_where.append( "mark_info.pfsp LIKE '%%{}%%'".format( q ) ) - - if len( sql_where ) > 0: - sql += " AND ( {} )".format( " OR ".join( sql_where ) ) - - sql += " ORDER BY files.id ASC" + segments_list = get_segment_list_for_target_folder( uuid, admin ) + annotation_list = get_annotation_list_for_target_folder( uuid, admin ) + marks_list_tmp = get_marks_list_for_target_folder( uuid, admin ) - mark_list = config.db.query_fetchall( sql, ( folder_id, ) ) - - if not isadmin: - sql = "SELECT count( * ) FROM cnm_folder_users WHERE user_id = %s AND folder_id = %s AND img_type = 2" - r = config.db.query_fetchone( sql, ( session.get( "user_id" ), folder_id, ) )[ "count" ] - if r == 0: - mark_list = [] - - return mark_list - -def view_segment_mark_ref_anno_lists_annotations( folder_id, fpc, isadmin ): - sql = """ - SELECT - id, - uuid, - fpc - FROM cnm_annotation - WHERE folder = %s - """ - data = ( folder_id, ) + if admin: + sql = """ + SELECT + submissions.uuid, + cnm_folder.pc, + users.username + FROM cnm_folder + INNER JOIN submissions ON cnm_folder.donor_id = submissions.donor_id + INNER JOIN users ON cnm_folder.donor_id = users.id + WHERE cnm_folder.uuid = %s + """ + submission_id, pc, username = config.db.query_fetchone( sql, ( uuid, ) ) + finger_name = "{} (F{})".format( segments_position_code[ pc ], pc ) - if fpc != "all": - sql += " AND fpc = %s" - data = ( folder_id, fpc, ) + marks_list = [] + for m in marks_list_tmp: + for z in m[ "pfsp" ].split( "," ): + if pc in pfsp2fpc[ z ]: + marks_list.append( m ) - annotations = config.db.query_fetchall( sql, data ) + sql = """ + SELECT + users.id, + users.username + FROM users + LEFT JOIN account_type ON users.type = account_type.id + WHERE account_type.name = 'AFIS' + """ + all_afis_users = config.db.query_fetchall( sql ) + + def get_user_assined( assignment_type ): + sql = """ + SELECT + cnm_assignment.user_id AS id + FROM cnm_assignment + LEFT JOIN cnm_assignment_type ON cnm_assignment.assignment_type = cnm_assignment_type.id + WHERE + cnm_assignment.folder_uuid = %s AND + cnm_assignment_type.name = '{}' + """.format( assignment_type ) + return config.db.query_fetchall( sql, ( uuid, ) ) + + users_assigned_refs = get_user_assined( "reference" ) + users_assigned_marks = get_user_assined( "mark" ) - return annotations - -def view_segment_inner( folder_id, fpc, isadmin ): - d = view_segment_mark_ref_anno_lists( folder_id, fpc, isadmin ) - mark_list = d[ "mark_list" ] - tenprints_list = d[ "tenprints_list" ] - annotations = d[ "annotations" ] - - # Get the username of the donor - sql = """ - SELECT username - FROM users - INNER JOIN submissions ON users.id = submissions.donor_id - INNER JOIN cnm_folder ON submissions.uuid = cnm_folder.donor - WHERE cnm_folder.uuid = %s - """ - username = config.db.query_fetchone( sql, ( folder_id, ) )[ "username" ] + else: + submission_id = None + finger_name = None + username = None + all_afis_users = None + users_assigned_refs = [] + users_assigned_marks = [] - # return utils.template.my_render_template( "afis/shared/segment.html", - folder_id = folder_id, - fpc = fpc, - tenprints_list = tenprints_list, - len_tenprints_list = len( tenprints_list ), - mark_list = mark_list, - len_mark_list = len( mark_list ), + target_uuid = uuid, + segments_list = segments_list, + annotation_list = annotation_list, + marks_list = marks_list, + submission_id = submission_id, username = username, - annotations = annotations, - segments_position_code = segments_position_code + finger_name = finger_name, + all_afis_users = all_afis_users, + users_assigned_refs = users_assigned_refs, + users_assigned_marks = users_assigned_marks ) -@afis_view.route( "/admin/afis//segment//add/illustration", methods = [ "POST" ] ) +@afis_view.route( "/admin/target//new_illustration", methods = [ "POST" ] ) @utils.decorator.admin_required -def admin_add_illustration( folder_id, fpc ): +def admin_add_illustration( uuid ): try: sql = """ - SELECT donor + SELECT submissions.uuid FROM cnm_folder - WHERE uuid = %s + LEFT JOIN submissions ON cnm_folder.donor_id = submissions.donor_id + WHERE cnm_folder.uuid = %s """ - donor_uuid = config.db.query_fetchone( sql, ( folder_id, ) )[ "donor" ] - + donor_id = config.db.query_fetchone( sql, ( uuid, ) )[ "uuid" ] + + sql = "SELECT id FROM cnm_data_type WHERE name = 'annotation'" + annotation_type_id = config.db.query_fetchone( sql )[ "id" ] + uploaded_file = request.files[ "file" ] - + fp = StringIO() uploaded_file.save( fp ) fp.seek( 0 ) - + file_data = fp.getvalue() file_data = base64.b64encode( file_data ) - file_data = utils.encryption.do_encrypt_dek( file_data, donor_uuid ) + file_data = utils.encryption.do_encrypt_dek( file_data, donor_id ) - sql = utils.sql.sql_insert_generate( "cnm_annotation", [ "uuid", "folder", "fpc", "annotation_data" ], "id" ) - config.db.query_fetchone( sql, ( str( uuid4() ), folder_id, fpc, file_data, ) ) + sql = utils.sql.sql_insert_generate( + "cnm_data", + [ "uuid", "folder_uuid", "data", "type_id" ], + "id" + ) + data = ( str( uuid4() ), uuid, file_data, annotation_type_id, ) + config.db.query_fetchone( sql, data ) config.db.commit() - + return jsonify( { "error": False } ) except: return jsonify( { - "error": True + "error": False } ) -@afis_view.route( "/admin/afis//segment//remove/illustration", methods = [ "POST" ] ) +@afis_view.route( "/admin/target//target/annotation/delete", methods = [ "POST" ] ) @utils.decorator.admin_required -def admin_remove_illustration( folder_id, fpc ): +def admin_delete_annotation( folder_uuid ): try: illustration_uuid = request.form.get( "uuid" ) - sql = "DELETE FROM cnm_annotation WHERE folder = %s AND fpc = %s AND uuid = %s" - config.db.query( sql, ( folder_id, fpc, illustration_uuid, ) ) + sql = "DELETE FROM cnm_data WHERE folder_uuid = %s AND uuid = %s" + config.db.query( sql, ( folder_uuid, illustration_uuid, ) ) config.db.commit() - - return jsonify( { - "error": False - } ) - - except: - return jsonify( { - "error": True - } ) - -@afis_view.route( "/admin/afis//remove/segment", methods = [ "POST" ] ) -@utils.decorator.admin_required -def admin_remove_segment( folder_id ): - try: - fpc = request.form.get( "fpc" ) - sql = "DELETE FROM cnm_segments WHERE folder_uuid = %s AND fpc = %s" - config.db.query( sql, ( folder_id, fpc, ) ) - - sql = "DELETE FROM cnm_annotation WHERE folder = %s AND fpc = %s" - config.db.query( sql, ( folder_id, fpc, ) ) - config.db.commit() - return jsonify( { "error": False } ) - + except: return jsonify( { "error": True } ) -@afis_view.route( "//afis//annotation/" ) +@afis_view.route( "/afis//download" ) @utils.decorator.login_required -def get_annotation_image( folder_id, a_uuid, u_type = "afis" ): - img = get_annotation_image_inner( folder_id, a_uuid ) - buff = utils.images.pil2buffer( img, "PNG" ) - return send_file( buff, mimetype = "image/png" ) +def download_target_folder( uuid ): + short_uuid = uuid[ 0:18 ] + + annotation_list = get_annotation_list_for_target_folder( uuid, False ) + segments_list = get_segment_list_for_target_folder( uuid, False ) + marks_list = get_marks_list_for_target_folder( uuid, False ) + + zipbuffer = StringIO() + + with zipfile.ZipFile( zipbuffer, "w", zipfile.ZIP_DEFLATED ) as fp: + if isinstance( annotation_list, list ): + for fid in annotation_list: + file_id = fid[ "uuid" ] + short_file_id = file_id[ 0:18 ] + + submission_id = views.images.get_submission_uuid_for_annotation( file_id ) + + img, _ = views.images.image_serve( "cnm_data", file_id, submission_id ) + img = views.images.image_tatoo( img, file_id ) + + buff = utils.images.pil2buffer( img, "TIFF" ) + fp.writestr( + "{}_annotation_{}.tiff".format( short_uuid, short_file_id ), + buff.getvalue() + ) + + if isinstance( segments_list, list ): + for sid in segments_list: + file_id = sid[ "uuid" ] + short_file_id = file_id[ 0:18 ] + tenprint_id = sid[ "tenprint" ] + pc = sid[ "pc" ] + + submission_id = views.images.get_submission_uuid_for_file( tenprint_id ) + + img, _ = views.images.image_serve( "files_segments", ( tenprint_id, pc ), submission_id ) + img = views.images.image_tatoo( img, file_id ) + + buff = utils.images.pil2buffer( img, "TIFF" ) + fp.writestr( + "{}_reference_{}.tiff".format( short_uuid, short_file_id ), + buff.getvalue() + ) + + if isinstance( marks_list, list ): + for mid in marks_list: + file_id = mid[ "uuid" ] + short_file_id = file_id[ 0:18 ] + + submission_id = views.images.get_submission_uuid_for_file( file_id ) + img, _ = views.images.image_serve( "files", file_id, submission_id ) + img = views.images.image_tatoo( img, file_id ) + + buff = utils.images.pil2buffer( img, "TIFF" ) + fp.writestr( + "{}_mark_{}.tiff".format( short_uuid, short_file_id ), + buff.getvalue() + ) + + zipbuffer.seek( 0 ) + + return send_file( + zipbuffer, + attachment_filename = "{}.zip".format( short_uuid ), + as_attachment = True + ) -def get_annotation_image_inner( folder_id, a_uuid ): - sql = "SELECT donor FROM cnm_folder WHERE uuid = %s" - donor_uuid = config.db.query_fetchone( sql, ( folder_id, ) )[ "donor" ] +@afis_view.route( "/afis//upload/list" ) +def upload_cnm_list_page( uuid ): + sql = """ + SELECT uuid + FROM cnm_result + WHERE + cnm_folder = %s AND + uploader = %s + """ + cnm_result_list = config.db.query_fetchall( sql, ( uuid, session.get( "user_id" ), ) ) + return utils.template.my_render_template( + "afis/user/upload_cnm_list.html", + cnm_result_list = cnm_result_list, + ) + +@afis_view.route( "/admin//target/list" ) +@utils.decorator.admin_required +def admin_show_target_list( uuid ): sql = """ - SELECT annotation_data - FROM cnm_annotation - WHERE uuid = %s + SELECT DISTINCT ON ( donor_segments_v.pc ) + donor_segments_v.*, + cnm_folder.uuid AS folder_uuid + FROM donor_segments_v + LEFT JOIN submissions ON submissions.donor_id = donor_segments_v.donor_id + LEFT JOIN cnm_folder ON + donor_segments_v.donor_id = cnm_folder.donor_id AND + donor_segments_v.pc = cnm_folder.pc + WHERE submissions.uuid = %s """ - data = config.db.query_fetchone( sql, ( a_uuid, ) )[ "annotation_data" ] + segments_list = config.db.query_fetchall( sql, ( uuid, ) ) - data = utils.encryption.do_decrypt_dek( data, donor_uuid ) - img = base64.b64decode( data ) + sql = """ + SELECT + cnm_folder.pc + FROM submissions + LEFT JOIN cnm_folder ON submissions.donor_id = cnm_folder.donor_id + LEFT JOIN cnm_data ON cnm_folder.uuid = cnm_data.folder_uuid + LEFT JOIN cnm_data_type ON cnm_data.type_id = cnm_data_type.id + WHERE + submissions.uuid = %s AND + cnm_data_type.name = 'annotation' + GROUP BY pc + """ + annotations = config.db.query_fetchall( sql, ( uuid, ) ) + annotations = [ a[ 'pc' ] for a in annotations ] - buff = StringIO() - buff.write( img ) - buff.seek( 0 ) + sql = """ + SELECT username + FROM users + LEFT JOIN submissions ON users.id = submissions.donor_id + WHERE submissions.uuid = %s + """ + username = config.db.query_fetchone( sql, ( uuid, ) )[ "username" ] - return Image.open( buff ) - -@afis_view.route( "/admin/afis//user/update", methods = [ "POST" ] ) + return utils.template.my_render_template( + "afis/admin/folder_list.html", + segments_list = segments_list, + annotations = annotations, + segments_position_code = segments_position_code, + username = username, + submission_uuid = uuid + ) + +@afis_view.route( "/admin/afis//user/update", methods = [ "POST" ] ) @utils.decorator.admin_required -def admin_update_users_in_afis_folder( folder_id ): +def admin_update_users_in_afis_folder( target_uuid ): try: users = request.form.get( "users" ) users = json.loads( users ) - if request.form.get( "type" ) == "ref": - img_type = 1 - else: - img_type = 2 - sql = "DELETE FROM cnm_folder_users WHERE folder_id = %s AND img_type = %s" - config.db.query( sql, ( folder_id, img_type, ) ) + assignment_type = request.form.get( "type" ) + sql = "SELECT id FROM cnm_assignment_type WHERE name = %s" + assignment_type_id = config.db.query_fetchone( sql, ( assignment_type, ) )[ "id" ] - sql = utils.sql.sql_insert_generate( "cnm_folder_users", [ "user_id", "folder_id", "img_type" ], "id" ) + sql = """ + DELETE FROM cnm_assignment + WHERE + folder_uuid = %s AND + assignment_type = %s + """ + config.db.query( sql, ( target_uuid, assignment_type_id, ) ) + + sql = utils.sql.sql_insert_generate( + "cnm_assignment", + [ "folder_uuid", "user_id", "assignment_type" ], + "id" + ) for user in users: - config.db.query_fetchone( sql, ( user, folder_id, img_type, ) ) - + config.db.query_fetchone( sql, ( target_uuid, user, assignment_type_id, ) ) + config.db.commit() - + return jsonify( { "error": False } ) + except: return jsonify( { "error": True } ) - - return jsonify( view_segment_mark_ref_anno_lists( folder_id, fpc, False ) ) - -@afis_view.route( "/afis//download/" ) -@utils.decorator.login_required -def download_folder_afis( folder_id, fpc ): - return download_folder_inner( folder_id, fpc, False ) - -@afis_view.route( "/admin/afis//download/" ) -@utils.decorator.login_required -def download_folder_admin( folder_id, fpc ): - return download_folder_inner( folder_id, fpc, True ) - -def download_folder_inner( folder_id, fpc, isadmin ): - if fpc == "all": - lst = view_segment_anno_list( folder_id, isadmin ) - else: - lst = view_segment_mark_ref_anno_lists( folder_id, fpc, isadmin ) - - zipbuffer = StringIO() - - with zipfile.ZipFile( zipbuffer, "w", zipfile.ZIP_DEFLATED ) as fp: - for fid in lst[ "mark_list" ]: - file_id = fid[ "uuid" ] - submission_id = views.images.get_submission_uuid_for_file( file_id ) - img, _ = views.images.image_serve( "files", file_id, submission_id ) - img = views.images.image_tatoo( img, file_id ) - buff = utils.images.pil2buffer( img, "TIFF" ) - - fp.writestr( "mark_{}.tiff".format( file_id ), buff.getvalue() ) - - for fid in lst[ "tenprints_list" ]: - file_id = fid[ "tenprint" ] - pc = fid[ "pc" ] - submission_id = views.images.get_submission_uuid_for_file( file_id ) - img, _ = views.images.image_serve( "files_segments", ( file_id, pc ), submission_id ) - img = views.images.image_tatoo( img, file_id ) - buff = utils.images.pil2buffer( img, "TIFF" ) - - fp.writestr( "reference_{}.tiff".format( file_id ), buff.getvalue() ) - - for fid in lst[ "annotations" ]: - file_id = fid[ "uuid" ] - fpc = fid[ "fpc" ] - img = get_annotation_image_inner( folder_id, file_id ) - img = views.images.image_tatoo( img, file_id ) - buff = utils.images.pil2buffer( img, "PNG" ) - - fp.writestr( "annotation_finger{}_{}.png".format( fpc, file_id ), buff.getvalue() ) - zipbuffer.seek( 0 ) - - return send_file( zipbuffer, attachment_filename = "{}.zip".format( folder_id ), as_attachment = True ) - diff --git a/views/afis/templates/afis/admin/folder_list.html b/views/afis/templates/afis/admin/folder_list.html new file mode 100644 index 0000000000000000000000000000000000000000..ae32e30752bffcfbef6c1913133e4002a356c7ee --- /dev/null +++ b/views/afis/templates/afis/admin/folder_list.html @@ -0,0 +1,179 @@ +{% import "jinja_functions.html" as common %} + + + + + {% for src in js %} + + {% endfor %} + {% for src in css %} + + {% endfor %} + + {% autoescape false %} + {{ app_files }} + {% endautoescape %} + + + + + + + {% include "header.html" %} + {% include navigation %} + +
+
+
+
+ {% for n in [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] %} +
+
{{ segments_position_code.get( n ) }} (F{{ n }})
+
+
+ segment not available + {{ common.checked_question( "segment_" + n|e + "_checked_error" ) }} +
+
+
+ {% endfor %} +
+
+
+
+
+ {% for n in [ 24, 27, 25, 22 ] %} +
+
{{ segments_position_code.get( n ) }} (F{{ n }})
+
+
+ segment not available + {{ common.checked_question( "segment_" + n|e + "_checked_error" ) }} +
+
+
+ {% endfor %} +
+
+
+
+
+
+ + + + + diff --git a/views/afis/templates/afis/shared/segment.html b/views/afis/templates/afis/shared/segment.html index 17323d07a6571e30c831cce6c25141f814f04e26..4f45c984bc263878288098180fd7799222784970 100644 --- a/views/afis/templates/afis/shared/segment.html +++ b/views/afis/templates/afis/shared/segment.html @@ -5,6 +5,95 @@ {{ app_files }} {% endautoescape %} + + - - + .list_of_assignee { + display: grid; + grid-template-columns: auto 1fr; + grid-gap: 3px 20px; + margin-bottom: 30px; + } + .icnml_download_target_buttons { + width: fit-content; + width: -moz-fit-content; + margin-top: 30px; + margin-left: auto; + margin-right: auto; + } + .icnml_buttons_list { + display: grid; + grid-template-columns: repeat( 2, 1fr ); + grid-gap: 10px; + margin: 20px; + } + .icnml_button { + height: 120px; + width: 120px; + padding: 0px; + } + .icnml_button > span { + height: 120px; + width: 120px; + line-height: 120px; + vertical-align: center; + text-align: center; + } + {% include "header.html" %} {% include navigation %}
- -
-
Annotation illustration PiAnoS ({{ annotations|length }})
-
- {% for a in annotations %} -
-
{{ a[ 'uuid' ][ 0:18 ] }}
-
- {% if admin %} -
-
- {% else %} + {% if not admin %} + + {% endif %} + + {% if admin %} +
+
Marks
+
+ +
+
References
+
+ +
+
+ {% endif %} + + {% if annotation_list != None %} +
+
Target annotations ({{ annotation_list|length }})
+
+ {% for s in annotation_list %} +
+
{{ s[ 'uuid' ][ 0:18 ] }}
+
+ style="background-image: url( {{ url_for( 'image.image_annotation_serve', uuid = s[ 'uuid' ] ) }} )">
- {% endif %} +
-
- {% endfor %} - {% if admin %} -
-
Add illustration
-
-
-
+ {% endfor %} + + {% if admin %} +
+
Add illustration
+
+
+
+
-
- {% endif %} + {% endif %} +
-
- {% if tenprints_list|length > 0 %} + {% else %} +
No annotations for this finger at the moment
+ {% endif %} + + {% if segments_list != None %}
-
Tenprint ({{ tenprints_list|length }})
+
Non annotated images ({{ segments_list|length }})
- {% for tenprint in tenprints_list %} -
-
{{ tenprint[ 'uuid' ][ 0:18 ] }}
+ {% for s in segments_list %} +
+
{{ s[ 'uuid' ][ 0:18 ] }}
+ style="background-image: url( {{ url_for( 'image.image_segment_serve', tenprint_id = s[ 'tenprint' ], pc = s[ 'pc' ] ) }} )">
{% endfor %}
+ {% elif admin %} +
No segment images in this folder at the moment
{% endif %} - {% if mark_list|length > 0 %} + + {% if marks_list != None %}
-
Marks ({{ mark_list|length }})
+
Marks ({{ marks_list|length }})
- {% for mark in mark_list %} -
-
Mark {{ mark[ 'id' ] }}
+ {% for mark in marks_list %} +
+
{{ mark[ 'uuid' ][ 0:18 ] }}
@@ -149,20 +266,64 @@ {% endfor %}
+ {% elif admin %} +
No mark images in this folder at the moment
{% endif %} +
- + diff --git a/views/afis/templates/afis/user/folder_list.html b/views/afis/templates/afis/user/folder_list.html new file mode 100644 index 0000000000000000000000000000000000000000..83c40029ce26a0858646ad4b498402b5826f5e47 --- /dev/null +++ b/views/afis/templates/afis/user/folder_list.html @@ -0,0 +1,106 @@ + + + + {% for src in js %} + + {% endfor %} + {% for src in css %} + + {% endfor %} + + {% autoescape false %} + {{ app_files }} + {% endautoescape %} + + + + + + + {% include "header.html" %} + {% include navigation %} + +
+ + +
+ {% for f in folder_list %} +
+
{{ f[ 'folder_uuid' ][ 0:18 ] }}
+
+
+
+
+
+ {% endfor %} +
+
+
+ + + + diff --git a/views/afis/templates/afis/user/upload_cnm_list.html b/views/afis/templates/afis/user/upload_cnm_list.html new file mode 100644 index 0000000000000000000000000000000000000000..64c72e8dfedf67301854fe89ac644aa05f32185a --- /dev/null +++ b/views/afis/templates/afis/user/upload_cnm_list.html @@ -0,0 +1,69 @@ + + + + {% for src in js %} + + {% endfor %} + {% for src in css %} + + {% endfor %} + + {% autoescape false %} + {{ app_files }} + {% endautoescape %} + + + + + + + {% include "header.html" %} + {% include navigation %} + +
+ + + {% if cnm_result_list != None %} +
+ {% for result in cnm_result_list %} + {{ result[ 'uuid' ] }} + {% endfor %} +
+ {% else %} + nothing uploaded for this target at the moment... + {% endif %} +
+
+ + + + diff --git a/views/images/__init__.py b/views/images/__init__.py index b7b92c1b81ea394baa5546b7e66f9eb086a25a59..e11bd9d8eade2732561ca82e8725c70a27efa7cb 100644 --- a/views/images/__init__.py +++ b/views/images/__init__.py @@ -39,6 +39,16 @@ def get_submission_uuid_for_file( file_uuid ): """ return config.db.query_fetchone( sql, ( file_uuid, ) )[ "uuid" ] +def get_submission_uuid_for_annotation( file_uuid ): + sql = """ + SELECT submissions.uuid + FROM submissions + LEFT JOIN cnm_folder ON submissions.donor_id = cnm_folder.donor_id + LEFT JOIN cnm_data ON cnm_data.folder_uuid = cnm_folder.uuid + WHERE cnm_data.uuid = %s + """ + return config.db.query_fetchone( sql, ( file_uuid, ) )[ "uuid" ] + @image_view.route( "/image/file//preview" ) @image_view.route( "/image/file/preview" ) @utils.decorator.login_required @@ -145,6 +155,16 @@ def image_segment_serve( tenprint_id, pc ): current_app.logger.error( "Error while creating the thumbnail. Serving a 'no preview' image" ) return send_file( no_preview_image(), mimetype = "image/png" ) +@image_view.route( "/image/annotation/" ) +def image_annotation_serve( uuid ): + submission_id = get_submission_uuid_for_annotation( uuid ) + + img, _ = image_serve( "cnm_data", uuid, submission_id ) + img = utils.images.create_thumbnail( None, img, submission_id ) + + buff = utils.images.pil2buffer( img, "PNG" ) + return send_file( buff, mimetype = "image/png" ) + def image_serve( table, image_id, submission_id ): """ Backend function to get the image from the database. @@ -176,6 +196,10 @@ def image_serve( table, image_id, submission_id ): p = ( image_id, ) need_to_decrypt = False + elif table == "cnm_data": + sql = "SELECT data, uuid FROM {} WHERE uuid = %s".format( table ) + p = ( image_id, ) + else: current_app.logger.error( "table '{}' not authorized".format( table ) ) raise Exception( "table not authorized" ) diff --git a/views/submission/__init__.py b/views/submission/__init__.py index af92fc719646f58b98785594b75cf13c06cd33a1..356760160b390452b25cea21fba2ae3d29f6d05e 100644 --- a/views/submission/__init__.py +++ b/views/submission/__init__.py @@ -2,11 +2,12 @@ # -*- coding: UTF-8 -*- from flask import Blueprint -from flask import current_app, request, jsonify, session, url_for, redirect, abort +from flask import current_app, request, jsonify, session, url_for, redirect, abort, send_file import base64 import hashlib import json +import zipfile from uuid import uuid4 from cStringIO import StringIO @@ -1083,26 +1084,23 @@ def donor_marks_annotations( submission_id ): sql = """ SELECT - cnm_annotation.id, - cnm_annotation.uuid, - cnm_annotation.fpc - FROM cnm_annotation - INNER JOIN cnm_folder ON cnm_annotation.folder = cnm_folder.uuid - WHERE cnm_folder.donor = %s - ORDER BY cnm_annotation.fpc ASC + cnm_data.id, + cnm_data.uuid, + cnm_folder.pc AS fpc + FROM cnm_data + LEFT JOIN cnm_folder ON cnm_data.folder_uuid = cnm_folder.uuid + LEFT JOIN submissions ON cnm_folder.donor_id = submissions.donor_id + LEFT JOIN cnm_data_type ON cnm_data.type_id = cnm_data_type.id + WHERE + submissions.uuid = %s AND + cnm_data_type.name = 'annotation' + ORDER BY cnm_folder.pc ASC """ annotations = config.db.query_fetchall( sql, ( submission_id, ) ) - sql = "SELECT uuid FROM cnm_folder WHERE donor = %s" - try: - folder_id = config.db.query_fetchone( sql, ( submission_id, ) )[ "uuid" ] - except: - folder_id = None - return utils.template.my_render_template( "submission/user/target.html", submission_id = submission_id, - folder_id = folder_id, nickname = nickname, annotations = annotations, segments_position_code = segments_position_code @@ -2431,3 +2429,47 @@ def submission_mark_inner( submission_id, mark_id, admin = False ): admin = admin ) +@submission_view.route( "/submission//targets/download" ) +def download_target_folder( submission_uuid ): + sql = """ + SELECT + cnm_data.uuid, + cnm_folder.pc AS fpc + FROM cnm_data + LEFT JOIN cnm_folder ON cnm_data.folder_uuid = cnm_folder.uuid + LEFT JOIN submissions ON cnm_folder.donor_id = submissions.donor_id + LEFT JOIN cnm_data_type ON cnm_data.type_id = cnm_data_type.id + WHERE + submissions.uuid = %s AND + cnm_data_type.name = 'annotation' + ORDER BY cnm_folder.pc ASC + """ + annotations = config.db.query_fetchall( sql, ( submission_uuid, ) ) + + zipbuffer = StringIO() + + with zipfile.ZipFile( zipbuffer, "w", zipfile.ZIP_DEFLATED ) as fp: + for fid in annotations: + file_id, fpc = fid + finger_name = segments_position_code[ fpc ] + finger_name = finger_name.replace( " ", "_" ) + + submission_id = views.images.get_submission_uuid_for_annotation( file_id ) + + img, _ = views.images.image_serve( "cnm_data", file_id, submission_id ) + img = views.images.image_tatoo( img, file_id ) + + buff = utils.images.pil2buffer( img, "TIFF" ) + fp.writestr( + "finger_{}_{}_annotation_{}.tiff".format( fpc, finger_name, file_id ), + buff.getvalue() + ) + + zipbuffer.seek( 0 ) + + return send_file( + zipbuffer, + attachment_filename = "{}.zip".format( submission_uuid ), + as_attachment = True + ) + diff --git a/views/submission/templates/submission/admin/submission_home.html b/views/submission/templates/submission/admin/submission_home.html index 7106b5d3bb36c4dab051b368eb9e478c4aafccb2..b075f6c75756b5c34e9adbdb5f2eae6d20718211 100644 --- a/views/submission/templates/submission/admin/submission_home.html +++ b/views/submission/templates/submission/admin/submission_home.html @@ -17,7 +17,7 @@ } .icnml_buttons_list { display: grid; - grid-template-columns: repeat( 4, 1fr ); + grid-template-columns: repeat( 5, 1fr ); grid-gap: 10px; margin: 20px; } @@ -61,6 +61,11 @@ {{ common.checked_exclamation( "tenprint_checked_error" ) }}
+
Mark(s) target @@ -235,6 +240,11 @@ window.location = "{{ url_for( 'submission.admin_submission_mark_list', submission_id = submission[ 'uuid' ], mark_type = 'incidental' ) }}"; } ); + $( "#target_button" ).on( "click", function() + { + window.location = "{{ url_for( 'afis.admin_show_target_list', uuid = submission[ 'uuid' ] ) }}"; + } ); + $( "#submission_uuid" ).on( "click", function() { $( "#submission_uuid" ).select(); diff --git a/views/submission/templates/submission/user/target.html b/views/submission/templates/submission/user/target.html index dbacb821a7862642ee2021f32fbf70878da7de10..4f7a6e6353a2d48c204f6152ba767d604c070e6f 100644 --- a/views/submission/templates/submission/user/target.html +++ b/views/submission/templates/submission/user/target.html @@ -41,14 +41,14 @@ {% include navigation %}
- {% if folder_id != None %} + {% if annotations != None %}
-
Annotation illustration PiAnoS ({{ annotations|length }})
+
Target annotated images ({{ annotations|length }})
{% for a in annotations %}
@@ -57,7 +57,7 @@
+ style="background-image: url( {{ url_for( 'image.image_annotation_serve', uuid = a[ 'uuid' ] ) }} )">
@@ -70,12 +70,10 @@