diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..f8e32ba5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "flask/bin/python2.7" +} \ No newline at end of file diff --git a/app/.DS_Store b/app/.DS_Store index 92adfbbe..654abdea 100644 Binary files a/app/.DS_Store and b/app/.DS_Store differ diff --git a/app/__init__.pyc b/app/__init__.pyc index e7507163..09267e35 100644 Binary files a/app/__init__.pyc and b/app/__init__.pyc differ diff --git a/app/adminutils.pyc b/app/adminutils.pyc index f461d543..feaf2e80 100644 Binary files a/app/adminutils.pyc and b/app/adminutils.pyc differ diff --git a/app/api.pyc b/app/api.pyc index d7cf8c80..fa85ce66 100644 Binary files a/app/api.pyc and b/app/api.pyc differ diff --git a/app/app_configuration.pyc b/app/app_configuration.pyc index 4493fb3f..271e7ef2 100644 Binary files a/app/app_configuration.pyc and b/app/app_configuration.pyc differ diff --git a/app/models/__init__.pyc b/app/models/__init__.pyc index fac223bf..18852007 100644 Binary files a/app/models/__init__.pyc and b/app/models/__init__.pyc differ diff --git a/app/models/models.py b/app/models/models.py index b7c9ac0e..5ace357c 100644 --- a/app/models/models.py +++ b/app/models/models.py @@ -226,6 +226,7 @@ class Project(db.Model): is_removed = db.Column(db.String(255)) description = db.Column(db.Text()) timestamp = db.Column(db.DateTime) + last_update_timestamp = db.Column(db.DateTime) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) pipelines = db.relationship('Pipeline', backref='project', lazy='dynamic') strains = db.relationship('Strain', secondary=projects_strains, @@ -376,6 +377,8 @@ class Strain(db.Model): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(255), unique=True) timestamp = db.Column(db.DateTime) + update_timestamp = db.Column(db.DateTime) + delete_timestamp = db.Column(db.DateTime) strain_metadata = db.Column(JSON) fields = db.Column(JSON) species_id = db.Column(db.Integer, db.ForeignKey('species.id')) diff --git a/app/models/models.pyc b/app/models/models.pyc index c7c6e7e2..1b6a7e4c 100644 Binary files a/app/models/models.pyc and b/app/models/models.pyc differ diff --git a/app/resources/__init__.pyc b/app/resources/__init__.pyc index ab246e62..9dccc336 100644 Binary files a/app/resources/__init__.pyc and b/app/resources/__init__.pyc differ diff --git a/app/resources/jobs/checks.py b/app/resources/jobs/checks.py index 46856ec4..65c75fe0 100644 --- a/app/resources/jobs/checks.py +++ b/app/resources/jobs/checks.py @@ -53,6 +53,7 @@ def get(self): print e return False + return True diff --git a/app/resources/postgres/projects.py b/app/resources/postgres/projects.py index fa8cc274..818fddfc 100644 --- a/app/resources/postgres/projects.py +++ b/app/resources/postgres/projects.py @@ -48,7 +48,9 @@ 'uri': fields.Url('user_single_project', absolute=True), 'species_id': fields.String, 'is_removed': fields.String, - 'username': fields.String + 'username': fields.String, + 'number_strains_change': fields.Integer, + 'strains_expire': fields.List(fields.String) } project_fields = { @@ -303,6 +305,16 @@ def get(self, id): .filter(project.user_id == User.id).first() project.username = user.username + count = 0 + project.strains_expire = [] + + + for strain in project.strains: + if strain.delete_timestamp != None: + if strain.delete_timestamp > project.timestamp: + count+=1 + project.strains_expire.append(strain.name) + project.number_strains_change = count return projects, 200 diff --git a/app/resources/postgres/strains.py b/app/resources/postgres/strains.py index 517a15bf..11cf6d0c 100644 --- a/app/resources/postgres/strains.py +++ b/app/resources/postgres/strains.py @@ -12,6 +12,7 @@ # Defining post arguments parser + strain_project_parser = reqparse.RequestParser() strain_project_parser.add_argument('strainID', dest='strainID', type=str, required=False, help="Strain identifier") @@ -60,7 +61,10 @@ 'classifier': fields.String, 'fq_location': fields.String, 'has_files': fields.String, - 'Accession': fields.String + 'Accession': fields.String, + 'delete_timestamp': fields.String, + 'update_timestamp': fields.String, + 'strainsIDs': fields.List(fields.String) } strain_fields_project = { @@ -160,6 +164,14 @@ def get(self): else: strains = db.session.query(Strain).all() + strains_aux = list(strains) + + for strain in strains: + if strain.delete_timestamp != None: + strains_aux.remove(strain) + + strains = strains_aux + for strain in strains: strain.file_1 = json.loads(strain.strain_metadata)["File_1"] strain.file_2 = json.loads(strain.strain_metadata)["File_2"] @@ -288,11 +300,72 @@ def put(self): for key, val in args.iteritems(): strain_metadata[key] = val + if "Accession" in args: + + metadata = json.loads(strain.strain_metadata) + + if metadata["Accession"] != args["Accession"]: + + strain_specie_name = database_correspondece.keys()[strain.species_id - 1] + + strain_specie = database_correspondece[strain_specie_name] + + result = db.session.query(strain_specie).filter(strain_specie.strain_metadata['strainID'].astext == metadata["Accession"]).first() + + if not result: + abort(404, message="An error as occurried") + + strain.update_timestamp = datetime.datetime.utcnow() + strain.strain_metadata = json.dumps(strain_metadata) + db.session.commit() return strain, 201 + @login_required + @marshal_with(strain_fields) + def delete(self): + """Remove strain + + This method allows removing a strain. Requires the + strain name and the project id. + + Parameters + ---------- + id: str + project identifier + + Returns + ------- + + """ + + + args = request.data + + obj = json.loads(args) + + strains_ids = list(obj.values())[0] + + if not current_user.is_authenticated: + abort(403, message="No permissions") + + for strainId in strains_ids: + strain = db.session.query(Strain).filter(Strain.id == strainId).first() + + if not strain: + abort(404, message="No strain available") + + if strain.user_id != current_user.id: + abort(404, message="No permissions") + + strain.delete_timestamp = datetime.datetime.utcnow() + + db.session.commit() + + return 200 + class StrainsByNameResource(Resource): """ diff --git a/app/static/.DS_Store b/app/static/.DS_Store index dc952784..ada48f3f 100644 Binary files a/app/static/.DS_Store and b/app/static/.DS_Store differ diff --git a/app/static/controllers/js_objects/metadata.js b/app/static/controllers/js_objects/metadata.js index 0d4b51ee..fb2bd837 100644 --- a/app/static/controllers/js_objects/metadata.js +++ b/app/static/controllers/js_objects/metadata.js @@ -50,7 +50,8 @@ const Metadata = () => { "Project Name":"project_name", "Classifier":"classifier", "Accession": "Accession", - "Timestamp":"timestamp" + "Timestamp":"timestamp", + "Strain_State":"Strain_State" }; //Conversion from the metadata fields stored in the db to how we want to see them on a table (Reverse) @@ -76,18 +77,19 @@ const Metadata = () => { "project_name": "Project Name", "classifier": "Classifier", "Accession": "Accession", - "timestamp": "Timestamp" + "timestamp": "Timestamp", + "Strain_State":"Strain_State" }; //The minimum headers to be seen on a table const minimal_headers = [ "Strain Name", "Received Date", "Source", "Additional Info", "File 1", "Primary", "Sampling Date", "Owner", "Case ID", "Submitter", "File 2", - "Location", "Accession", "Timestamp"]; + "Location", "Accession", "Timestamp", "Strain_State"]; const default_headers = [ - "Strain Name", "Received Date", "Source", "Sampling Date", "Location", - "Sample", "Run Identifier", "Project Name", "Classifier", "Accession", "Timestamp"]; + "Strain Name", "Received Date", "Source", "Sampling Date", "Location","Owner", + "Sample", "Run Identifier", "Project Name", "Classifier", "Accession", "Timestamp","Strain_State"]; return { diff --git a/app/static/controllers/js_objects/objects_utils.js b/app/static/controllers/js_objects/objects_utils.js index 74186200..596dbb41 100644 --- a/app/static/controllers/js_objects/objects_utils.js +++ b/app/static/controllers/js_objects/objects_utils.js @@ -53,7 +53,11 @@ const Objects_Utils = (single_project, $sc) => { const format_analysis = (d, table_id) => { // `d` is the original data object for the row - $("#" + d.strainID + "_table").remove(); + + let strain_id = d.strainID; + strain_id = strain_id.replace(/(.*?) { } if (table_id === "modify_strains_table" || table_id === "reports_trees_table") { - selection_style = "single"; + //selection_style = "single"; + selection_style = "multi"; } else { selection_style = "multi"; @@ -745,7 +750,7 @@ const Objects_Utils = (single_project, $sc) => { $("#" + table_id + " thead").append(create_table_headers(table_headers, has_analysis, table_id)); $("#" + table_id + " tfoot > tr").remove(); - $("#" + table_id + " tfoot").append(create_table_headers(table_headers, has_analysis, table_id)); + //$("#" + table_id + " tfoot").append(create_table_headers(table_headers, has_analysis, table_id)); callback(); diff --git a/app/static/controllers/js_objects/projects_table.js b/app/static/controllers/js_objects/projects_table.js index 1fca281d..da2969f9 100644 --- a/app/static/controllers/js_objects/projects_table.js +++ b/app/static/controllers/js_objects/projects_table.js @@ -102,13 +102,25 @@ const Projects_Table = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http) => { ' fa-unlock">'; } + if(d.number_strains_change > 0) + { + icon = ""; + d.Project_State= icon + " - Outdated "; + + }else{ + icon = ""; + d.Project_State= icon + " - Up-to-date "; + } + + other_projects.push({ name: d.name, description: d.description, date: d.timestamp.split(" ").slice(0, 4).join(' '), id: d.id, username: d.username, - lockStatus: lockStatus + lockStatus: lockStatus, + Project_State:d.Project_State }); } }); @@ -138,13 +150,32 @@ const Projects_Table = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http) => { ' fa-unlock">'; } + + let strain_ex = d.name; + if(d.number_strains_change > 0) + { + icon = ""; + d.Project_State= icon + " - Outdated "; + if(d.strains_expire.includes(d.name)) + { + + strain_ex += " " + ""; + } + }else{ + icon = ""; + d.Project_State= icon + " - Up-to-date "; + } + projects.push({ - name: d.name, + name: strain_ex, description: d.description, date: d.timestamp.split(" ").slice(0, 4).join(' '), id: d.id, username: d.username, - lockStatus: lockStatus + lockStatus: lockStatus, + number_strains_change: d.number_strains_change, + strains_expire: d.strains_expire, + Project_State:d.Project_State }); } }); @@ -180,13 +211,16 @@ const Projects_Table = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http) => { ' style="width:100%;text-align:center;">'; + let icon = ""; + projects.push({ name: response.data.name, description: response.data.description, date: response.data.timestamp.split(" ").slice(0, 4).join(' '), id: response.data.id, username: response.data.username, - lockStatus: lockStatus + lockStatus: lockStatus, + Project_State:icon+ " - Up-to-date " }); $('#newProjectModal').modal('hide'); diff --git a/app/static/controllers/js_objects/single_project.js b/app/static/controllers/js_objects/single_project.js index d4b30262..daad8102 100644 --- a/app/static/controllers/js_objects/single_project.js +++ b/app/static/controllers/js_objects/single_project.js @@ -206,8 +206,26 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => strains_headers = JSON.parse(data.fields).metadata_fields; strains_headers.push('Analysis'); strains_headers.push("timestamp"); + strains_headers.push("Strain_State"); + + const strain_data = JSON.parse(data.strain_metadata); + if(data.delete_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Removed "; + + strain_data["delete_timestamp"] = data[i].delete_timestamp; + }else if(data.update_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Uptated "; ; + strain_data["update_timestamp"] = data[i].update_timestamp; + }else{ + icon = ""; + strain_data["Strain_State"] = icon + " - No changed "; ; + } strain_data['Analysis'] = ""; strain_data["timestamp"] = data.timestamp; let sd = {}; @@ -710,6 +728,7 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => let public_strains_headers = JSON.parse(data[0].fields).metadata_fields; public_strains_headers.unshift("strainID"); public_strains_headers.push("timestamp"); + public_strains_headers.push("Strain_State"); for (const i in data) { @@ -721,6 +740,22 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => //strain_data["FilesLocation"] = data[i].fq_location; strain_data["timestamp"] = data[i].timestamp; + if(data[i].delete_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Removed "; + + strain_data["delete_timestamp"] = data[i].delete_timestamp; + }else if(data[i].update_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Uptated "; ; + strain_data["update_timestamp"] = data[i].update_timestamp; + }else{ + icon = ""; + strain_data["Strain_State"] = icon + " - No changed "; ; + } + let sd = {}; //Parse the metadata and add it to the public strains object for (const j in public_strains_headers) { @@ -804,13 +839,31 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => strains_headers.push("timestamp"); strains_headers.push("has_files"); strains_headers.push("Accession"); + strains_headers.push("Owner"); + strains_headers.push("Strain_State"); console.log(data); for (const i in data) { let strain_data = JSON.parse(data[i].strain_metadata); - strain_data["strainID"] = data[i].strainID; + strain_data["strainID"] = data[i].strainID ; + if(data[i].delete_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Removed "; + + strain_data["delete_timestamp"] = data[i].delete_timestamp; + }else if(data[i].update_timestamp != null) + { + icon = ""; + strain_data["Strain_State"] = icon + " - Uptated "; ; + strain_data["update_timestamp"] = data[i].update_timestamp; + }else{ + icon = ""; + strain_data["Strain_State"] = icon + " - No changed "; ; + } + strain_data['Analysis'] = ""; strain_data['FilesLocation'] = data[i].fq_location; strain_data['timestamp'] = data[i].timestamp; @@ -836,8 +889,13 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => else { sd[strains_headers[j]] = strain_data[strains_headers[j]]; } + + sd["delete_timestamp"] = strain_data["delete_timestamp"]; + sd["update_timestamp"] = strain_data["update_timestamp"]; } } + + if (!strains_dict.hasOwnProperty($.trim(data[i].strainID))) { strains_dict[$.trim(data[i].strainID)] = data[i].id; } @@ -846,6 +904,7 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => sd[s] = sd[s] !== "" ? sd[s] : "NA"; } + add_strains.push(sd); } @@ -1267,6 +1326,15 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => }); }, + /* + Remove strain metadata + */ + remove_metadata: (strain_id, callback) => { + pg_requests.remove_metadata(strain_id, (response) => { + callback(response); + }); + }, + /* Get nextflow logs */ @@ -1355,6 +1423,9 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => while (strain_names.length !== 0) { let strain_name = strain_names.pop(); + strain_name = strain_name.replace(/(.*?) { count_removed += 1; @@ -1691,6 +1762,14 @@ let Single_Project = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http, $rootScope) => return item['strainID']; }); + for(let i = 0; i< strain_names.length; i++) + { + let strain_id = strain_names[i]; + strain_id = strain_id.replace(/(.*?) return item['strainID']; }); + for(let i = 0; i< strain_names.length; i++) + { + let strain_id = strain_names[i]; + strain_id = strain_id.replace(/(.*?) return item['strainID']; }); + for(let i = 0; i< strain_names.length; i++) + { + let strain_id = strain_names[i]; + strain_id = strain_id.replace(/(.*?) { return item['FilesLocation']; }); diff --git a/app/static/controllers/modify_strains_controller.js b/app/static/controllers/modify_strains_controller.js index 668e9c3f..957de941 100644 --- a/app/static/controllers/modify_strains_controller.js +++ b/app/static/controllers/modify_strains_controller.js @@ -241,6 +241,47 @@ innuendoApp.controller("modifyStrainsCtrl", ($scope, $rootScope, $http) => { }; + $scope.deleteStrains = () => { + + currentSelections = []; + const strain_selected = $.map($('#modify_strains_table').DataTable().rows('.selected').data(), (item) => { + return item; + }); + + if (strain_selected.length === 0){ + modalAlert("Please select a strain first.", "Select Strains", () => { + + }); + currentSelected = []; + return; + } + else { + currentSelected = strain_selected; + } + + for (i = 0; i < currentSelected.length; i++) { + currentSelections.push(currentSelected[i].id); + } + + + + modalAlert("Do you want to remove the strains? " + + "Please note that you will not be able to affect further testing with these strains.", "Remove Strains!", () => { + removeMetadata(currentSelections); + + + }); + + //$('#modifyStrainModal').modal("show"); + + /*const updateMetadataEl = $('#update_metadata_button'); + + updateMetadataEl.off("click").on("click", () => { + console.log("AQUI"); + //updateMetadata(strain_id_in_use); + });*/ + }; + $scope.modifyStrains = () => { const strain_selected = $.map($('#modify_strains_table').DataTable().rows('.selected').data(), (item) => { @@ -264,8 +305,42 @@ innuendoApp.controller("modifyStrainsCtrl", ($scope, $rootScope, $http) => { $('#'+key).val(strain_selected[0][key]); } + if(strain_selected[0].Accession != undefined) + { + $('#file_selector_modify').val("accession"); + $('#file_selector_modify').attr('disabled', 'disabled'); + $("#div_file1").css({"display":"none"}); + $("#div_file2").css({"display":"none"}); + $("#div_accession").css({"display":"block"}); + }else if(strain_selected[0].File1 != undefined) + { + + $('#file_selector_modify').val("reads"); + $('#file_selector_modify').attr('disabled', 'disabled'); + $("#div_file1").css({"display":"block"}); + $("#div_file2").css({"display":"block"}); + $("#div_accession").css({"display":"none"}); + } + + /* $('#file_selector_modify').on("change", (e) => { + const currentValue = $(e.target).val(); + console.log($(e.target).val()); + if (currentValue === "reads"){ + $("#div_file1").css({"display":"block"}); + $("#div_file2").css({"display":"block"}); + $("#div_accession").css({"display":"none"}); + } + else if(currentValue === "accession"){ + $("#div_file1").css({"display":"none"}); + $("#div_file2").css({"display":"none"}); + $("#div_accession").css({"display":"block"}); + } + });*/ + $('#modifyStrainModal').modal("show"); + + /*const updateMetadataEl = $('#update_metadata_button'); updateMetadataEl.off("click").on("click", () => { @@ -281,6 +356,32 @@ innuendoApp.controller("modifyStrainsCtrl", ($scope, $rootScope, $http) => { const updateMetadata = (strain_id_in_use) => { single_project.update_metadata(strain_id_in_use, (response) => { + + single_project.get_strains(true, (strains_results) => { + objects_utils.destroyTable('modify_strains_table'); + global_public_strains = strains_results.public_strains; + let headers_defs = set_headers_metadata(global_public_strains); + + strains_headers = headers_defs[1]; + + objects_utils.restore_table_headers('modify_strains_table', strains_headers, false, () => { + objects_utils.loadDataTables('modify_strains_table', global_public_strains, headers_defs[0], strains_headers); + + // Remove selection from table + $("#modify_strains_table").DataTable().rows().deselect(); + + + modalAlert("Strains was update.", "Success!", () => { + + }); + }); + }); + }); + }; + + const removeMetadata = (strainsIds) => { + single_project.remove_metadata(strainsIds, (response) => { + single_project.get_strains(true, (strains_results) => { objects_utils.destroyTable('modify_strains_table'); global_public_strains = strains_results.public_strains; diff --git a/app/static/controllers/projects_controller.js b/app/static/controllers/projects_controller.js index 49bf8e9e..a7edfdc1 100644 --- a/app/static/controllers/projects_controller.js +++ b/app/static/controllers/projects_controller.js @@ -74,6 +74,7 @@ innuendoApp.controller("projectsCtrl", ($scope, $http) => { $("#user_tools").css({"display":"block"}); $("#species_drop_button_li").css({"display":"block"}); $("#overview_li").css({"display":"none"}); + $("#AlertStrainExpire").css({"display":"none"}); //Reset application to overview page. Allows to select a diferent species $("#reset_strain").on("click", () => { @@ -159,10 +160,11 @@ innuendoApp.controller("projectsCtrl", ($scope, $http) => { { "data": "name" }, { "data": "username" }, { "data": "description" }, - { "data": "date" } + { "data": "date" }, + { "data": "Project_State" } ]; - $scope.projects_headers = ['Lock Status','Name', 'Owner','Description', "Date"]; + $scope.projects_headers = ['Lock Status','Name', 'Owner','Description', "Date", "Project_State"]; let other_projects = []; @@ -181,8 +183,27 @@ innuendoApp.controller("projectsCtrl", ($scope, $http) => { projects_table.get_projects_from_species(CURRENT_SPECIES_ID, false, (results) => { projects = results; + projects.forEach(p => { + + let message = "There are " + p.number_strains_change + " strains that have been changed or removed. Please review the strains of the projects you intend to run."; + + if (p.number_strains_change > 0) + { + icon = ""; + p.Project_State= icon + " - Outdated "; + $("#AlertStrainExpire").css({"display":"block"}); + $("#AlertStrainExpire").text(message); + + }else{ + icon = ""; + p.Project_State= icon + " - Up-to-date "; + } + }); + + objects_utils.loadDataTables('projects_table', projects, project_col_defs); + //Get available projects for the selected species of the other users projects_table.get_projects_from_species(CURRENT_SPECIES_ID, true, (results) => { other_projects = results; @@ -259,6 +280,8 @@ innuendoApp.controller("projectsCtrl", ($scope, $http) => { $scope.selectedTemplate.path = results.template; }); + + }; $scope.LockProject = () => { @@ -270,6 +293,8 @@ innuendoApp.controller("projectsCtrl", ($scope, $http) => { modalAlert("Project Locked!", "Information", () => {}); }); }); + + } }); \ No newline at end of file diff --git a/app/static/controllers/requests/requests.js b/app/static/controllers/requests/requests.js index 7de5fc90..9039996c 100644 --- a/app/static/controllers/requests/requests.js +++ b/app/static/controllers/requests/requests.js @@ -958,6 +958,24 @@ const Requests = (CURRENT_PROJECT_ID, CURRENT_PROJECT, $http) => { callback(response); }); + }, + remove_metadata: (strain_ids, callback) => { + + const req = { + url: "api/v1.0/strains/", + method: "DELETE", + data: { + "strainsIds": strain_ids + } + }; + + $http(req).then((response) => { + callback(response); + }, + (response) => { + callback(response); + }); + }, remove_strain_from_project: (strain_name, callback) => { diff --git a/app/static/controllers/single_project_controller.js b/app/static/controllers/single_project_controller.js index e35f7ef4..954cffd7 100644 --- a/app/static/controllers/single_project_controller.js +++ b/app/static/controllers/single_project_controller.js @@ -78,11 +78,11 @@ const set_headers_single_project = (table_id, global_strains) => { { "data": "File_1", "visible":false }, { "data": "Primary" , "visible":false}, { "data": "SamplingDate" }, - { "data": "Owner", "visible":false }, + { "data": "Owner", "visible":true }, { "data": "Food-Bug", "visible":false }, { "data": "Submitter", "visible":false }, { "data": "File_2", "visible":false }, - { "data": "Location" }, + { "data": "Location" ,"visible":false}, { "data": "Accession" }, { "data": "timestamp" } @@ -108,13 +108,14 @@ const set_headers_single_project = (table_id, global_strains) => { { "data": "File_1", "visible":false }, { "data": "Primary" , "visible":false}, { "data": "SamplingDate" }, - { "data": "Owner", "visible":false }, + { "data": "Owner","visible":true }, { "data": "Food-Bug", "visible":false }, { "data": "Submitter", "visible":false }, { "data": "File_2", "visible":false }, - { "data": "Location" }, + { "data": "Location", "visible":false}, { "data": "Accession" }, - { "data": "timestamp" }, + { "data": "timestamp" }, + { "data": "Strain_State" }, { "className": 'details-control', "orderable": false, @@ -153,7 +154,12 @@ const set_headers_single_project = (table_id, global_strains) => { p_col_defs.push({"data":x, "className": 'strain_cell'}); } else { - p_col_defs.push({"data":x}); + if(x==="Location") + p_col_defs.push({"data":x, "visible":false}); + else{ + p_col_defs.push({"data":x, "visible":true}); + } + } } else{ @@ -471,6 +477,8 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { $scope.showProject = () => { $timeout( () => { + + //Only show run and delete strain button if the project is from the current user const buttonRunStrainEl = $("#button_run_strain"); @@ -505,6 +513,8 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { $("#submission_status").html("Getting Available Workflows..."); + + $scope.getWorkflows( () => { //Get all the public strains that can be added to a project $("#submission_status").html("Getting Database Strains..."); @@ -564,11 +574,14 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { $("#overlayWorking").css({"display":"none"}); $("#single_project_controller_div").css({"display":"block"}); $("#submission_status").empty(); + $.fn.dataTable.tables( { visible: true, api: true } ).columns.adjust(); }); }); - } + } + + }); /* @@ -756,9 +769,51 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { */ $scope.runPipelines = () => { - const alert_message = "By choosing this option, all selected" + + + const table = $('#strains_table').DataTable(); + + const strains_DeleteTimeStamps = $.map(table.rows('.selected').data(), (item) => { + return item['delete_timestamp']; + }); + + const strains_names = $.map(table.rows('.selected').data(), (item) => { + return item['strainID']; + }); + + + + let strain_names=""; + for(let i = 0; i< strains_DeleteTimeStamps.length; i++) + { + if(strains_DeleteTimeStamps[i] != undefined && strains_DeleteTimeStamps[i] != null) + { + if(strain_names!=="") + { + strain_names+= ", " + strains_names[i] + }else{ + strain_names+= strains_names[i] + } + } + } + + const message_deleteStrains = "the strain/strains: " + strain_names + " were removed " + +"from the system by their creator."; + + let alert_message=""; + + + + if(strain_names !== "") + { + alert_message = "By choosing this option, all selected" + + " pipelines will be saved and unsubmitted jobs will be sent" + + " to the server. And " + message_deleteStrains + " Do you want to proceed?"; + }else + { + alert_message = "By choosing this option, all selected" + " pipelines will be saved and unsubmitted jobs will be sent" + " to the server. Do you want to proceed?"; + } modalAlert(alert_message, "Run Pipelines", () => { @@ -809,7 +864,11 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { single_project.save_pipelines((run) => { //Run the pipelines if(run === true) { + single_project.run_pipelines(); + + + } else if(run !== "no_select") { modalAlert('All processes for the selected strains' + @@ -1098,10 +1157,13 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { objects_utils.restore_table_headers('public_strains_table', strains_headers, true, () => { objects_utils.loadDataTables('public_strains_table', global_public_strains, headers_defs[0], strains_headers); $.fn.dataTable.tables( { visible: true, api: true } ).columns.adjust(); - callback(); + //callback(); }); + + }); + callback(); }; /* @@ -1111,8 +1173,20 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { single_project.get_project_strains( (strains_results) => { global_strains = strains_results.strains; + let headers_defs = set_headers_single_project('strains_table', global_strains); + $('#AlertProjectStrains').css({"display":"none"}); + for(let i = 0; i< global_strains.length; i++) + { + if(global_strains[i].delete_timestamp!== null || global_strains[i].delete_timestamp!==undefined) + { + $('#AlertProjectStrains').css({"display":"block"}); + break; + } + } + + objects_utils.restore_table_headers('strains_table', strains_headers, true, () => { objects_utils.loadDataTables('strains_table', global_strains, headers_defs[0], strains_headers); callback(); @@ -1154,6 +1228,15 @@ innuendoApp.controller("projectCtrl", ($scope, $rootScope, $http, $timeout) => { else{ objects_utils.destroyTable('strains_table'); global_strains = strains_results.strains; + $('#AlertProjectStrains').css({"display":"none"}); + for(let i = 0; i< global_strains.length; i++) + { + if(global_strains[i].delete_timestamp!== null || global_strains[i].delete_timestamp!==undefined) + { + $('#AlertProjectStrains').css({"display":"block"}); + break; + } + } let headers_defs = set_headers_single_project('strains_table', global_strains); @@ -1247,6 +1330,15 @@ const newPipelineFromFile = (element) => { single_p.add_strain_to_project($(element).attr("strain_name"), (strains_results, strain_name) => { objects_utils.destroyTable('strains_table'); global_strains = strains_results.strains; + $('#AlertProjectStrains').css({"display":"none"}); + for(let i = 0; i< global_strains.length; i++) + { + if(global_strains[i].delete_timestamp!== null && global_strains[i].delete_timestamp!==undefined) + { + $('#AlertProjectStrains').css({"display":"block"}); + break; + } + } let headers_defs = set_headers_single_project('strains_table', global_strains); objects_utils.restore_table_headers('strains_table', sh, true, () => { diff --git a/app/static/html_components/manage_projects_view.html b/app/static/html_components/manage_projects_view.html index a5cfaf72..e29e7dec 100644 --- a/app/static/html_components/manage_projects_view.html +++ b/app/static/html_components/manage_projects_view.html @@ -30,6 +30,7 @@
  • Description
  • +
    @@ -91,6 +92,8 @@
    + +