diff --git a/.gitignore b/.gitignore index 6cded5a6..1efad910 100644 --- a/.gitignore +++ b/.gitignore @@ -66,7 +66,7 @@ src/scripts/ useful_command.txt password.txt - +api/mail_server.js .idea/ docs/ diff --git a/api/server.js b/api/server.js index 2f3ba621..1f1886f8 100644 --- a/api/server.js +++ b/api/server.js @@ -56,8 +56,11 @@ const errors = require('@arangodb').errors; const queues = require('@arangodb/foxx/queues') const getUserName = require("./queries/get-user-name"); const telegram = require("./queries/telegram-chat"); -const { exec } = require('child_process'); -//const { spawn } = require('child_process'); +var child_process = require('child_process'); + +//const { exec } = require('child_process'); +//const spawn = require('child_process').spawn; +const path = require('path') //const uuidV4 = require('uuid/v4'); //const uuid = require('uuid'); //const { v4: uuidv4 } = require('uuid'); @@ -371,12 +374,30 @@ router.get('/get_person_id/:user_key', function (req, res) { person = db._query(aql`FOR edge IN ${users_edge} FILTER edge._from == ${user_id} AND CONTAINS(edge._to,"persons") RETURN edge._to`).toArray(); res.send(person); }) - .pathParam('user_key', joi.string().required(), 'user id of the entry.') +.pathParam('user_key', joi.string().required(), 'user id of the entry.') //.response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') .response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') .summary('List entry keys') .description('Assembles a list of keys of entries in the collection.'); +router.get('/get_persons/:model_key/:collection_type', function (req, res) { + var model_id = req.pathParams.collection_type +"/"+req.pathParams.model_key; + var person = []; + var persons_coll = 'persons' + if (!db._collection(persons_coll)) { + db._createCollection(persons_coll); + } + const persons = db._collection(persons_coll); + person = db._query(aql`FOR v, e, s IN 1..1 OUTBOUND ${model_id} GRAPH 'global' PRUNE e._from ==${model_id} FILTER CONTAINS(e._to, "persons") RETURN s.vertices[1]`); + res.send(person); +}) +.pathParam('model_key', joi.string().required(), 'investigation id of the parent\'s entry.') +.pathParam('collection_type', joi.string().required(), 'collection_type of the parent\'s entry.') +//.response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') +.response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') +.summary('List entry keys') +.description('Assembles a list of keys of entries in the collection.'); + router.get('/get_person/:person_id', function (req, res) { var person_id = req.pathParams.person_id; var person = []; @@ -555,7 +576,6 @@ router.post('/authenticate_group', function (req, res) { res.send({ success: false, message: 'group key ' + group_key + ' doesn\'t exists', group: {} }); } else { - // add edge in group edge var groups_edge_coll = 'groups_edge' if (!db._collection(groups_edge_coll)) { @@ -569,7 +589,6 @@ router.post('/authenticate_group', function (req, res) { "roles": roles }; var edges = db._query(aql`UPSERT ${edge_obj} INSERT ${edge_obj} UPDATE {} IN ${groups_edge} RETURN NEW `); - res.send({ success: true, message: 'group key ' + group_key + ' found', group: group_array['_documents'][0] }); } } @@ -578,6 +597,7 @@ router.post('/authenticate_group', function (req, res) { username: joi.string().required(), password: joi.string().required(), group_key: joi.string().required(), + roles: joi.object().required(), group_password: joi.string().required() }).required(), 'Values to check.') .response( @@ -946,56 +966,8 @@ router.post('/request-reset', (req, res) => { let personId = result[0]['person']['Person ID'] var edges = db._query(aql`UPSERT {'Person ID':${personId}} INSERT {} UPDATE {'token':${token}} IN ${users} RETURN NEW `); // send mail with email and token - - /* const { child_process } = require('child_process'); - child_process.execFile('./scripts/send_mail.sh',[req.body.email,req.body.token], (err, data) => { - if (err) { - console.log("error "+err); - return res.status(500).send('Error'); - } - else{ - console.log("good") - } - }); */ - //var spawn = require('child_process').spawn - - var command = "sh ./scripts/send_mail.sh " + email + " " + token; - var sendmail = exec(command, - (error, stdout, stderr) => { - if (error !== null) { - console.log(`exec error: ${error}`); - res.send({ success: false }); - } - else { - res.send({ success: true }); - } - }); - - /* const child = require('child_process').spawn("./scripts/send_mail.sh'",[email,token], { detached: true } ); - child.stdout.on('data', data => { - console.log(`stdout:\n${data}`); - res.send({ success: true }); - }); + res.send({ success: true , token:token}) - child.stderr.on('data', data => { - console.error(`stderr: ${data}`); - res.send({ success: false }); - }); */ - ////res.send('end spawn launch'); - - /* const exec = require('child_process').exec; - var child; - const myShellScript = exec('sh send_mail.sh '); - myShellScript.stdout.on('data', (data)=>{ - console.log(data); - // do whatever you want here with data - }); - myShellScript.stderr.on('data', (data)=>{ - console.error(data); - }); */ - - - } catch (e) { if (!e.isArangoError || e.errorNum !== DOC_NOT_FOUND) { @@ -1004,7 +976,7 @@ router.post('/request-reset', (req, res) => { res.throw(404, 'The entry does not exist', e); } - + res.send({ success: true , token:token}) @@ -1015,7 +987,7 @@ router.post('/request-reset', (req, res) => { //sendMail({'email':email}) //res.json(sendMail({'email':email})); - res.send({ success: true }) + //res.send({ success: true }) }) .body(joi.object({ email: joi.string().required(), @@ -1166,7 +1138,51 @@ router.get('/get_ncbi_taxon_data/', function (req, res) { .summary('List entry keys') .description('Assembles a list of keys of entries in the collection.'); - +router.get('/get_ncbi_taxon_data_by_species_regex/:regex', function (req, res) { + var regex = req.pathParams.regex; + const coll = db._collection('NCBITaxons'); + if (!coll) { + db._createDocumentCollection('NCBITaxons'); + } + var get_data = db._query(aql` + FOR entry IN ${coll} + LET RES=(FOR data in entry.data + FILTER CONTAINS(data.species,${regex}) + RETURN data) + RETURN RES + `).toArray(); + //var result=get_data[0] + //console.log(get_data[0]['species'].length) + res.send(get_data[0]); + }) + .pathParam('regex', joi.string().required(), 'regex to find reduced species set.') + .response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') + .summary('List entry keys') + .description('Assembles a list of keys of entries in the collection.'); + +router.get('/get_ncbi_taxon_data_by_taxon_regex/:regex', function (req, res) { + var regex = req.pathParams.regex; + const coll = db._collection('NCBITaxons'); + if (!coll) { + db._createDocumentCollection('NCBITaxons'); + } + var get_data = db._query(aql` + FOR entry IN ${coll} + LET RES=(FOR data in entry.data + FILTER CONTAINS(data.taxon,${regex}) + RETURN data) + RETURN RES + `).toArray(); + //var result=get_data[0] + //console.log(get_data[0]['species'].length) + res.send(get_data[0]); + }) + .pathParam('regex', joi.string().required(), 'regex to find reduced species set.') + .response(joi.array().items(joi.object().required()).required(), 'List of entry keys.') + .summary('List entry keys') + .description('Assembles a list of keys of entries in the collection.'); + + /* var get_data = db._query(aql` LET document = DOCUMENT("NCBITaxons/33550834") LET alteredList = ( @@ -1259,12 +1275,12 @@ router.get('/get_max_level/:model_type', function (req, res) { .description('Assembles a list of keys of entries in the collection.'); -router.get('/get_lindaID_by_studyID/:study_unique_id/:parent_key', function (req, res) { - var study_unique_id = req.pathParams.study_unique_id; +router.get('/get_lindaID_by_studyName/:study_name/:parent_key', function (req, res) { + var study_name = req.pathParams.study_name; var parent_key = req.pathParams.parent_key; var parent_id = "investigations/" + parent_key; var data = {} - data = db._query(aql`FOR v, e IN 1..1 OUTBOUND ${parent_id} GRAPH 'global' FILTER v['Study unique ID']==${study_unique_id} RETURN {_id:v._id}`).toArray(); + data = db._query(aql`FOR v, e IN 1..1 OUTBOUND ${parent_id} GRAPH 'global' FILTER v['Study Name']==${study_name} RETURN {_id:v._id}`).toArray(); if (data.length > 0) { data[0]["success"] = true res.send(data[0]); @@ -1275,7 +1291,7 @@ router.get('/get_lindaID_by_studyID/:study_unique_id/:parent_key', function (req } }) - .pathParam('study_unique_id', joi.string().required(), 'username of the entry.') + .pathParam('study_name', joi.string().required(), 'username of the entry.') .pathParam('parent_key', joi.string().required(), 'username of the entry.') .response(joi.object().required(), 'Entry stored in the collection.') .summary('List entry keys') @@ -1619,6 +1635,9 @@ router.get('/get_childs_by_model/:model_type/:model_key', function (req, res) { else if (model_type == "environment") { isa_model = "study_isa/Study_isa" } + else if (model_type == "event") { + isa_model = "event_isa/Event_isa" + } else { isa_model = "assay_isa/assay_Isa" } @@ -2294,7 +2313,7 @@ router.post('/upload_data', function (req, res) { var password = req.body.password; var parent_id = req.body.parent_id; var values = req.body.values; - const edge = db._collection("studies_edge"); + const edge = db._collection("investigations_edge"); var coll = db._collection("data_files"); // //first check if user exist ///////////////////////////// @@ -2763,7 +2782,6 @@ router.post('/update_document', function (req, res) { var username = req.body.username; var password = req.body.password; var _key = req.body._key; - var values = req.body.values; var model_type = req.body.model_type; var datatype = ""; @@ -3005,7 +3023,7 @@ router.post('/update_multiple_field', function (req, res) { if (model_data[field] === value) { if (datafile_key !== '') { let df_id = "data_files/" + datafile_key - if (model_field === 'Study unique ID') { + if (model_field === 'Study Name') { const edges3 = db._query(aql` LET document = DOCUMENT(${df_id}) LET alteredData = ( @@ -4439,7 +4457,11 @@ router.post('/add_multiple', function (req, res) { const edges = db._query(aql`UPSERT ${obj} INSERT ${obj} UPDATE {} IN ${edge} RETURN NEW `); ///res.send({ success: true, message: 'Everything is good ', _id: data[0].id }); + var linda_unique_id="LINDA:"+data[0].id.split('/')[1] if (model_type === 'investigation') { + var update = db._query(aql` FOR entry IN ${coll} FILTER entry._id == ${data[0].id} UPDATE {_key:${data[0].id.split('/')[1]}} WITH {'Investigation unique ID': ${linda_unique_id}} IN ${coll} RETURN NEW`).toArray(); + + var person = get_person_id_from_user_id(user[0]['_id'], users_edge) console.log(person) var obj2 = { @@ -4452,6 +4474,8 @@ router.post('/add_multiple', function (req, res) { const edges2 = db._query(aql`UPSERT ${obj2} INSERT ${obj2} UPDATE {} IN ${investigations_edge} RETURN NEW `); } if (model_type === 'study') { + var update = db._query(aql` FOR entry IN ${coll} FILTER entry._id == ${data[0].id} UPDATE {_key:${data[0].id.split('/')[1]}} WITH {'Study unique ID': ${linda_unique_id}} IN ${coll} RETURN NEW`).toArray(); + var person = get_person_id_from_user_id(user[0]['_id'], users_edge) console.log(person) var obj2 = { @@ -4686,6 +4710,7 @@ router.post('/add', function (req, res) { data = db._query(aql`INSERT ${values} IN ${coll} RETURN { new: NEW, id: NEW._id } `).toArray(); if (model_type !== 'observation_unit') { + // var data = []; // data = db._query(aql`INSERT ${values} IN ${coll} RETURN { new: NEW, id: NEW._id } `).toArray(); @@ -4699,14 +4724,22 @@ router.post('/add', function (req, res) { } //Document exists add edges in edge collection else { + var obj = { "_from": parent_id, "_to": data[0].id, }; + var linda_unique_id="LINDA:"+data[0].id.split('/')[1] const edges = db._query(aql`UPSERT ${obj} INSERT ${obj} UPDATE {} IN ${edge} RETURN NEW `); ///res.send({ success: true, message: 'Everything is good ', _id: data[0].id }); + if (model_type === 'investigation') { + //update Investigation unique ID + + var update = db._query(aql` FOR entry IN ${coll} FILTER entry._id == ${data[0].id} UPDATE {_key:${data[0].id.split('/')[1]}} WITH {'Investigation unique ID': ${linda_unique_id}} IN ${coll} RETURN NEW`).toArray(); + + var person = get_person_id_from_user_id(user[0]['_id'], users_edge) console.log(person) var obj2 = { @@ -4719,6 +4752,10 @@ router.post('/add', function (req, res) { const edges2 = db._query(aql`UPSERT ${obj2} INSERT ${obj2} UPDATE {} IN ${investigations_edge} RETURN NEW `); } if (model_type === 'study') { + + //update Study unique ID + var update = db._query(aql` FOR entry IN ${coll} FILTER entry._id == ${data[0].id} UPDATE {_key:${data[0].id.split('/')[1]}} WITH {'Study unique ID': ${linda_unique_id}} IN ${coll} RETURN NEW`).toArray(); + var person = get_person_id_from_user_id(user[0]['_id'], users_edge) console.log(person) var obj2 = { @@ -5066,8 +5103,6 @@ router.post('/add_parent_and_child', function (req, res) { //Search unique id in studies collection for this parent id ??? //check = db._query(aql`FOR v, e IN 1..1 OUTBOUND ${parent_id} GRAPH 'global' FILTER v['Study unique ID'] == ${ID} RETURN {v_id:v._id,id:v['Study unique ID'], study:v}`).toArray(); check = db._query(aql`FOR v, e IN 1..1 OUTBOUND ${parent_id} GRAPH 'global' FILTER CONTAINS(v['Study unique ID'], ${ID}) RETURN {v_id:v._id,id:v['Study unique ID'], study:v}`).toArray(); - - //check = db._query(aql` FOR entry IN ${coll} FILTER entry['Study unique ID'] == ${ID} RETURN entry`).toArray() // ID was not found if (check.length === 0) { @@ -5461,7 +5496,7 @@ router.post('/check', function (req, res) { //var user_id = user[0]._id if (as_template) { check = db._query(aql`FOR v, e IN 1..3 OUTBOUND ${parent_id} GRAPH 'global' FILTER v.${field} == ${value} AND CONTAINS('e._to','templates') RETURN {eto:e._to, vertice:v}`).toArray(); - f + } else { check = db._query(aql`FOR v, e IN 1..3 OUTBOUND ${parent_id} GRAPH 'global' FILTER v.${field} == ${value} RETURN {eto:e._to, vertice:v}`).toArray(); @@ -5547,6 +5582,154 @@ router.get('/event', function (req, res) { ****************************************************************************************** ****************************************************************************************** ******************************************************************************************/ + router.post('/add_observation_units_factor_value', function (req, res) { + var username = req.body.username; + var password = req.body.password; + var experimental_factor_values = req.body.experimental_factor_values; + var obs_unit_id = req.body.obs_unit_id; + var factor_type = req.body.factor_type + //observation unit edge + var observation_unit_edge_coll = 'observation_units_edge' + if (!db._collection(observation_unit_edge_coll)) { + db._createEdgeCollection(observation_unit_edge_coll); + } + var observation_unit_edge = db._collection(observation_unit_edge_coll); + + //observation units collection + var observation_unit_coll = db._collection('observation_units'); + if (!observation_unit_coll) { + db._createDocumentCollection('observation_units'); + } + ///////////////////////////// + //first check if user exist + ///////////////////////////// + const user = db._query(aql` + FOR entry IN ${users} + FILTER entry.username == ${username} + FILTER entry.password == ${password} + RETURN entry + `); + if (user.next() === null) { + res.send({ success: false, message: 'Username ' + username + ' doesn\'t exists' }); + } + else { + const factors_values = db._query(aql`FOR entry IN ${observation_unit_coll} + FILTER entry._id==${obs_unit_id} + RETURN entry['Observation Unit factor value'] + `).toArray(); + console.log(factors_values) + console.log(factors_values) + console.log(factor_type) + for (var j = 0; j < experimental_factor_values.length; j++) { + let obj={} + obj[factor_type]=experimental_factor_values[j] + factors_values[0][j].push(obj) + } + console.log(factors_values) + /* LET alteredFactorsValues = ( + FOR element IN document['Observation Unit factor value'] + LET newItem = PUSH(element,"3") + RETURN newItem + ) */ + const data = db._query(aql` + LET document = DOCUMENT(${obs_unit_id}) + UPDATE document + WITH { 'Observation Unit factor value': ${factors_values[0]} } + IN observation_units + RETURN {after: NEW } + `); + res.send({ success: true, message: 'document has been updated ', _id: obs_unit_id }); + + } + + }).body(joi.object().keys({ + username: joi.string().required(), + password: joi.string().required(), + experimental_factor_values: joi.array().items(joi.string().required()).required(), + obs_unit_id:joi.string().required(), + factor_type:joi.string().required() +}).required(), 'Values to check.') +.response(joi.object().keys({ + success: joi.boolean().required(), + message: joi.string().required(), + _id: joi.string().required() +}).required(), 'response.') +.summary('List entry keys') +.description('add MIAPPE description for given model.'); + + + + router.post('/add_observation_units_observed_variables', function (req, res) { + var username = req.body.username; + var password = req.body.password; + var parent_id = req.body.parent_id;//observation unit id + var values = req.body.values; + var observed_variable_id=req.body.observed_variable_id; + //var model_type = req.body.model_type; + var datatype = "observation_units"; + + //observation unit edge + var observation_unit_edge_coll = datatype + '_edge' + if (!db._collection(observation_unit_edge_coll)) { + db._createEdgeCollection(observation_unit_edge_coll); + } + var observation_unit_edge = db._collection(observation_unit_edge_coll); + + //observation units collection + var observation_unit_coll = db._collection(datatype); + if (!observation_unit_coll) { + db._createDocumentCollection(datatype); + } + ///////////////////////////// + //first check if user exist + ///////////////////////////// + const user = db._query(aql` + FOR entry IN ${users} + FILTER entry.username == ${username} + FILTER entry.password == ${password} + RETURN entry + `); + if (user.next() === null) { + res.send({ success: false, message: 'Username ' + username + ' doesn\'t exists' }); + } + else { + var observation_data = values['observations']; + var observed_variable_obj = { + "_from": parent_id, + "_to": observed_variable_id, + "observations": [] + } + // add Observed variable link to observation unit edge + if (observation_data !== undefined) { + for (var j = 0; j < observation_data.length; j++) { + observation_data[j]['Observed variable ID'] = observed_variable_id + observed_variable_obj["observations"].push(observation_data[j]) + } + } + if ("_from" in observed_variable_obj) { + db._query(aql`UPSERT ${observed_variable_obj} INSERT ${observed_variable_obj} UPDATE {} IN ${observation_unit_edge} RETURN NEW `); + res.send({ success: true, message: 'Everything is good ', _id: observed_variable_id }); + } + } +}) + .body(joi.object().keys({ + username: joi.string().required(), + password: joi.string().required(), + parent_id: joi.string().required(), + values: joi.object({ + observations: joi.array().items(joi.object().required()).required(), + }).required(), + observed_variable_id: joi.string().required(), + }).required(), 'Values to check.') + .response(joi.object().keys({ + success: joi.boolean().required(), + message: joi.string().required(), + _id: joi.string().required() + }).required(), 'response.') + .summary('List entry keys') + .description('add MIAPPE description for given model.'); + + //Post new data router.post('/add_observation_units_samples', function (req, res) { var username = req.body.username; @@ -6093,12 +6276,66 @@ router.post('/add_observation_units', function (req, res) { .summary('List entry keys') .description('add MIAPPE description for given model.'); +router.post('/add_observation_unit_factor', function (req, res) { + var username = req.body.username; + var password = req.body.password; + var observation_unit_id = req.body.observation_unit_id; + var experimental_factor = req.body.experimental_factor; + var datatype = "observation_units"; + + //observation unit edge + var observation_unit_edge_coll = 'observation_units_edge' + if (!db._collection(observation_unit_edge_coll)) { + db._createEdgeCollection(observation_unit_edge_coll); + } + var observation_unit_edge = db._collection(observation_unit_edge_coll); + + //observation units collection + var observation_unit_coll = db._collection(datatype); + if (!observation_unit_coll) { + db._createDocumentCollection(datatype); + } + + ///////////////////////////// + //first check if user exist + ///////////////////////////// + const user = db._query(aql` + FOR entry IN ${users} + FILTER entry.username == ${username} + FILTER entry.password == ${password} + RETURN entry + `); + if (user.next() === null) { + res.send({ success: false, message: 'Username ' + username + ' doesn\'t exists' , _id:username}); + } + else { + var ef_obj = { + "_from": observation_unit_id, + "_to": experimental_factor['_id'] + } + const result=db._query(aql`UPSERT ${ef_obj} INSERT ${ef_obj} UPDATE {} IN ${observation_unit_edge} RETURN NEW `); + res.send({ success: true, message: 'successfully added factor in observation unit edge' , _id:result['_id']}); + } +}) +.body(joi.object().keys({ + username: joi.string().required(), + password: joi.string().required(), + observation_unit_id: joi.string().required(), + experimental_factor: joi.object().required() +}).required(), 'Values to check.') +.response(joi.object().keys({ + success: joi.boolean().required(), + message: joi.string().required(), + _id: joi.string().required() +}).required(), 'response.') +.summary('List entry keys') +.description('add MIAPPE description for given model.'); router.post('/remove_observation_unit', function (req, res) { var username = req.body.username; var password = req.body.password; - var id = req.body.id; + var id = req.body.id;//observation unit const user = db._query(aql` FOR entry IN ${users} @@ -6132,7 +6369,7 @@ router.post('/remove_observation_unit', function (req, res) { //Delete child vertice in collection if ((childs[i].v_id !== null) || (childs[i].v_key !== null)) { - if (childs[i].v_id.split("/")[0] !== "biological_materials" && childs[i].v_id.split("/")[0] !== "experimental_factors") { + if (childs[i].v_id.split("/")[0] !== "biological_materials" && childs[i].v_id.split("/")[0] !== "experimental_factors" && childs[i].v_id.split("/")[0] !== "observed_variables") { var child_coll = childs[i].v_id.split("/")[0]; var child_vkey = childs[i].v_key; try { @@ -7389,10 +7626,10 @@ router.get('/get_templates/:person_key', function (req, res) { //Get templates - used in template selection dialog component -router.get('/get_templates_by_user/:user_key/:model_coll/', function (req, res) { +router.get('/get_templates_by_user/:user_key/:model_type/', function (req, res) { try { var user_key = req.pathParams.user_key; - var model_coll = req.pathParams.model_coll; + var model_type = req.pathParams.model_type; var coll_name = 'templates' var data = []; @@ -7417,8 +7654,7 @@ router.get('/get_templates_by_user/:user_key/:model_coll/', function (req, res) } //data = coll.byExample().toArray(); - - + data=data.filter(template=>template['_model_type']===model_type) res.send(data); } catch (e) { @@ -7430,7 +7666,7 @@ router.get('/get_templates_by_user/:user_key/:model_coll/', function (req, res) }) .pathParam('user_key', joi.string().required(), 'model requested.') - .pathParam('model_coll', joi.string().required(), 'unique key.') + .pathParam('model_type', joi.string().required(), 'unique key.') .response(joi.array().items(joi.object().required()).required(), 'Entry stored in the collection.') .summary('Retrieve an entry') .description('Retrieves an entry from the "myFoxxCollection" collection by key.'); diff --git a/package-lock.json b/package-lock.json index 34bdab40..db09a65a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3950,9 +3950,9 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "ansi-styles": { "version": "3.2.1", @@ -4906,34 +4906,86 @@ "dev": true }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, @@ -5963,8 +6015,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "convert-source-map": { "version": "1.7.0", @@ -6666,7 +6717,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7063,8 +7113,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { "version": "1.3.550", @@ -7634,11 +7683,47 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } } } }, @@ -8819,6 +8904,13 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } } }, "has-bigints": { @@ -12972,8 +13064,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { "version": "4.3.0", @@ -13263,9 +13354,9 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "moment": { - "version": "2.29.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", - "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==" + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" }, "move-concurrently": { "version": "1.0.1", @@ -15178,22 +15269,57 @@ "dev": true }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, @@ -16911,6 +17037,13 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } } }, "strip-bom": { @@ -17721,7 +17854,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -17884,8 +18016,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "unset-value": { "version": "1.0.0", diff --git a/package.json b/package.json index 87b771be..6587587d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,9 @@ "ag-grid-enterprise": "^27.1.0", "angular-datatables": "^8.1.0", "angular-ui-tour": "^0.9.4", + "ansi-regex": "^6.0.1", "auth0": "^2.38.1", + "body-parser": "^1.20.0", "bootstrap": "^3.4.1", "core-js": "^3.6.5", "csv": "^6.0.5", @@ -60,7 +62,7 @@ "mdb-ui-kit": "^3.4.0", "minimist": "^1.2.6", "mkdirp": "^1.0.4", - "moment": "^2.29.2", + "moment": "^2.29.3", "ng-bootstrap": "^1.6.3", "ng-gantt": "^2.5.0", "ngx-guided-tour": "^1.1.11", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index fe7b5842..e3d3a693 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -7,13 +7,13 @@ import { HomeComponent } from './modules/general/home/home.component'; import { AdminComponent } from './components/admin/admin.component' import { HomeNewComponent } from './modules/general/home/home-new.component'; import { NotFoundComponent } from './modules/general/not-found/not-found.component'; -import { ResponseResetComponent } from './modules/general/response-reset/response-reset.component'; +//import { ResponseResetComponent } from './modules/general/response-reset/response-reset.component'; const routes: Routes = [ { path: '', redirectTo: 'home2', pathMatch: 'full' }, //{ path: 'home', component: HomeComponent, canActivate: [AuthGuard]}, - { path: 'home2',component: HomeNewComponent, canActivate: [AuthGuard]}, - { path: 'response-reset',component: ResponseResetComponent}, + { path: 'home2',component: HomeNewComponent}, + //{ path: 'response-reset',component: ResponseResetComponent}, { path: 'login', loadChildren: () => import('./modules/general/login/login.module') @@ -118,11 +118,11 @@ const routes: Routes = [ loadChildren: () => import('./modules/general/request-reset/request-reset.module') .then(m => m.RequestResetModule) }, - /* { + { path: 'response-reset', loadChildren: () => import('./modules/general/response-reset/response-reset.module') .then(m => m.ResponseResetModule) - }, */ + }, // DOCUMENTATION MODULE { path: '', diff --git a/src/app/app.component.css b/src/app/app.component.css index d59ff064..70f08698 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -1,9 +1,10 @@ .scrollable-menu { height: auto; max-height: 200px; - overflow-x: hidden; + /* overflow-x: hidden; */ } + button { padding-top: 2px; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 9d8110a3..2a938d3e 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -64,6 +64,7 @@ import { HomeComponent } from './modules/general/home/home.component'; import { HomeNewComponent } from './modules/general/home/home-new.component'; import { NotFoundComponent } from './modules/general/not-found/not-found.component'; import { ResponseResetComponent } from './modules/general/response-reset/response-reset.component'; +import { ResponseResetModule } from './modules/general/response-reset/response-reset.module'; @@ -79,8 +80,8 @@ import { ResponseResetComponent } from './modules/general/response-reset/respons DragDropDirective, PublicationsComponent, HomeNewComponent, - NotFoundComponent, - ResponseResetComponent + NotFoundComponent//, + //ResponseResetComponent ], imports: [ BrowserModule, @@ -125,7 +126,8 @@ import { ResponseResetComponent } from './modules/general/response-reset/respons AlertModule, MapModule, AssignModule, - RequestResetModule + RequestResetModule, + ResponseResetModule //DocumentationModule //ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }) ], diff --git a/src/app/components/admin/admin.component.ts b/src/app/components/admin/admin.component.ts index 01437156..09ca7b57 100644 --- a/src/app/components/admin/admin.component.ts +++ b/src/app/components/admin/admin.component.ts @@ -4,104 +4,104 @@ import { UserInterface } from 'src/app/models/linda/person'; import { User } from '../../models/user'; declare const annyang: any; @Component({ - selector: 'app-admin', - templateUrl: './admin.component.html', - styleUrls: ['./admin.component.css'] + selector: 'app-admin', + templateUrl: './admin.component.html', + styleUrls: ['./admin.component.css'] }) export class AdminComponent implements OnInit { - voiceActiveSectionDisabled: boolean = true; + voiceActiveSectionDisabled: boolean = true; voiceActiveSectionError: boolean = false; voiceActiveSectionSuccess: boolean = false; voiceActiveSectionListening: boolean = false; voiceText: any; - users: UserInterface[] = []; - constructor(private ngZone: NgZone) { } + users: UserInterface[] = []; + constructor(private ngZone: NgZone) { } - ngOnInit() {} + ngOnInit() { } - initializeVoiceRecognitionCallback(): void { + initializeVoiceRecognitionCallback(): void { annyang.addCallback('error', (err) => { - if(err.error === 'network'){ - this.voiceText = "Internet is require"; - annyang.abort(); - this.ngZone.run(() => this.voiceActiveSectionSuccess = true); - } else if (this.voiceText === undefined) { + if (err.error === 'network') { + this.voiceText = "Internet is require"; + annyang.abort(); + this.ngZone.run(() => this.voiceActiveSectionSuccess = true); + } else if (this.voiceText === undefined) { this.ngZone.run(() => this.voiceActiveSectionError = true); annyang.abort(); } }); annyang.addCallback('soundstart', (res) => { - this.ngZone.run(() => this.voiceActiveSectionListening = true); + this.ngZone.run(() => this.voiceActiveSectionListening = true); }); annyang.addCallback('end', () => { - if (this.voiceText === undefined) { - this.ngZone.run(() => this.voiceActiveSectionError = true); + if (this.voiceText === undefined) { + this.ngZone.run(() => this.voiceActiveSectionError = true); annyang.abort(); } }); annyang.addCallback('result', (userSaid) => { this.ngZone.run(() => this.voiceActiveSectionError = false); - alert("I think the user said: " + userSaid[0] + "
But then again, it could be any of the following: " + userSaid); + alert("I think the user said: " + userSaid[0] + "
But then again, it could be any of the following: " + userSaid); let queryText: any = userSaid[0]; annyang.abort(); - this.voiceText = queryText; - console.log(queryText) + this.voiceText = queryText; + console.log(queryText) this.ngZone.run(() => this.voiceActiveSectionListening = false); - this.ngZone.run(() => this.voiceActiveSectionSuccess = true); + this.ngZone.run(() => this.voiceActiveSectionSuccess = true); }); } startVoiceRecognition(): void { - this.voiceActiveSectionDisabled = false; + this.voiceActiveSectionDisabled = false; this.voiceActiveSectionError = false; this.voiceActiveSectionSuccess = false; - this.voiceText = undefined; + this.voiceText = undefined; if (annyang) { - console.log(this.voiceText) -// let commands = { -// 'demo-annyang': () => { }, -// 'hello-world' : () => { console.log("hello world")} -// } + console.log(this.voiceText) + // let commands = { + // 'demo-annyang': () => { }, + // 'hello-world' : () => { console.log("hello world")} + // } - const commands = { - 'hello': () => { alert('Hello world!'); } + const commands = { + 'hello': () => { alert('Hello world!'); } - }; + }; annyang.addCommands(commands); - this.initializeVoiceRecognitionCallback(); + this.initializeVoiceRecognitionCallback(); annyang.start({ autoRestart: false, continuous: false }); } } closeVoiceRecognition(): void { - this.voiceActiveSectionDisabled = true; + this.voiceActiveSectionDisabled = true; this.voiceActiveSectionError = false; this.voiceActiveSectionSuccess = false; this.voiceActiveSectionListening = false; - + this.voiceText = undefined; - if(annyang){ - annyang.abort(); - } + if (annyang) { + annyang.abort(); + } } -// private loadAllUsers() { -// this.userService.getAll().pipe(first()).subscribe(users => { -// this.users = users; -// }); -// } -// deleteUser(id: string) { -// this.userService.delete(id).pipe(first()).subscribe(() => { -// this.loadAllUsers() -// }); -// } + // private loadAllUsers() { + // this.userService.getAll().pipe(first()).subscribe(users => { + // this.users = users; + // }); + // } + // deleteUser(id: string) { + // this.userService.delete(id).pipe(first()).subscribe(() => { + // this.loadAllUsers() + // }); + // } } diff --git a/src/app/components/chip-list/chip-list.component.css b/src/app/components/chip-list/chip-list.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/chip-list/chip-list.component.html b/src/app/components/chip-list/chip-list.component.html new file mode 100644 index 00000000..29a21186 --- /dev/null +++ b/src/app/components/chip-list/chip-list.component.html @@ -0,0 +1,6 @@ + + + {{skill.name}} + cancel + + diff --git a/src/app/components/chip-list/chip-list.component.ts b/src/app/components/chip-list/chip-list.component.ts new file mode 100644 index 00000000..e9fdf123 --- /dev/null +++ b/src/app/components/chip-list/chip-list.component.ts @@ -0,0 +1,20 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; + +@Component({ + selector: 'chip-list', + templateUrl: 'chip-list.component.html', + styleUrls: ['chip-list.component.css'], +}) +export class ChipListComponent { + @Input() skills; + @Output() notify: EventEmitter<{}> = new EventEmitter<{}>(); + removable=true + onRemove(name:string){ + this.skills=this.skills.filter(skill=>skill.name!==name) + this.notify.emit({skills:this.skills, selected_skill:name}) + } + onSelect(name:any){ + //this.skills=this.skills.filter(skill=>skill.name!==name) + this.notify.emit({skills:this.skills, selected_skill:name}) + } +} \ No newline at end of file diff --git a/src/app/components/footer/footer.component.css b/src/app/components/footer/footer.component.css index 60821114..362720bd 100644 --- a/src/app/components/footer/footer.component.css +++ b/src/app/components/footer/footer.component.css @@ -1,6 +1,5 @@ .nga-footer { background-color: #2f323a;; - color: white; } @@ -11,7 +10,7 @@ .nga-footer a:hover, .nga-footer a:focus { - color: yellow; + color: #4ECDC4; text-decoration: underline; } diff --git a/src/app/components/footer/footer.component.html b/src/app/components/footer/footer.component.html index 3176f0f8..a7a294fa 100644 --- a/src/app/components/footer/footer.component.html +++ b/src/app/components/footer/footer.component.html @@ -8,7 +8,7 @@
Quick links
  • Home
  • About
  • FAQ
  • -
  • Get Started
  • +
  • Get Started
  • @@ -22,15 +22,6 @@
    Partners
    -
    diff --git a/src/app/components/header/header.component.css b/src/app/components/header/header.component.css index 9a1602e5..b887f029 100644 --- a/src/app/components/header/header.component.css +++ b/src/app/components/header/header.component.css @@ -6,9 +6,9 @@ } .navbar.navbar-dark .navbar-nav .nav-item .nav-link:hover { - color: yellow; - border-top: 1px solid yellow; - border-bottom: 1px solid yellow; + color: #4ECDC4; + border-top: 1px solid #4ECDC4; + border-bottom: 1px solid #4ECDC4; } .nga-navbar { @@ -38,3 +38,5 @@ border-color: #0a58ca; } + + diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index ddc528eb..d08d1162 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -23,6 +23,9 @@ +
    diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index 447cd7bf..f88d437f 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -1,216 +1,230 @@ -import { Component , OnInit, Input} from '@angular/core'; -import {GlobalService, SearchService, AuthenticationService } from '../../services'; -import { MatDialog} from '@angular/material/dialog'; +import { Component, OnInit, Input } from '@angular/core'; +import { GlobalService, SearchService, AuthenticationService } from '../../services'; +import { MatDialog } from '@angular/material/dialog'; import { first } from 'rxjs/operators'; import { Subscription } from 'rxjs'; import { SearchResultComponent } from '../../modules/application/dialogs/search-result.component'; import { Router } from '@angular/router'; import { User } from '../../models'; import { UserInterface } from 'src/app/models/linda/person'; +import { Investigation } from 'src/app/models/linda/investigation'; @Component({ - selector: 'app-header', - templateUrl: './header.component.html', - styleUrls: ['./header.component.css'] + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.css'] }) -export class HeaderComponent implements OnInit{ +export class HeaderComponent implements OnInit { //@Input() private _currentUser!: {}; - private _currentUser:UserInterface - public get currentUser(): UserInterface { + private _currentUser: UserInterface + public get currentUser(): UserInterface { return this._currentUser; - } - public set currentUser(value: UserInterface) { + } + public set currentUser(value: UserInterface) { this._currentUser = value; - } - title = 'LINDA'; - selected="Home"; - public stats = {}; - public stats_advanced = {}; - public vertice_data:any=[]; - public search_string:string="" - constructor(private globalService : GlobalService, private searchService : SearchService, public dialog: MatDialog,private authenticationService: AuthenticationService, private router: Router){ - console.log("Welcome in Header component") - this.stats_advanced={ - "investigations":[], - "studies":[], - "experimental_factors":[], - "environments": [], - "metadata_files": [], - "observation_units": [], - "samples": [], - "events": [], - "data_files":[], - "biological_materials":[], - "observed_variables":[] } - // this.currentUserSubscription = this.authenticationService.currentUser.subscribe(user => { - // this.currentUser = user; - // }); - } - async ngOnInit() { - console.log("Welcome in Header component") - this.authenticationService.currentUser.subscribe(x => this.currentUser = x); - if (this.currentUser!==null || this.currentUser!==undefined){ - await this.get_vertices() + title = 'LINDA'; + selected = "Home"; + public stats = {}; + public stats_advanced = {}; + public vertice_data: any = []; + public search_string: string = "" + constructor(private globalService: GlobalService, private searchService: SearchService, public dialog: MatDialog, private authenticationService: AuthenticationService, private router: Router) { + //console.log("Welcome in Header component") + this.stats_advanced = { + "investigations": [], + "studies": [], + "experimental_factors": [], + "environments": [], + "metadata_files": [], + "observation_units": [], + "samples": [], + "events": [], + "data_files": [], + "biological_materials": [], + "observed_variables": [] + } + // this.currentUserSubscription = this.authenticationService.currentUser.subscribe(user => { + // this.currentUser = user; + // }); } - // await this.get_vertices() - /** - * test modif - * // TODO: here need to get same parameter as for edit fucntion in user tree - */ - //let currentUser=JSON.parse(localStorage.getItem('currentUser')); - - -} - onSearch(){ - this.searchService.startSearch(this.search_string).pipe(first()).toPromise().then( - data=>{ - console.log(data) - const dialogRef = this.dialog.open(SearchResultComponent, { disableClose: true,width: '1000px', autoFocus: false, maxHeight: '90vh' , data: {search_type :this.search_string, model_id:"",values:data, parent_id:""}}); - dialogRef.afterClosed().subscribe(result => { - if (result){ - console.log(result) - var parent_id=result['parent_id'] - var model_id=result['model_id'] - var model_type=result['model_id'].split("/")[0] - var model_key=result['model_id'].split("/")[1] - if (model_type=="metadata_files"){ - //this.router.navigate(['/download'],{ queryParams: {parent_id: parent_id, model_key:model_key,model_type:"metadata_file",mode:"edit"}}); - } - else{ - if (model_type==='studies'){ - model_type='study' - } - else{ - model_type=model_type.slice(0, -1) - } - //this.router.navigate(['/generic_form'],{ queryParams: {level:"1", parent_id:parent_id, model_key:model_key,model_type:model_type,mode:"edit", inline:"false", asTemplate:false, onlyTemplate:false}, skipLocationChange: true}); - } - } - }); - } - ); - } - user_page(){ - this.router.navigate(['/profile']); - } - logout() { - this.authenticationService.logout(); - this.router.navigate(['/login']); - } - updateData(value: string) { - this.searchService.updateData(value); - } + async ngOnInit() { + //console.log("Welcome in Header component") + this.authenticationService.currentUser.subscribe(x => this.currentUser = x); + if (this.currentUser !== null || this.currentUser !== undefined) { + await this.get_vertices() + } + // await this.get_vertices() + /** + * test modif + * // TODO: here need to get same parameter as for edit fucntion in user tree + */ + //let currentUser=JSON.parse(localStorage.getItem('currentUser')); - searchStart(event){ - this.search_string=event.target.value; - //this.searchService.updateData(this.search_string); - } - set_percent_style(percent: any): Object { - var percent_css=percent+"%" - //style="width: 40%" - return {width: percent_css} - } -// identifyYourself() { -// if (this.outslet && this.outlet.component) { -// this.outlet.component.identify(); -// } -// } - set_pending_task_background_color(id: any): Object { - - if (id.includes('Investigations tree')){ - - return {backgroundColor: 'white'} } - else if (id.includes('studies')){ - - return {backgroundColor: 'white'} + onSearch() { + if (this.search_string!==""){ + + this.searchService.startSearch(this.search_string).pipe(first()).toPromise().then( + data => { + //console.log(data) + const dialogRef = this.dialog.open(SearchResultComponent, { disableClose: true, width: '1000px', autoFocus: false, maxHeight: '90vh', data: { search_type: this.search_string, model_id: "", values: data, parent_id: "" } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + //console.log(result) + var parent_id = result['parent_id'] + var model_id = result['model_id'] + var model_type = result['model_id'].split("/")[0] + var model_key = result['model_id'].split("/")[1] + if (model_type == "metadata_files") { + //this.router.navigate(['/download'],{ queryParams: {parent_id: parent_id, model_key:model_key,model_type:"metadata_file",mode:"edit"}}); + } + else { + if (model_type === 'studies') { + model_type = 'study' + } + else { + model_type = model_type.slice(0, -1) + } + //this.router.navigate(['/generic_form'],{ queryParams: {level:"1", parent_id:parent_id, model_key:model_key,model_type:model_type,mode:"edit", inline:"false", asTemplate:false, onlyTemplate:false}, skipLocationChange: true}); + } + } + }); + } + ); + } } - else if(id.includes('investigations')){ - - return {backgroundColor: 'white'} + user_page() { + this.router.navigate(['/profile']); } - else if(id.includes('events')){ - - return {backgroundColor: 'white'} + logout() { + this.authenticationService.logout(); + this.router.navigate(['/login']); } - else if(id.includes('metadata')){ - - return {backgroundColor: 'white'} + updateData(value: string) { + this.searchService.updateData(value); } - else{ - return {backgroundColor: 'white'} - } -} -/* onActivate(componentReference:any) { - if(componentReference instanceof UserTreeComponent){ - console.log("This is a message from the UserTreeComponent"); - ///this.currentUser=JSON.parse(localStorage.getItem('currentUser')); - this.get_vertices() - return; - } - else{ - console.log("This is not the UserTreeComponent") - //this.currentUser=JSON.parse(localStorage.getItem('currentUser')); - ///console.log(this.currentUser) - this.get_vertices() - return; - } -} */ + searchStart(event) { + this.search_string = event.target.value; + //this.searchService.updateData(this.search_string); + } + set_percent_style(percent: any): Object { + var percent_css = percent + "%" + //style="width: 40%" + return { width: percent_css } + } + // identifyYourself() { + // if (this.outslet && this.outlet.component) { + // this.outlet.component.identify(); + // } + // } + + set_pending_task_background_color(id: any): Object { + + if (id.includes('Investigations tree')) { - get_vertices(){ - this.stats_advanced={ - "investigations":[], - "studies":[], - "experimental_factors":[], - "environments": [], - "metadata_files": [], - "observation_units": [], - "samples": [], - "events": [], - "data_files":[], - "biological_materials":[], - "observed_variables":[] + return { backgroundColor: 'white' } + } + else if (id.includes('studies')) { + + return { backgroundColor: 'white' } + } + else if (id.includes('investigations')) { + + return { backgroundColor: 'white' } + } + else if (id.includes('events')) { + + return { backgroundColor: 'white' } + } + else if (id.includes('metadata')) { + + return { backgroundColor: 'white' } + } + else { + return { backgroundColor: 'white' } + } } - /* if (this.currentUser){ - return this.globalService.get_inv_stud_vertices(this.currentUser['_key']).toPromise().then( + + /* onActivate(componentReference:any) { + if(componentReference instanceof UserTreeComponent){ + //console.log("This is a message from the UserTreeComponent"); + ///this.currentUser=JSON.parse(localStorage.getItem('currentUser')); + this.get_vertices() + return; + } + else{ + //console.log("This is not the UserTreeComponent") + //this.currentUser=JSON.parse(localStorage.getItem('currentUser')); + /////console.log(this.currentUser) + this.get_vertices() + return; + } + } */ + + async get_vertices() { + this.stats_advanced = { + "investigations": [], + "studies": [], + "experimental_factors": [], + "environments": [], + "metadata_files": [], + "observation_units": [], + "samples": [], + "events": [], + "data_files": [], + "biological_materials": [], + "observed_variables": [] + } + if (this.currentUser) { + return await this.globalService.get_inv_stud_vertices(this.currentUser['_key']).toPromise().then( data => { - this.vertice_data=data; + this.vertice_data = data; this.vertice_data.forEach( d => { - var stat_object={ - 'id':d["e"]["_to"], - 'percent_fill':0, - 'parent_id':d["e"]["_from"] + console.log(d) + var stat_object = { + 'id': d["e"]["_to"], + 'name':"", + 'percent_fill': 0, + 'parent_id': d["e"]["_from"] } //this.stats[d["e"]["_to"].split("/")[0]]+=1 - - var vertices:[]=d["s"]["vertices"] + + var vertices: [] = d["s"]["vertices"] vertices.forEach( vertice => { - var vertice_keys=Object.keys(vertice) - var vertice_id=vertice["_id"] - var total=0; - for (var i = 0; i< vertice_keys.length; i++) { - if (vertice[vertice_keys[i]]!==""){ - total+=1 - } - } - var percent= Math.round(100 *((total-3)/(vertice_keys.length-3))) - if (vertice_id===stat_object['id']){ - stat_object['percent_fill']=percent + var vertice_keys = Object.keys(vertice) + //console.log(vertice_keys) + var vertice_id:string = vertice["_id"] + var total = 0; + for (var i = 0; i < vertice_keys.length; i++) { + if (vertice[vertice_keys[i]] !== "") { + total += 1 + } + } + var percent = Math.round(100 * ((total - 3) / (vertice_keys.length - 3))) + if (vertice_id === stat_object['id']) { + stat_object['percent_fill'] = percent + if (vertice_id.includes('Investigations')){ + stat_object['name'] = vertice['Project Name'] + } + else{ + stat_object['name'] = vertice['Study Name'] + } } } ) - if (stat_object['percent_fill'] < 100){ + this.stats_advanced[d["e"]["_to"].split("/")[0]].push(stat_object) + /* if (stat_object['percent_fill'] < 100) { this.stats_advanced[d["e"]["_to"].split("/")[0]].push(stat_object) - } - + } */ } ); + //console.log(this.stats_advanced) } ) - } */ -} + } + } } diff --git a/src/app/components/sider/sider.component.css b/src/app/components/sider/sider.component.css index 0d72b928..a7bd7c32 100644 --- a/src/app/components/sider/sider.component.css +++ b/src/app/components/sider/sider.component.css @@ -1,4 +1,40 @@ -aside { +/* aside { float: left; width: 15%; - } \ No newline at end of file + } */ + @media only screen and (min-width:480px) { + aside { + float: left; + width: 15%; + } + } +@media only screen and (max-width:480px) { + section.page, section.content { + display : block; /* override flexbox */ + min-height : inherit; + } + section.page { + padding : 0.5em 0.25em 0.5em 0.25em; + } + aside { + display : none; /* hide sidebar */ + } + article { + min-height : 20em; + margin : 4em 0 1em 0; + } + header, nav { /* compress header & nav */ + min-height : 2em; + position : absolute; + top : 0.5em; + } + header { + left : 0.5em; + width : 60%; + } + nav { + right : 0.5em; + width : 20%; + min-width : inherit; + } +} \ No newline at end of file diff --git a/src/app/components/sider/sider.component.html b/src/app/components/sider/sider.component.html index f2597730..24c08b6d 100644 --- a/src/app/components/sider/sider.component.html +++ b/src/app/components/sider/sider.component.html @@ -19,7 +19,21 @@ - + -
    @@ -47,7 +66,7 @@

    Add a new column

    -- - + {{associated_header.header + " (" +associated_header.associated_component_field + ")"}} @@ -104,6 +123,26 @@

    Add a new column

    +
    + +
    + + + Autogenerate ids + Paste ids + +
    + + + + + + + + + + +
    + +
    +
    +

    Experimental factor and experimental design

    +

    + Depending on the experimental design you defined previously, you need to associate experimental factor to a given + observation level. + for example if you plan to associate a factor with 2 values (wateredr and rainfed) at the block level, you have to + select block in the corrreponding select list below. + Then you have to select between three options, each describing a specific arrangment of factor across the block or + plot + +

    +

    + Which Experimental factor do you plan to use ? +

    + +

    Experimental design details

    +

    You have {{total_available_plots}} plots in your experimental design. + Take care to assign factors in respect of design capability !! + You could use differents configurations +

    +

    You do not find corresponding trait, create new experimental factor

    + + + +
    +
    + + + + + + + +
    +
    + + + + + + + + + + + Filter + + + +
    + + + + + + + + + + + + + + + + + + +
    {{column}} {{element[column]}} {{column}} {{element[column]}} + + + + + +
    + + +
    + +
    + + + +
    + +

    Select Factor repartition

    + +

    Completely randomized design

    +

    + The simplest, least restrictive experimental design is the Completely + Randomized Design (CRD). In a CRD, the treatments are assigned + to the plots without restriction. That is, with the CRD, every plot is + equally likely to be assigned in any treatment +

    +

    Randomized complete block design

    +

    + The Randomized complete Block Design (RBD) is the design use most often + in agricultural research. In a RBD, the plots (experimental units) are + first classified into groups, + or blocks, of plots within blocks in such a way that each treatment + occurs the same number of time, usually once within each block. + The object is to make the variation from plot to plot as small as + possible within the blocks while maximizing the variation among blocks +

    +

    Latin Square Design

    +

    + In the latin square, the number of plots is the square of the number of + treatments. For practical purposes, its use is restricted to trials with + more than four + but fewer than 10 treatments. +

    +
    + +

    + As the name implies, in incomplete block designs the plots are grouped + into blocks that are not large enough to contain a full replication of + all treatments (experimental factors). + Incomplete block designs fall into two broad classes: Balanced designs + and partially balanced designs. + In balanced design, each treatment occurs together in the same block with every + other treatment an equal number of times, usually once. + In a balanced incomplete block design, all pairs of treatment are compared with the + same precision event though the differences between block may be large. + It is possible to construct a balanced design for any numbers of treatments + and any block size (plots per block). + These two parameters fix the minimum number of replications required for balance. + Often, this minimum is too large for the balanced design to be of practical significance. +

    +

    Balanced incomplete block design

    +

    + A Balanced Incomplete Block Design (BIBD) can be used when it is not possible + to include all treatments or factor combinations in every block. + Use BIBDs for testing a treatments in b blocks when only k treatments + can be run in any one block (and k < a). +
    A BIB design is a design with a treatments and b blocks in which each block is of size k, + each treatment is replicated r times, and every pair of distinct treatments occurs together in λ blocks. +
    The design is said to have the parameters (a, b, r, k, λ). + The design is said to be proper if k < a, that is, the blocks are incomplete. +
    For a proper BIB design, Fisher’s inequality b a, or equivalently r k, holds. + A BIB design is said to be symmetric if a = b, and consequently r = k. + Such a design is called a symmetric (a,k , λ) design, and λ(a - 1) = k(k - 1). + A necessary condition for the existence of a symmetric (a, k, λ) design is given by the following: + For example, you might have a + situation where there are limitations on the number of treatments that + can be tested at the same time. The BIBD design is constructed such that + each treatment and each pair of treatments occurs together in blocks an equal + number of times. This makes the design balanced. + Not including all treatments in every block makes the design incomplete. +

    +

    Partially balanced design

    +

    + Because balanced designs are not always practical, a class of designs called partially + balanced incomplete block design (pbibd) has been developed. +

    +
    + + + {{available_design}} + + + + + + {{factor}} + + +
    +

    Treatment repartition

    + + + {{'Block ' + bd['Block number'].value}} + + +
    +
    +

    Treatment repartition

    + + + {{get_associated_material_source(pd)}} + + + +
    +
    +
    +
    +
    +
    + + +
    +
    \ No newline at end of file diff --git a/src/app/modules/application/dialogs/associate-experimental-factor.component.spec.ts b/src/app/modules/application/dialogs/associate-experimental-factor.component.spec.ts new file mode 100644 index 00000000..67142902 --- /dev/null +++ b/src/app/modules/application/dialogs/associate-experimental-factor.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AssociateExperimentalFactorComponent } from './associate-experimental-factor.component'; + +describe('AssociateExperimentalFactorComponent', () => { + let component: AssociateExperimentalFactorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AssociateExperimentalFactorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AssociateExperimentalFactorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/application/dialogs/associate-experimental-factor.component.ts b/src/app/modules/application/dialogs/associate-experimental-factor.component.ts new file mode 100644 index 00000000..d2c962ba --- /dev/null +++ b/src/app/modules/application/dialogs/associate-experimental-factor.component.ts @@ -0,0 +1,585 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { ChangeDetectorRef, Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { MatDialog, MatDialogRef, MatPaginator, MatSort, MatTableDataSource, MAT_DIALOG_DATA, PageEvent } from '@angular/material'; +import { Router } from '@angular/router'; +import { indexOf, isBuffer } from 'lodash'; +import { first } from 'rxjs/operators'; +import { BlockDesignInterface, ExperimentalDesign, PlotDesign } from 'src/app/models/linda/experimental-design'; +import { ExperimentalFactor, ExperimentalFactorInterface } from 'src/app/models/linda/experimental_factor'; +import { AlertService, GlobalService } from 'src/app/services'; +import { AssociateBiologicalMaterial } from './associate-biological-material.component'; +import { FormGenericComponent } from './form-generic.component'; +import { TemplateSelectionComponent } from './template-selection.component'; + +interface DialogData { + model_id: string; + parent_id: string; + model_type: string; + total_available_plots: number; + role: string; + grand_parent_id: string; + available_designs: string[]; + group_key: string; + design: ExperimentalDesign; + total_blocks_per_row: number; + total_columns_per_block: number; + + block_design_type: string; +} + +@Component({ + selector: 'app-associate-experimental-factor', + templateUrl: './associate-experimental-factor.component.html', + styleUrls: ['./associate-experimental-factor.component.css'] +}) +export class AssociateExperimentalFactorComponent implements OnInit { + @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; + @ViewChild(MatSort, { static: false }) sort: MatSort; + private model_id: string; + private parent_id: string; + model_type: string; + total_available_plots: number = 0 + total_available_blocks: number = 0 + total_blocks_per_row: number = 0 + total_columns_per_block: number = 0 + role: string = "" + grand_parent_id: string = "" + group_key: string = "" + design: ExperimentalDesign; + private block_design_type: string; + public available_designs: string[] + public block_design_subtype: string = "" + private initialSelection = [] + private factor_values: string[] = [] + private obs_unit_factor_values: {} = {} + observation_level: string = "" + factors_col = [ + 'LightCoral', + 'lightblue', + 'Silver', + 'lightgreen', + 'Gainsboro', + 'LightPink', + 'Orange', + 'DarkKhaki', + 'AntiqueWhite', + 'CornflowerBlue', + 'DarkMagenta', + 'LavenderBlush', + 'Turquoise' + ] + my_bg_colors = {} + observation_levels = [ + { + "levelName": "study", + "levelOrder": 1 + }, + { + "levelName": "rep", + "levelOrder": 2 + }, + { + "levelName": "block", + "levelOrder": 3 + }, + { + "levelName": "row", + "levelOrder": 4 + }, + { + "levelName": "column", + "levelOrder": 5 + }, + { + "levelName": "plot", + "levelOrder": 6 + } + ] + selection = new SelectionModel(true, this.initialSelection /* multiple */); + panel_disabled: boolean = true + panel_expanded: boolean = false + selected_material: ExperimentalFactorInterface; + private dataSource: MatTableDataSource; + + private displayedColumns: string[] = ['Experimental Factor description', 'Experimental Factor values', 'Experimental Factor accession number', 'Experimental Factor type', 'select']; + contextMenuPosition = { x: '0px', y: '0px' }; + helpMenuPosition = { x: '0px', y: '0px' }; + + loaded: boolean = false + block_index: number = 0; + + constructor( + private globalService: GlobalService, + private alertService: AlertService, + public dialogRef: MatDialogRef, + private router: Router, + public dialog: MatDialog, + private _cdr: ChangeDetectorRef, + @Inject(MAT_DIALOG_DATA) public data: DialogData + ) { + this.model_id = this.data.model_id + this.model_type = this.data.model_type + this.parent_id = this.data.parent_id + this.total_available_plots = this.data.total_available_plots + this.role = this.data.role + this.grand_parent_id = this.grand_parent_id + this.available_designs = this.data.available_designs + this.group_key = this.data.group_key + console.log(this.available_designs) + this.design = this.data.design + this.total_blocks_per_row = this.data.total_blocks_per_row + this.block_design_type = this.data.block_design_type + this.total_columns_per_block = this.data.total_columns_per_block + + this.design.Blocking.value.forEach(block => { + this.total_available_blocks += 1 + /* block['Plot design'].value.forEach(plot => { + this.total_available_plots += 1 + }) */ + }); + + } + + async ngOnInit() { + this.dataSource = new MatTableDataSource([]); + //console.log(this.parent_id) + await this.set_all_experimental_factors() + this.loaded = true + } + async set_all_experimental_factors() { + var data = await this.globalService.get_all_experimental_factors(this.parent_id.split('/')[1]).toPromise(); + console.log(data); + if (data.length > 0) { + this.dataSource = new MatTableDataSource(data); + //console.log(this.dataSource); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + } + + /* EXPERIMENTAL FACTOR TABLE */ + rowToggle(row) { + this.selection.toggle(row) + console.log(this.selection.selected) + if (this.selection.selected.length === 0) { + this.panel_disabled = true + } + else { + this.panel_disabled = false + this.factor_values = this.selection.selected[0]['Experimental Factor values'].split(";") + } + } + + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); this.panel_disabled = false + } + public handlePageBottom(event: PageEvent) { + this.paginator.pageSize = event.pageSize; + this.paginator.pageIndex = event.pageIndex; + this.paginator.page.emit(event); + } + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } + + add_experimental_factor(template: boolean = false) { + let user = JSON.parse(localStorage.getItem('currentUser')); + //let exp_factor: ExperimentalFactor = new ExperimentalFactor() + if (template) { + const dialogRef = this.dialog.open(TemplateSelectionComponent, { disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'experimental_factor', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) + result = Object.keys(result).filter(key => !key.startsWith("_")).reduce((obj, key) => { obj[key] = result[key]; return obj; }, {}); + let exp_factor: ExperimentalFactor = result + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + this.ngOnInit(); + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + return true; + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + return false; + } + } + ); + } + }); + } + else { + const formDialogRef = this.dialog.open(FormGenericComponent, { disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id: this.parent_id, formData: {}, mode: "preprocess" } }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let exp_factor: ExperimentalFactor = result["formData"]["form"] + + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + this.ngOnInit() + } + }); + } + } + }); + } + } + go_to_exp_factor_form() { + //this.dialogRef.close() + const formDialogRef = this.dialog.open(FormGenericComponent, { disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id: this.parent_id, formData: {}, mode: "preprocess" } }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let exp_factor: ExperimentalFactor = result["formData"]["form"] + + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + this.ngOnInit() + // this.reloadComponent() + } + }); + } + } + }); + + //this.router.navigate(['/materialform'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: "", model_type: 'biological_material', mode: "create", role:this.role, grand_parent_id:this.grand_parent_id, group_key:this.group_key } }); + } + /** Whether the number of selected elements matches the total number of rows. */ + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected == numRows; + } + + /* OBSERVATION LEVEL SELECTION */ + + onObservationLevelChange(value) { + //check if mulitple else fill as many as possible + this.observation_level = value + if (this.observation_level === 'study') { + } + else if (this.observation_level === 'rep') { + } + else if (this.observation_level === 'block') { + if (this.total_available_blocks % this.get_factor_values.length === 0) { + let total_needed_colors = this.get_factor_values.length + for (let index = 0; index < this.total_available_blocks; index++) { + const random = Math.floor(Math.random() * this.get_factor_values.length); + console.log(random, this.get_factor_values[random]); + this.my_bg_colors[index + 1] = this.factors_col[random] + } + } + else { + + } + + } + else if (this.observation_level === 'row') { + } + else if (this.observation_level === 'column') { + + } + //plot + else { + console.log(this.total_available_plots) + if (this.total_available_plots % this.get_factor_values.length === 0) { + let total_needed_colors = this.get_factor_values.length + for (let index = 0; index < this.total_available_plots; index++) { + const random = Math.floor(Math.random() * this.get_factor_values.length); + console.log(random, this.get_factor_values[random]); + this.my_bg_colors[index + 1] = this.factors_col[random] + } + } + else { + + } + } + console.log(this.my_bg_colors) + } + + + + + + /* GRID */ + + + get_associated_material_source(_pd: PlotDesign) { + if (_pd['Associate_material_source'].value !== null) { + return _pd['Plot number'].value + ": " + _pd['Associate_material_source'].value + } + else { + return _pd['Plot number'].value + ": No material defined" + } + } + get_background_code_color(index: number) { + return this.factors_col[index + 1] + } + shuffle(t) { + let last = t.length + let n + while (last > 0) { + n = this.rand(last) + this.swap(t, n, --last) + } + } + + private rand = n => + Math.floor(Math.random() * n) + + swap(t, i, j) { + let q = t[i] + t[i] = t[j] + t[j] = q + return t + } + change_design_subtype(e) { + console.log(e) + console.log(e.value) + this.block_design_subtype = e.value + // Factor values are equally distributed among each plot in each block (full random) + if (this.block_design_subtype === 'completely randomized design') { + if (this.total_available_plots % this.get_factor_values.length === 0) { + let my_values = [] + for (let index = 0; index < this.get_factor_values.length; index++) { + /* console.log(this.total_available_plots) + let factor_ratio:number=this.total_available_plots / this.get_factor_values.length + console.log(factor_ratio) */ + for (let j = 0; j < this.total_available_plots / this.get_factor_values.length; j++) { + // console.log("factor index ", index, "plot index ", j) + my_values.push(this.get_factor_values[index]) + } + } + this.shuffle(my_values) + for (let j = 0; j < my_values.length; j++) { + this.my_bg_colors[j + 1] = {'color':this.factors_col[indexOf(this.get_factor_values,my_values[j])],"factor_value":my_values[j]} + this.obs_unit_factor_values[j+1]=my_values[j] + } + /* console.log(this.my_bg_colors) + console.log(my_values) + console.log(this.obs_unit_factor_values) */ + } + else { + //some plots will not be treated + + } + + } + else if (this.block_design_subtype === 'Latin square') { + // Test that the number of plots is the square of the number of treatments + this.printLatin(4) + if (this.factor_values.length * this.factor_values.length === this.total_available_plots) { + + } + else { + this.alertService.error("you cannot use this design due to uncorrect ratio between factor values and plot number") + } + } + // one factor value per block, if 4 blocks and 2 factor values => 2 block with factor value 1, 2 blocks with factor valeu + else if (this.block_design_subtype === 'Randomized complete block design') { + if (this.total_available_plots % this.get_factor_values.length === 0) { + let total_needed_colors = this.get_factor_values.length + for (let index = 0; index < this.total_available_plots; index++) { + const random = Math.floor(Math.random() * this.get_factor_values.length); + console.log(random, this.get_factor_values[random]); + this.my_bg_colors[index + 1] = this.factors_col[random] + } + } + } + + else if (this.block_design_subtype === 'Balanced incomplete design') { + if (this.total_available_blocks >= this.factor_values.length) { + if (this.total_available_plots < this.factor_values.length) { + + } + else { + + this.alertService.error("You cannot performed balanced incomplete with this configuration !!! \n Total number of plots must be lower than treament (factor) values") + this.block_design_subtype = "" + } + + } + else { + this.alertService.error("You cannot performed balanced incomplete with this configuration !!! ") + this.block_design_subtype = "" + } + } + //partially balance block design + else { + this.alertService.error("this deign is not yet implemented !!! ") + this.block_design_subtype = "" + + } + } + printLatin(n:number){ + // A variable to control the rotation + // point. + let str='' + let k = n+1; + for (let i = 1; i < n; i++) { + let temp = k; + while (temp <= n){ + str+=temp+'\n' + temp++; + } + for (let j = 1; j < n; j++) { + str+=j+'\t' + } + k-- + str+='\n' + + } + console.log(str) + } + + dispatch_again() { + this.my_bg_colors={} + // Factor values are equally distributed among each plot in each block (full random) + if (this.block_design_subtype === 'completely randomized design') { + if (this.total_available_plots % this.get_factor_values.length === 0) { + let my_values = [] + for (let index = 0; index < this.get_factor_values.length; index++) { + /* console.log(this.total_available_plots) + let factor_ratio:number=this.total_available_plots / this.get_factor_values.length + console.log(factor_ratio) */ + for (let j = 0; j < this.total_available_plots / this.get_factor_values.length; j++) { + //console.log("factor index ", index, "plot index ", j) + my_values.push(this.get_factor_values[index]) + } + } + //console.log(my_values) + this.shuffle(my_values) + //console.log(my_values) + for (let j = 0; j < my_values.length; j++) { + this.my_bg_colors[j + 1] = {'color':this.factors_col[indexOf(this.get_factor_values,my_values[j])],"factor_value":my_values[j]} + } + //this.my_bg_colors[index + 1] = this.factors_col[random] + + + /* let total_needed_colors = this.get_factor_values.length + for (let index = 0; index < this.total_available_blocks; index++) { + const random = Math.floor(Math.random() * this.get_factor_values.length); + console.log(random, this.get_factor_values[random]); + this.my_bg_colors[index + 1] = this.factors_col[random] + } */ + } + else { + //some plots will not be treated + + } + + } + else if (this.block_design_subtype === 'Latin square') { + // Test that the number of plots is the square of the number of treatments + if (this.factor_values.length * this.factor_values.length === this.total_available_plots) { + + } + else { + this.alertService.error("you cannot use this design due to uncorrect ratio between factor values and plot number") + } + } + // one factor value per block, if 4 blocks and 2 factor values => 2 block with factor value 1, 2 blocks with factor valeu + else if (this.block_design_subtype === 'Randomized complete block design') { + if (this.total_available_plots % this.get_factor_values.length === 0) { + let total_needed_colors = this.get_factor_values.length + for (let index = 0; index < this.total_available_plots; index++) { + const random = Math.floor(Math.random() * this.get_factor_values.length); + console.log(random, this.get_factor_values[random]); + this.my_bg_colors[index + 1] = this.factors_col[random] + } + } + } + + else if (this.block_design_subtype === 'Balanced incomplete design') { + if (this.total_available_blocks >= this.factor_values.length) { + if (this.total_available_plots < this.factor_values.length) { + + } + else { + + this.alertService.error("You cannot performed balanced incomplete with this configuration !!! \n Total number of plots must be lower than treament (factor) values") + this.block_design_subtype = "" + } + + } + else { + this.alertService.error("You cannot performed balanced incomplete with this configuration !!! ") + this.block_design_subtype = "" + } + } + //partially balance block design + else { + this.alertService.error("this deign is not yet implemented !!! ") + this.block_design_subtype = "" + + } + } + get_background_color(index: number, subtype: string = "") { + /* console.log(index) + if (subtype === 'completely randomized design') { + console.log(subtype) + } + else if (subtype === 'Randomized complete block design') { + console.log(subtype) + } + else if (subtype === 'Balanced incomplete design') { + console.log(subtype) + } + else if (subtype === 'Partially balanced design') { + console.log(subtype) + } + else if (subtype === 'Latin square') { + console.log(subtype) + } + else { + console.log(subtype) + } */ + return this.my_bg_colors[index + 1]['color'] + + + } + get_block_background_color(index: number, subtype: string = ""){ + if (subtype === 'completely randomized design') { + console.log(subtype) + return 'blue' + } + + } + get get_design(): ExperimentalDesign { return this.design } + get get_observation_level() { return this.observation_level } + get get_factor_values(): string[] { return this.factor_values } + get get_displayedColumns() { return this.displayedColumns } + get get_dataSource() { return this.dataSource } + get get_parent_id() { return this.parent_id } + get get_block_design_subtype() { return this.block_design_subtype } + onClickTour(help_mode: boolean = false, step: number) { + } + + display_block(_block: BlockDesignInterface) { + this.block_index = _block['Block number'].value - 1 + } + + onNoClick(): void { + this.dialogRef.close({ event: "Cancel", selected_material: null }); + } + onOkClick(): void { + this.dialogRef.close({ event: "Confirmed", selected_experimental_factor: this.selection.selected,block_design_subtype:this.block_design_subtype,experimental_factor_values:this.my_bg_colors}); + } + +} diff --git a/src/app/modules/application/dialogs/associate-observation-unit.component.html b/src/app/modules/application/dialogs/associate-observation-unit.component.html index 2ad19bbd..373d8af6 100644 --- a/src/app/modules/application/dialogs/associate-observation-unit.component.html +++ b/src/app/modules/application/dialogs/associate-observation-unit.component.html @@ -1,50 +1,184 @@

    Extract Observation units from design

    -
    + + +

    Define observation units

    +

    + In this dialog, you can define observation units based on existing material defined in your experimental design structure. + By defining level of observation in this specific design, you will create subsequents point of observation also known as observation unit +

    + + +

    Create a new set of observation units

    +

    Depending on the design you've selected, differents level of observation are possible

    +

    In your case, you have {{total_available_plots}} plots in your experimental design.

    +

    Do you want to extract {{total_available_plots}} observation units (one per plot)? +
    To do so, please select plot level in list below
    +

    +

    Define Observation unit level

    + + + + + + Help + + +
    +

    + 1. Select level of observations (observation unit)
    + 2. Define observation units ids
    + 3. Click on to create corresponding observation units.
    + 4. Click on button to link each observation unit with the corresponding level in your experimental design
    +

    +
    +
    +
    +

    Select level of observations

    + + +
    +

    You have selected {{get_observation_unit_level}} level and consequently preload + {{return_data.observation_units.length}} observation units in your study
    + associated with {{return_data.biological_materials.length*return_data.biological_materials[0].length}} biological + materials. +

    -

    You have {{total_available_plots}} plots in your experimental design.

    -

    Do you want to extract {{total_available_plots}} observation units (one per plot)? To do so, select plot level in list below

    -

    Define Observation unit level

    - -

    Select levels of observations

    - + + + + + Global options + + +

    External ID

    + +

    + You can use your own observation unit ID by selecting Paste ids. +

    +
    +
    + + Autogenerate external ids + Paste external ids + +
    + + +

    you are ready to autogenerate external Ids for {{return_data.observation_units.length}} observation units !!

    +
    + +

    Paste your list of Ids here !! + Each Id has to be separated by a new line !! + Take care to have the same number of line than the total observation units

    + + +
    +
    -
    -

    You have selected {{get_observation_unit_level}} level and consequently preload {{return_data.observation_units.length}} observation units in your study
    - associated with {{return_data.biological_materials.length*return_data.biological_materials[0].length}} biological materials .

    +

    Observation unit ID

    - Click on to create corresponding observation units.
    - Click on button to link each observation unit with the corresponding level in your experimental design
    + You can use your own observation unit ID by selecting Paste ids.

    +
    +
    + + Autogenerate ids + Paste ids + +
    + + +

    you are ready to autogenerate Ids for {{return_data.observation_units.length}} observation units !!

    +
    + +

    Paste your list of Ids here !! + Each Id has to be separated by a new line !! + Take care to have the same number of line than the total observation units

    + + +
    +
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - You have sucessfully extracted observations -
    -
    + + + + + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + You have successfully extracted observation units +
    +
    -
    - + \ No newline at end of file diff --git a/src/app/modules/application/dialogs/associate-observation-unit.component.ts b/src/app/modules/application/dialogs/associate-observation-unit.component.ts index c276a338..108722fe 100644 --- a/src/app/modules/application/dialogs/associate-observation-unit.component.ts +++ b/src/app/modules/application/dialogs/associate-observation-unit.component.ts @@ -14,6 +14,7 @@ import * as uuid from 'uuid'; import { cpuUsage } from 'process'; import { first, switchMap, takeUntil } from 'rxjs/operators'; import { timer } from 'rxjs'; +import { SelectionComponent } from './selection.component'; interface DialogData { model_id: string; mode:string; @@ -21,7 +22,6 @@ interface DialogData { parent_id: string; model_type: string; material_id:string; - total_available_plots:number; design:ExperimentalDesign; } @@ -34,71 +34,77 @@ export class AssociateObservationUnit implements OnInit { private model_id: string; private model_key: string; private mode: string; + private existing_observation_units: [] model_type: string; material_id:string + private already_there:string[]=[] private parent_id: string; plot_dict={} return_data = { "observation_units": [], "biological_materials": [], "samples": [], "experimental_factors": [] } design:ExperimentalDesign; total_available_plots:number=0 - observation_unit_level:string="" + total_available_blocks:number=0 current_material_id:string="" biological_model:BiologicalMaterialFullInterface; + observation_unit_level:string="" + //study, block, sub-block, plot, sub-plot, pot, plant observation_levels= [ { "levelName": "study", "levelOrder": 1 }, { - "levelName": "field", + "levelName": "block", "levelOrder": 2 }, { - "levelName": "entry", + "levelName": "sub-block", "levelOrder": 3 }, { - "levelName": "rep", + "levelName": "plot", "levelOrder": 4 }, { - "levelName": "block", + "levelName": "sub-plot", "levelOrder": 5 }, + { - "levelName": "sub-block", + "levelName": "pot", "levelOrder": 6 }, - { - "levelName": "plot", - "levelOrder": 7 - }, - { - "levelName": "sub-plot", - "levelOrder": 8 - }, { "levelName": "plant", - "levelOrder": 9 - }, - { - "levelName": "pot", - "levelOrder": 10 + "levelOrder": 7 }, { "levelName": "sample", - "levelOrder": 11 + "levelOrder": 8 } ] loaded:boolean=false building:boolean=false built: boolean=false; + labelPosition_obsID: 'autogenerate ids' | 'paste ids' = 'autogenerate ids'; + labelPosition_obs_extID: 'autogenerate ids' | 'paste ids' = 'autogenerate ids'; + + + autogenerateIsChecked: boolean = false + ef_data: any; + experimental_factor_id: string=""; + experimental_factor_value: string=""; + ExternalID:string + pasted_external_ids:string[]=[] + pasted_ids:string[]=[] + constructor( private globalService: GlobalService, public dialogRef: MatDialogRef, private _cdr: ChangeDetectorRef, private alertService:AlertService, + public dialog: MatDialog, @Inject(MAT_DIALOG_DATA) public data: DialogData ) { this.model_id = this.data.model_id @@ -106,38 +112,201 @@ export class AssociateObservationUnit implements OnInit { this.model_type = this.data.model_type this.parent_id = this.data.parent_id this.material_id=this.data.material_id - this.total_available_plots=this.data.total_available_plots - this.design=this.data.design this.mode=this.data.mode - console.log(this.design) + this.design=this.data.design + + this.design.Blocking.value.forEach(block=>{ + this.total_available_blocks+=1 + block['Plot design'].value.forEach(plot=>{ + this.total_available_plots+=1 + }) + }); this.building=false this.loaded=false this.built=false - + this.existing_observation_units=[] + this.ef_data=[] } async ngOnInit() { console.log(this.material_id) console.log(this.parent_id) + this.existing_observation_units=await this.globalService.get_type_child_from_parent('studies', this.parent_id.split('/')[1], 'observation_units').toPromise()//.then( this.biological_model= (await this.globalService.get_biological_material_by_key(this.material_id.split('/')[1]).toPromise()).data console.log(this.biological_model) + console.log(this.existing_observation_units) } + onSelectObservationUnit(event){ + console.log(event) + let current_obs_unit=this.existing_observation_units.filter(obs_unit=>obs_unit['_id']===event)[0] + this.observation_unit_level=current_obs_unit['Observation unit type'][0] + + } + get get_existing_observation_units(){ + return this.existing_observation_units + } + + get get_already_there(){ + return this.already_there + } + get_experimental_factor() { + return this.ef_data + } + onIDAdd(event){ + console.log(event) + + } + addFactorValues(factor_value: string) { + console.log(factor_value) + } + onTaskAdd(event) { + } + addExperimentalFactor() { + const dialogRef = this.dialog.open(SelectionComponent, + {disableClose: true, width: '1400px', autoFocus: true,restoreFocus: false, maxHeight: '800px', data: { model_id: "", parent_id: this.parent_id, model_type: "experimental_factor", values: [], already_there: [], observation_id: "" } } + ); + dialogRef.afterClosed().subscribe(result => { + if (result) { + + this.alertService.success("experimental factor selected! "); + var experimentalFactorData = result['data'] + for (var i = 0; i < experimentalFactorData.length; i++) { + var ef: ExperimentalFactorDialogModel + ef = experimentalFactorData[i] + ef.efUUID = uuid.v4() + this.experimental_factor_id = ef.efUUID + ef.obsUUID = "" + this.ef_data.push(ef) + } + } + }); + } + + + onInput(content: string, type:string) { + console.log(content) + console.log(content.split("\n")) + if (type==='extid'){ + + if ([...new Set(content.split("\n"))].length!==this.return_data.observation_units.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.return_data.observation_units.length){ + this.alertService.error("you need to have same number of observation IDs than observation units IDs. in your case, you need " +this.return_data.observation_units.length + " observations Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_external_ids=content.split("\n") + + } + } + + } + else{ + if ([...new Set(content.split("\n"))].length!==this.return_data.observation_units.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.return_data.observation_units.length){ + this.alertService.error("you need to have same number of observation IDs than observation units IDs. in your case, you need " +this.return_data.observation_units.length + " observations Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + + } + } + + } + } + onPaste(event: ClipboardEvent, type:string) { + let clipboardData = event.clipboardData; + let content = clipboardData.getData('text'); + + if (type==='extid'){ + + if ([...new Set(content.split("\n"))].length!==this.return_data.observation_units.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.return_data.observation_units.length){ + this.alertService.error("you need to have same number of observation IDs than observation units IDs. in your case, you need " +this.return_data.observation_units.length + " observations Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_external_ids=content.split("\n") + + } + } + + } + else{ + if ([...new Set(content.split("\n"))].length!==this.return_data.observation_units.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.return_data.observation_units.length){ + this.alertService.error("you need to have same number of observation IDs than observation units IDs. in your case, you need " +this.return_data.observation_units.length + " observations Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + + } + } + + } + console.log(content) + } + onObservationUnitLevelChange(value){ console.log(value) this.observation_unit_level=value this.current_material_id=this.design['Associated biological Materials'].value this.return_data = { "observation_units": [], "biological_materials": [], "samples": [], "experimental_factors": [] } - if(value==='plot'){ - + if(value==='study'){ + } + else if (value==='block'){ let bm_list:BiologicalMaterialDialogModel[][]=[] this.design.Blocking.value.forEach(block=>{ + let obs_unit={} + + obs_unit['External ID']="" + obs_unit['Observation Unit factor value']=[] + obs_unit['Observation unit ID']=value+":"+ block['Block number'].value + obs_unit['Observation unit type']=value + obs_unit['Spatial distribution']=value+":"+ block['Block number'].value + let obs_id=uuid.v4() + obs_unit['obsUUID']=obs_id + let sub_bm_list:BiologicalMaterialDialogModel[]=[] block['Plot design'].value.forEach(plot=>{ - let obs_unit={} - let sub_bm_list:BiologicalMaterialDialogModel[]=[] + + this.plot_dict[plot['Plot number'].value]=obs_id + this.load_material(this.biological_model, obs_id, plot.Associate_material_source.value, plot.Associated_biological_material.value).forEach(load_mat=>{ + sub_bm_list.push(load_mat) + }) + }); + bm_list.push(sub_bm_list) + this.return_data.observation_units.push(obs_unit) + }); + console.log(bm_list) + console.log(this.return_data.observation_units) + this.return_data.biological_materials=bm_list + } + else if (value==='sub-block'){ + + } + else if(value==='plot'){ + let bm_list:BiologicalMaterialDialogModel[][]=[] + this.design.Blocking.value.forEach(block=>{ + block['Plot design'].value.forEach(plot=>{ + let obs_unit={} + let sub_bm_list:BiologicalMaterialDialogModel[]=[] obs_unit['External ID']="" - obs_unit['Observation Unit factor value']="" + obs_unit['Observation Unit factor value']=[] obs_unit['Observation unit ID']=value+":"+plot['Plot number'].value obs_unit['Observation unit type']=value obs_unit['Spatial distribution']="block-"+block['Block number'].value+":"+"plot-"+plot['Plot number'].value + ":column-"+plot['Column number'].value @@ -148,19 +317,29 @@ export class AssociateObservationUnit implements OnInit { sub_bm_list.push(load_mat) }) bm_list.push(sub_bm_list) - this.return_data.observation_units.push(obs_unit) //this.load_material(this.biological_model, obs_id, plot.Associate_material_source.value, plot.Associated_biological_material.value) - }) }) - this.return_data.biological_materials=bm_list + this.return_data.biological_materials=bm_list + console.log(this.return_data) + } + else if (value==='sub-plot'){ + } + else if (value==='pot'){ - console.log(this.return_data) + } + else if(value==='plant'){ + + } + //sample + else{ + } this.loaded=true } + load_material(model: BiologicalMaterialFullInterface, obs_uuid:string, material_id:string, biological_material_ids:string[]): BiologicalMaterialDialogModel[] { var data = [] var keys = Object.keys(model); @@ -223,12 +402,24 @@ export class AssociateObservationUnit implements OnInit { async save() { this.building=true if (this.mode === "create") { + if (this.labelPosition_obsID==="paste ids"){ + this.return_data.observation_units.forEach((obs_unit, index)=>{ + obs_unit['Observation unit ID']=this.pasted_ids[index] + }) + } + if (this.labelPosition_obs_extID==="paste ids"){ + this.return_data.observation_units.forEach((obs_unit, index)=>{ + obs_unit['External ID']=this.pasted_external_ids[index] + }) + } + + //timer(0, 5000).pipe( switchMap(() => this.globalService.add_observation_units(this.return_data, this.model_type, this.parent_id)), takeUntil(this.stopPolling) ) const data=await this.globalService.add_observation_units(this.return_data, this.model_type, this.parent_id).toPromise() if (data["success"]) { this.model_id = data["_id"]; - var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " has been successfully integrated in your history !!" + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " object has been successfully integrated in your history !!" this.alertService.success(message) this.building=false this.built=true @@ -270,7 +461,6 @@ export class AssociateObservationUnit implements OnInit { if (data["success"]) { var message = this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " has been successfully updated in your history !!" this.alertService.success(message) - } else { this.alertService.error("this form contains errors! " + data["message"]); @@ -292,7 +482,6 @@ export class AssociateObservationUnit implements OnInit { get get_model_key(){ return this.model_key } - onNoClick(): void { this.dialogRef.close({event:"Cancel", selected_material: null}); } diff --git a/src/app/modules/application/dialogs/associate-observations-measurement.component.css b/src/app/modules/application/dialogs/associate-observations-measurement.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/modules/application/dialogs/associate-observations-measurement.component.html b/src/app/modules/application/dialogs/associate-observations-measurement.component.html new file mode 100644 index 00000000..050a12c1 --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observations-measurement.component.html @@ -0,0 +1,172 @@ +

    Extract Observedd variable measurement from design

    + + + + +

    Define observation units

    +

    + In this dialog, you can define observed variables measurement based on existing observations defined in your experimental design structure. + By defining level of observation in this specific design, you will create subsequents point of observation also known as observation unit +

    + +

    Observations selection table

    + + + + + + + + + + + + + + + + +
    {{displayedObservationsColumns[i]}} {{element[column]}} + + + + + +
    + + +

    Associate experimental measurement with observed variables

    +

    Given the selected observations, you have to feed Linda with the corresponding values

    +

    In your case, you have {{get_observationDataSource.data.length}} observations in your experimental design.

    +
    +

    Define Observation unit level

    + + + + + + Help + + +
    +

    + 1. Select observations to describe
    + 2. Define observed variable measurement (paste values or load from tabular file)
    + 3. Click on to create corresponding measurements.
    + 4. Click on button to link each measurement with the corresponding level in your experimental design
    +

    +
    +
    +
    + + + + + + + Global options + + +

    Observation measurements

    +
    +
    + + Load from files + Paste values + +
    + + + + + +

    Paste your list of values here !!
    + Each value has to be separated by a new line !! + Take care to have the same number of line than the total observations selected !
    + For instance, you need {{this.selection.selected.length}} observation value(s)to match number of samples selected +

    + + +
    +
    + + + + + + +
    +
    + +
    +
    + + + +
    + + +
    +
    \ No newline at end of file diff --git a/src/app/modules/application/dialogs/associate-observations-measurement.component.spec.ts b/src/app/modules/application/dialogs/associate-observations-measurement.component.spec.ts new file mode 100644 index 00000000..ed1ecbaa --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observations-measurement.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AssociateObservationsMeasurementComponent } from './associate-observations-measurement.component'; + +describe('AssociateObservationsMeasurementComponent', () => { + let component: AssociateObservationsMeasurementComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AssociateObservationsMeasurementComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AssociateObservationsMeasurementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/application/dialogs/associate-observations-measurement.component.ts b/src/app/modules/application/dialogs/associate-observations-measurement.component.ts new file mode 100644 index 00000000..89a50ab1 --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observations-measurement.component.ts @@ -0,0 +1,155 @@ +import { SelectionModel } from '@angular/cdk/collections'; +import { ChangeDetectorRef, Component, Inject, OnInit, ViewChild, AfterViewInit } from '@angular/core'; +import { MatDialog, MatDialogRef, MatPaginator, MatTableDataSource, MAT_DIALOG_DATA } from '@angular/material'; +import { ExperimentalDesign } from 'src/app/models/linda/experimental-design'; +import { ObservationInterface } from 'src/app/models/linda/observation'; +import { AlertService, GlobalService } from 'src/app/services'; + +interface DialogData { + model_id: string; + parent_id: string; + model_type: string; + bm_data: []; + material_id: string; + total_available_plots: number; + design: ExperimentalDesign; +} + +@Component({ + selector: 'app-associate-observations-measurement', + templateUrl: './associate-observations-measurement.component.html', + styleUrls: ['./associate-observations-measurement.component.css'] +}) +export class AssociateObservationsMeasurementComponent implements OnInit, AfterViewInit { + //entry params + private model_id: string; + private design: ExperimentalDesign; + private user_key: string; + private result: [] + private model_type: string; + private parent_id: string; + public total_available_plots:number; + + @ViewChild('observationpaginator', { static: true }) observationpaginator: MatPaginator; + + + labelPosition_obsID: 'from files' | 'paste ids' = 'from files'; + pasted_ids:string[]=[] + private observationdataSource: MatTableDataSource; + displayedObservationsColumns: string[] = ['No observations defined', 'select']; + private initialSelection = [] + panel_disabled: boolean = true; + selection = new SelectionModel(true, this.initialSelection /* multiple */); + + constructor( + private globalService: GlobalService, + private alertService: AlertService, + public dialogRef: MatDialogRef, + private _cdr: ChangeDetectorRef, + public dialog: MatDialog, + @Inject(MAT_DIALOG_DATA) public data: DialogData + ) { + this.model_id = this.data.model_id + this.model_type = this.data.model_type + this.parent_id = this.data.parent_id + this.total_available_plots = this.data.total_available_plots + this.design = this.data.design + + this.observationdataSource = new MatTableDataSource([]) + } + + ngOnInit() { + if(this.design.get_associated_observations()[0]!==undefined){ + this.displayedObservationsColumns = Object.keys(this.design.get_associated_observations()[0]).filter(key => !key.includes('UUID')) + this.displayedObservationsColumns.push('select') + console.log(this.displayedObservationsColumns) + this.observationdataSource = new MatTableDataSource(this.design.get_associated_observations()); + this.observationdataSource.paginator = this.observationpaginator; + } + } + ngAfterViewInit() { + this.observationdataSource.paginator = this.observationpaginator; + this._cdr.detectChanges() + } + onInput(content: string) { + + if (content.split("\n").length!==this.selection.selected.length){ + + console.log([...new Set(content.split("\n"))].length) + + this.alertService.error("you need to have same number of observation IDs than sample selected. in your case, you need " +this.selection.selected.length + " samples Ids") + + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + + } + + } + + onPaste(event: ClipboardEvent) { + + let clipboardData = event.clipboardData; + let content = clipboardData.getData('text'); + console.log(content) + + if (content.split("\n").length!==this.selection.selected.length){ + this.alertService.error("you need to have same number of observation values than total observations selected. in your case, you need " +this.selection.selected.length + " observation values") + } + else{ + this.alertService.success("Correct number of observation values !! ") + this.pasted_ids=content.split("\n") + } + + + } + async save() { + if (this.selection.selected.length!==this.pasted_ids.length || this.selection.selected.length===0){ + this.alertService.error("not valid form ") + + } + else{ + this.selection.selected.forEach((obs, index) => { + console.log(this.pasted_ids[index]) + console.log(obs['Observation ID']) + this.observationdataSource.data.filter(obsv=>obsv['Observation ID']===obs['Observation ID'])[0]['Observed variable measure']=this.pasted_ids[index] + console.log(this.observationdataSource.data.filter(obsv=>obsv['Observation ID']===obs['Observation ID'])[0]) + }) + this.alertService.success("You have successfully link your measurement to corresponding observations!! ") + //return true; + } + + }; + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.observationdataSource.data.length; + return numSelected == numRows; + } + rowToggle(row) { + this.selection.toggle(row) + if (this.selection.selected.length === 0) { + this.panel_disabled = true + } + else ( + this.panel_disabled = false + ) + } + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.observationdataSource.data.forEach(row => this.selection.select(row)); this.panel_disabled = false + } + + get get_observationDataSource() { + return this.observationdataSource + } + onNoClick(): void { + this.dialogRef.close({event:"Cancel", selected_material: null}); + } + onOkClick(): void { + this.dialogRef.close({event:"Confirmed", observation_unit_id: this.model_id}); + } + +} diff --git a/src/app/modules/application/dialogs/associate-observed-variable.component.css b/src/app/modules/application/dialogs/associate-observed-variable.component.css new file mode 100644 index 00000000..20c72b47 --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observed-variable.component.css @@ -0,0 +1,43 @@ +span.span-project{ + margin-left:5px; + margin-right:5px; + height:100%; + width:1px; + border-top:1px solid gray; + } + + .nga-card-step { + box-shadow: 0 4px 4px rgba(0, 0, 0, .04), 0 3px 3px rgba(0, 0, 0, .09); + margin: 4px; + cursor: pointer; + text-decoration: none; + } +/* td.mat-cell{ + background-color: bisque; + } */ + /* tr.mat-row:hover{ + box-shadow: 0 10px 10px rgba(0, 0, 0, .9), 0 4px 4px rgba(0, 0, 0, .13); + border-radius: 20px; + color: #0d6efd; + } */ + + .nga-card-step:hover { + box-shadow: 0 10px 10px rgba(0, 0, 0, .09), 0 4px 4px rgba(0, 0, 0, .13); + border-radius: 4px; + color: #0d6efd; + + } + + .nga-card-step a { + color: black; + text-decoration: none; + } + + .nga-card-step a:hover { + color: #0d6efd; + text-decoration: none; + } + + th.mat-header-cell.edit_col { + text-align: right; + } diff --git a/src/app/modules/application/dialogs/associate-observed-variable.component.html b/src/app/modules/application/dialogs/associate-observed-variable.component.html new file mode 100644 index 00000000..9ede5e1e --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observed-variable.component.html @@ -0,0 +1,263 @@ +

    Select observations

    + + + +
    +
    +

    Observation details

    +

    You have {{total_available_plots}} plots in this experimental design. + Take care to assign observations in respect of design capability !! +

    +

    Observed variables and experimental design

    +

    + Definition: An observed variable describes how a measurement has been made. + It typically takes the form of a measured characteristic of the observation unit + (plant or environmental trait), associated to the method and unit of measurement. +

    +

    + There are two types of observations in Linda. + A destructive observation is an observation where the integrity of the biological material is affected following the samples taken for downstream analyzes (leaves, fruits, whole plant, etc.). + A contrario, a non desctructive obsservation does not impact the integrity of the biological material (plant height measurement, etc) +

    +

    Observed variable and type of observation

    +

    Destructive observations

    +

    + Destructive observations are available for downstream sample analysis. + Select samples that will be observed and choose also the corresponding observed trait. +

    + +

    Non destructive observations

    +

    + Non Destructive observations consists of observed trait that leave the plant intact. + Select biological material that will be observed and choose also the corresponding observed trait. +

    + +

    Select type of observations

    + + + +

    Samples selection table

    + + + + + + + + + + + + + + +
    {{displayedSamplesColumns[i]}} {{element[column]}} + + + + + +
    + + +

    biological material selection table

    + + + + + + + + + + + + + + + +
    {{displayedMaterialColumns[i]}} {{element[column]}} + + + + + +
    + + + + + + + + Global options + + +

    Observation date

    + +

    Observation description

    + + +

    Observation ID

    + + +

    + You can use your own observation IDs by selecting Paste observation ids. +

    +
    + +
    + + Autogenerate observation unique ids + Paste observation unique ids + +
    + + +

    + you are ready to autogenerate observations Ids for {{get_total}} biological materials selected !! +

    +

    + you are ready to autogenerate observations Ids for {{get_total}} samples selected !! +

    +
    + +

    Paste your list of Ids here !!
    + Each Id has to be separated by a new line !! + Take care to have the same number of line than the total biological materials selected !
    + For instance, you need {{get_total}} observations Id(s) to match number of materials selected +

    +

    Paste your list of Ids here !!
    + Each Id has to be separated by a new line !! + Take care to have the same number of line than the total biological materials selected !
    + For instance, you need {{get_total}} observation Id(s)to match number of samples selected +

    + + +
    +
    + + +
    + +
    +
    +

    You do not have any samples defined in this study, you need to add first in the experimental + design page and then you can create desctrucive rom this material.

    +
    +
    + +
    +
    + +
    +
    +

    You do not have any samples defined in this study, you need to add first in the experimental + design page and then you can create desctrucive rom this material.

    +
    +
    + +
    +
    +

    You do not find corresponding trait, create one

    + + + +
    +
    + + + + + + + +
    +
    + + + + + + + + + + + Filter + + +

    Observed variable table

    + + + + + + + + + + + + + + + +
    {{displayedColumns[i]}} {{element[column]}} + + + + + +
    + + +
    +
    + + +
    +

    Now You are ready to add {{get_total}} observations in your experimental design. +
    + A datafile will be created in which you can further add your measuremement values (e.g plant heigth or all plot + observed) +
    +

    + +
    +
    + +
    + + +
    +
    \ No newline at end of file diff --git a/src/app/modules/application/dialogs/associate-observed-variable.component.ts b/src/app/modules/application/dialogs/associate-observed-variable.component.ts new file mode 100644 index 00000000..e89b8249 --- /dev/null +++ b/src/app/modules/application/dialogs/associate-observed-variable.component.ts @@ -0,0 +1,468 @@ +import { Component, OnInit, Inject, ViewChild, ChangeDetectorRef, AfterViewInit } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { GlobalService, AlertService } from '../../../services'; +import { SelectionModel } from '@angular/cdk/collections'; +import { MatSort } from '@angular/material/sort'; +import { MatTable, MatTableDataSource } from '@angular/material/table'; +import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { Router } from '@angular/router'; +import { ObservedVariable, ObservedVariableInterface } from 'src/app/models/linda/observed-variable'; +import { FormGenericComponent } from './form-generic.component'; +import { TemplateSelectionComponent } from './template-selection.component'; +import { first } from 'rxjs/operators'; +import { MatMenuTrigger } from '@angular/material'; +import { ExperimentalDesign } from 'src/app/models/linda/experimental-design'; +import { SampleInterface } from 'src/app/models/linda/sample'; +import { Observation, ObservationInterface } from 'src/app/models/linda/observation'; +import { BiologicalMaterialInterface } from 'src/app/models/linda/biological-material'; +import { BiologicalMaterialDialogModel } from 'src/app/models/biological_material_models'; + +interface DialogData { + model_id: string; + parent_id: string; + model_type: string; + bm_data: []; + material_id: string; + total_available_plots: number; + design: ExperimentalDesign; +} +const OBSERVED_VARIABLE_ELEM: ObservedVariableInterface[] = [] +const SAMPLE_ELEM: SampleInterface[] = [] +const BM_ELEMENT_DATA: BiologicalMaterialDialogModel[] = [] + +@Component({ + selector: 'app-associate-observed-variable', + templateUrl: './associate-observed-variable.component.html', + styleUrls: ['./associate-biological-material.component.css'] +}) + +export class AssociateObservedVariable implements OnInit { + + @ViewChild(MatMenuTrigger, { static: false }) contextMenu: MatMenuTrigger; + @ViewChild(MatMenuTrigger, { static: false }) userMenu: MatMenuTrigger; + @ViewChild(MatMenuTrigger, { static: false }) helpMenu: MatMenuTrigger; + @ViewChild(MatMenuTrigger, { static: false }) userMenusecond: MatMenuTrigger; + @ViewChild(MatMenuTrigger, { static: false }) investigationMenu: MatMenuTrigger; + contextMenuPosition = { x: '0px', y: '0px' }; + userMenuPosition = { x: '0px', y: '0px' }; + userMenusecondPosition = { x: '0px', y: '0px' }; + investigationMenuPosition = { x: '0px', y: '0px' }; + helpMenuPosition = { x: '0px', y: '0px' }; + + + autogenerateIsChecked: boolean = false + ObservationDescription: string = ""; + //@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; + pasted_ids:string[]=[] + @ViewChild('obsvarpaginator', { static: true }) obsvarpaginator: MatPaginator; + @ViewChild('samplepaginator', { static: true }) samplepaginator: MatPaginator; + @ViewChild('matpaginator', { static: true }) matpaginator: MatPaginator; + @ViewChild(MatSort, { static: true }) sort: MatSort; + ///@ViewChild(MatTable, { static: false }) table: MatTable + labelPosition_observation_ID: 'autogenerate ids' | 'paste ids' = 'autogenerate ids'; + + private model_id: string; + private design: ExperimentalDesign; + private user_key: string; + private result: [] + private model_type: string; + private parent_id: string; + search_type: string + //sampledataSource = new MatTableDataSource(SAMPLE_ELEM); + private sampledataSource: MatTableDataSource; + //private sampledataSource:MatTableDataSource + dataSource = new MatTableDataSource(OBSERVED_VARIABLE_ELEM); + materialdataSource = new MatTableDataSource(BM_ELEMENT_DATA); + //displayedColumns: string[] = ['No Observed variables defined', 'select']; + + //displayedMaterialsColumns: string[] = ['No Materials defined', 'select']; + private initialSampleSelection = [] + sampleSelection = new SelectionModel(true, this.initialSampleSelection /* multiple */); + private initialSelection = [] + selection = new SelectionModel(false, this.initialSelection /* multiple */); + private initialMatSelection = [] + matSelection = new SelectionModel(true, this.initialMatSelection /* multiple */); + panel_disabled: boolean = false; + sample_panel_disabled: boolean = false; + mat_panel_disabled: boolean = false; + loaded: boolean = false + sampleloaded: boolean = false + matloaded: boolean = false + showSample: boolean = false + showMat: boolean = false + total_available_plots: number = 0 + observations: ObservationInterface[]; + observation_type: string = ""; + samples: [] + ObservationDate: Date; + material_id: string = "" + associated_materials: BiologicalMaterialDialogModel[] = [] + private bm_data: []; + displayedSamplesColumns: string[] = ['No Samples defined', 'select']; + displayedMaterialColumns: string[] = ['biologicalMaterialId', 'materialId', 'genus', 'species', 'lindaID', 'select']; + displayedColumns: string[] = ['Trait', 'Method', 'Variable ID', 'Variable name', 'Scale', 'select']; + + + + constructor( + private globalService: GlobalService, + private alertService: AlertService, + public dialogRef: MatDialogRef, + private router: Router, + private _cdr: ChangeDetectorRef, + public dialog: MatDialog, + @Inject(MAT_DIALOG_DATA) public data: DialogData + ) { + this.model_id = this.data.model_id + this.model_type = this.data.model_type + this.parent_id = this.data.parent_id + this.material_id = this.data.material_id + this.bm_data = this.data.bm_data + this.total_available_plots = this.data.total_available_plots + + this.design = this.data.design + this.sampleloaded = false + + //set_associated_materials() + + this.sampledataSource = new MatTableDataSource([]) + this.dataSource = new MatTableDataSource([]) + //this.sampledataSource = new MatTableDataSource(this.design.get_associated_samples()) + //this.sampledataSource.paginator= this.samplepaginator + //console.log(this.sampledataSource) + this.observations = [] + } + /* async set_associated_materials() { + this.associated_materials=await this.globalService.get_biological_material_by_key(this.associated_material_id.split("/")[1]).toPromise() + console.log(materials) + } */ + + + async ngOnInit() { + await this.set_all_observed_variables() + if(this.design.get_associated_samples()[0]!==undefined){ + this.displayedSamplesColumns = Object.keys(this.design.get_associated_samples()[0]).filter(key => !key.includes('UUID')) + this.displayedSamplesColumns.push('select') + this.sampledataSource = new MatTableDataSource(this.design.get_associated_samples()); + this.sampledataSource.paginator = this.samplepaginator; + } + /* else{ + this.displayedSamplesColumns = Object.keys(this.design.get_associated_samples()[0]).filter(key => !key.includes('UUID')) + this.displayedSamplesColumns.push('select') + this.sampledataSource = new MatTableDataSource(this.design.get_associated_samples()); + this.sampledataSource.paginator = this.samplepaginator; + } */ + + this.materialdataSource.data = this.bm_data + this.materialdataSource.sort = this.sort + this.materialdataSource.paginator = this.matpaginator; + console.log(this.materialdataSource.data) + this._cdr.detectChanges() + this.observation_type = "" + //await this.set_all_observed_variables() + } + ngAfterViewInit() { + this.dataSource.sort = this.sort; + this.dataSource.paginator = this.obsvarpaginator; + this.sampledataSource.paginator = this.samplepaginator + this._cdr.detectChanges() + } + onDateAdd(event) { + this.ObservationDate = event.target.value + } + async set_all_observed_variables() { + var data = await this.globalService.get_all_observed_variables(this.parent_id.split('/')[1]).toPromise(); + console.log(data); + if (data.length > 0) { + console.log(Object.keys(data[0])) + //this.displayedColumns = Object.keys(data[0]).filter(key => !key.startsWith('_')) + //this.displayedColumns.push('select') + console.log(data) + this.dataSource.data = data + this.dataSource.sort = this.sort + this.dataSource.paginator = this.obsvarpaginator; + this._cdr.detectChanges() + } + } + + add_data() { + + } + onObservationTypeChange(_observation_type: string) { + this.observation_type = _observation_type + if (this.observation_type === 'Destructive') { + this.showSample = true + this.showMat = false + } + else { + this.showMat = true + this.showSample = false + } + } + + add_observed_variables(template: boolean = false) { + let user = JSON.parse(localStorage.getItem('currentUser')); + //let exp_factor: ExperimentalFactor = new ExperimentalFactor() + console.log(this.model_type) + console.log(this.parent_id) + if (template) { + const dialogRef = this.dialog.open(TemplateSelectionComponent, { disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'observed_variable', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) + var keys = Object.keys(result); + + for (var i = 0; i < keys.length; i++) { + if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { + keys.splice(i, 1); + //var k=this.keys[i] + i--; + } + } + var new_values = {} + keys.forEach(attr => { new_values[attr] = result[attr] }) + + + this.globalService.add(new_values, this.model_type, this.parent_id, false).pipe(first()).toPromise().then( + data => { + if (data["success"]) { + this.ngOnInit(); + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + return true; + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + return false; + } + } + ); + } + }); + } + else { + const formDialogRef = this.dialog.open(FormGenericComponent, { disableClose: true, width: '1400px', data: { model_type: this.model_type, parent_id: this.parent_id, formData: {}, mode: "preprocess" } }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let obs_variable: ObservedVariable = result["formData"]["form"] + this.globalService.add(obs_variable, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + this.ngOnInit() + } + });; + } + } + }); + } + } + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } + isAllSampleSelected() { + const numSelected = this.sampleSelection.selected.length; + const numRows = this.sampledataSource.data.length; + return numSelected == numRows; + } + sampleRowToggle(row) { + this.sampleSelection.toggle(row) + if (this.sampleSelection.selected.length === 0) { + this.panel_disabled = true + } + else ( + this.panel_disabled = false + ) + } + /** Selects all rows if they are not all selected; otherwise clear selection. */ + sampleMasterToggle() { + this.isAllSampleSelected() ? + this.sampleSelection.clear() : + this.sampledataSource.data.forEach(row => this.sampleSelection.select(row)); this.panel_disabled = false + } + isAllMatSelected() { + const numSelected = this.matSelection.selected.length; + const numRows = this.materialdataSource.data.length; + return numSelected == numRows; + } + matRowToggle(row) { + this.matSelection.toggle(row) + if (this.matSelection.selected.length === 0) { + this.panel_disabled = true + } + else ( + this.panel_disabled = false + ) + } + /** Selects all rows if they are not all selected; otherwise clear selection. */ + matMasterToggle() { + this.isAllMatSelected() ? + this.matSelection.clear() : + this.materialdataSource.data.forEach(row => this.matSelection.select(row)); this.panel_disabled = false + } + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected == numRows; + } + rowToggle(row) { + this.selection.toggle(row) + if (this.selection.selected.length === 0) { + this.panel_disabled = true + } + else ( + this.panel_disabled = false + ) + } + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); this.panel_disabled = false + } + get_observation_type() { + return this.observation_type + } + get get_design() { + return this.design + } + get get_sampleDataSource() { + return this.sampledataSource + } + get get_associated_materials(): BiologicalMaterialDialogModel[] { + return this.bm_data + } + onInput(content: string) { + if (this.observation_type === 'Destructive') { + if (content.split("\n").length!==this.sampleSelection.selected.length){ + + console.log([...new Set(content.split("\n"))].length) + + this.alertService.error("you need to have same number of observation IDs than sample selected. in your case, you need " +this.sampleSelection.selected.length + " samples Ids") + + } + else{ + if ([...new Set(content.split("\n"))].length!==this.sampleSelection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + else{ + if ([...new Set(content.split("\n"))].length!==this.matSelection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.matSelection.selected.length){ + this.alertService.error("you need to have same number of sample IDs than biological materials selected. in your case, you need " +this.matSelection.selected.length + " samples Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + } + get get_total():number{ + if (this.observation_type === 'Destructive') { + return this.sampleSelection.selected.length + } + else{ + return this.matSelection.selected.length + + } + } + onPaste(event: ClipboardEvent) { + + let clipboardData = event.clipboardData; + let content = clipboardData.getData('text'); + console.log(content) + if (this.observation_type === 'Destructive') { + if ([...new Set(content.split("\n"))].length!==this.sampleSelection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.sampleSelection.selected.length){ + this.alertService.error("you need to have same number of observation IDs than sample selected. in your case, you need " +this.sampleSelection.selected.length + " samples Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + else{ + if ([...new Set(content.split("\n"))].length!==this.matSelection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.matSelection.selected.length){ + this.alertService.error("you need to have same number of sample IDs than biological materials selected. in your case, you need " +this.matSelection.selected.length + " samples Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + } + onNoClick(): void { + this.dialogRef.close({ event: "Cancel", selected_material: null }); + } + onOkClick(): void { + console.log(this.observations) + console.log(this.selection.selected) + console.log(this.sampleSelection.selected) + this.selection.selected.forEach(obs_var => { + if (this.observation_type === 'Destructive') { + if (this.labelPosition_observation_ID!=='autogenerate ids'){ + this.sampleSelection.selected.forEach((sample, index) => { + console.log(sample) + let obs_uuid = this.pasted_ids[index] + this.observations.push(new Observation(obs_uuid, this.ObservationDescription, this.ObservationDate, true, sample['Sample ID'], sample.obsUUID, obs_var['_id'], obs_var['Scale'], obs_var['Trait'])) + }) + } + else{ + this.sampleSelection.selected.forEach((sample, index) => { + console.log(sample) + let obs_uuid = sample['Sample ID'] + "_obs_" + (index + 1) + this.observations.push(new Observation(obs_uuid, this.ObservationDescription, this.ObservationDate, true, sample['Sample ID'], sample.obsUUID, obs_var['_id'], obs_var['Scale'], obs_var['Trait'])) + }) + } + } + else { + if (this.labelPosition_observation_ID!=='autogenerate ids'){ + this.matSelection.selected.forEach((bm, index) => { + let obs_uuid = this.pasted_ids[index] + this.observations.push(new Observation(obs_uuid, this.ObservationDescription, this.ObservationDate, false, bm.biologicalMaterialId, bm.obsUUID, obs_var['_id'], obs_var['Scale'], obs_var['Trait'])) + }) + } + else{ + this.matSelection.selected.forEach((bm, index) => { + let obs_uuid = bm.biologicalMaterialId + "_obs_" + (index + 1) + this.observations.push(new Observation(obs_uuid, this.ObservationDescription, this.ObservationDate, false, bm.biologicalMaterialId, bm.obsUUID, obs_var['_id'], obs_var['Scale'], obs_var['Trait'])) + }) + + } + /*this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { + let obs_uuid = "sedwfxd" + this.observations.push(new Observation(obs_uuid, 'observation first test', this.ObservationDate, false, 'Not defined', plot.get_observation_uuid(), obs_var['_id'])) + }) + })*/ + } + }); + this.dialogRef.close({ event: "Confirmed", selected_observed_variable: this.selection.selected, observation_type: this.observation_type, observations: this.observations }); + } + +} diff --git a/src/app/modules/application/dialogs/biological-material.component.html b/src/app/modules/application/dialogs/biological-material.component.html index 9fceb918..9e3a3bc8 100644 --- a/src/app/modules/application/dialogs/biological-material.component.html +++ b/src/app/modules/application/dialogs/biological-material.component.html @@ -1,43 +1,176 @@ -

    Generate Biological Material ID

    +

    Biological Material Description

    -

    biological material identifiers

    + + + + + Global configuration options + + + + + Taxon Scientific Name + + + + + +
    + +
    + + + +

    Holding institution

    + + + + + +
    + +
    +
    + + Biological Material Preprocessing + +
    + +
    +
    +
    + + +

    NCBI Taxon

    + + + + + +

    biological material source identifier

    +

    + Definition: An identifier for the source of the biological material, in the form of a key-value pair comprising + the name/identifier of the repository from which the material was sourced plus the accession number + of the repository for that material. Where an accession number has not been assigned, but the material + has been derived from the crossing of known accessions, the material can be defined as follows: + 'mother_accession X father_accession', or, if father is unknown, as 'mother_accession X UNKNOWN'. + For in situ material, the region of provenance may be used when an accession is not available. +

    + + +

    biological material identifiers

    +

    Definition: Code used to identify the biological material in the data file. Should be unique within + the Investigation. Can correspond to experimental plant ID, seed lot ID, etc This material + identification is different from a BiosampleID which corresponds to Observation Unit or + Samples sections +

    +

    + You can use your own Material ID by selecting Paste ids + or simply let Linda create biological material identifier based on material source accession, plant + number and replicate number. +

    +
    +
    + + Autogenerate ids + + Paste ids + +
    + + + Select the number of plants by accession in your study ?
    +
    + Select the number of replicate by accession in your study ?
    + +
    + + + + +
    + +
    +
    + +
    +
    + +
    -

    - You have defined the selected column as Material source ID in the data file called {{data_filename}}.
    - We have allready generated 1 biological material ID by default for each Material ID encountered.
    - Now but you probably want to add more than one biological material by Accession ID. - Select the number of plant by accession in your study ?
    - -

    -
    -
    -

    - You have material source
    +

    + You have defined the selected column as Material source ID in the data file called {{data_filename}}. +
    + We have allready generated 1 biological material ID by default for each Material ID encountered.
    + Now but you probably want to add more than one biological material by Accession ID. + Select the number of plant by accession in your study ?
    + +

    +
    +
    -
    \ No newline at end of file + \ No newline at end of file diff --git a/src/app/modules/application/dialogs/biological-material.component.ts b/src/app/modules/application/dialogs/biological-material.component.ts index 36bdf8c3..2dfb2f37 100644 --- a/src/app/modules/application/dialogs/biological-material.component.ts +++ b/src/app/modules/application/dialogs/biological-material.component.ts @@ -1,12 +1,22 @@ import { Component, OnInit, Inject } from '@angular/core'; -import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {GlobalService } from '../../../services'; - - +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { GlobalService } from '../../../services'; +import { FormGroup, FormControl, FormBuilder } from '@angular/forms'; +import { ChipListComponent } from 'src/app/components/chip-list/chip-list.component' +import { OntologyTreeComponent } from '../dialogs/ontology-tree.component'; +import { OntologyTerm } from '../../../models/ontology/ontology-term'; +import { BiologicalMaterial } from 'src/app/models/linda/biological-material'; interface DialogData { material_type: string; - data_filename:string; - mode:string; + data_filename: string; + mode: string; + selected_data: []; +} +export interface TaxonScientificNames { + name: string; +} +export interface BiologicalMaterialPreprocessings { + name: string; } @Component({ @@ -15,42 +25,325 @@ interface DialogData { styleUrls: ['./biological-material.component.css'] }) export class BiologicalMaterialComponent implements OnInit { - material_type:string; - data_filename:string; - biological_material_n:number; - mode:string="from_data_file" - numbers:number[]; - replication:number; - constructor(private globalService: GlobalService, public dialogRef: MatDialogRef, + + material_type: string; + data_filename: string; + biological_material_n: number; + selected_data: any[] = [] + mode: string = "from_data_file" + numbers: number[]; + replication: number; + labelPosition: 'autogenerate ids' | 'paste ids' = 'autogenerate ids'; + PasteMaterialIds: "" | 'paste ids' = "" + autogenerateIsChecked: boolean = false + TaxonScientificName: string + MaterialID: string + BiologicalMaterialId: string; + Taxon: string; + Institution: string + selected_species: any[]; + selected_taxons: any[]; + selected_institutions: any[] = []; + BiologicalMaterialpastedIds: string[]; + MaterialpastedIds: string[]; + bm_list:BiologicalMaterial[]=[] + + taxonScientificNames: TaxonScientificNames[] = []; + BiologicalMaterialPreprocessings: BiologicalMaterialPreprocessings[] = []; + private taxonScientificNameForm: FormGroup; + private BiologicalMaterialPreprocessingForm: FormGroup; + BiologicalMaterialPreprocessing: string = ""; + validated_term = {} + + + constructor(private globalService: GlobalService, private fb: FormBuilder, public dialog: MatDialog, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData) { - this.material_type=this.data.material_type - this.data_filename=this.data.data_filename - this.numbers=[]; - this.biological_material_n=1 - this.replication=1 - if (this.data.mode){ - this.mode=this.data.mode - } - } + this.material_type = this.data.material_type + this.data_filename = this.data.data_filename + this.numbers = []; + this.biological_material_n = 1 + this.replication = 1 + if (this.data.mode) { + this.mode = this.data.mode + } + this.taxonScientificNameForm = this.fb.group({ + "keyTaxonScientificNames": new FormControl() + }); + this.BiologicalMaterialPreprocessingForm = this.fb.group({ + "keyBiologicalMaterialPreprocessings": new FormControl() + }); + this.MaterialpastedIds = [] + this.BiologicalMaterialpastedIds = [] + if (this.data.selected_data.length > 0) { + this.selected_data = this.data.selected_data + console.log(this.selected_data) + this.MaterialID = "" + let bm_count = 1 + this.selected_data.forEach(async bm => { + console.log(bm.TaxonScientificName) + if (bm_count === this.selected_data.length) { + this.MaterialID = this.MaterialID.concat(bm.AccessionNumber) + } + else { + this.MaterialID = this.MaterialID.concat(bm.AccessionNumber + '\n') + } + this.MaterialpastedIds.push(bm.AccessionNumber) + if (this.taxonScientificNames.filter(species=>species.name===bm.TaxonScientificName).length===0){ + this.taxonScientificNames.push({ name: bm.TaxonScientificName }); + } + + this.Institution = bm.HoldingInstitution.split(" - ")[0] + const res = await this.globalService.get_ncbi_taxon_data_by_species_regex(bm.TaxonScientificName).toPromise() + console.log(res) + ///this.Taxon=res[0].taxon + //this.addSkillsToArray(bm.taxonScientificName); + bm_count += 1 + }) + } + + } + get get_taxonScientificNameForm() { + return this.taxonScientificNameForm + } + get get_biologicalMaterialPreprocessingForm(){ + return this.BiologicalMaterialPreprocessingForm + } + keyTaxonScientificNames() { + return this.taxonScientificNameForm.get('keyTaxonScientificNames') as FormControl + } onNumChange(value: number) { this.biological_material_n = +value } onRepChange(value: number) { this.replication = +value } + onspeciesChanged(event) { + console.log(event.target.value) + } + onInstitutionChanged(event) { + console.log(event.target.value) + } + onMaterialIdChanged(event) { + console.log(event.target.value) + this.MaterialID = event.target.value + + } + get_output_from_taxonScientificNameForm(val: any) { + console.log(this.taxonScientificNameForm.value) + this.taxonScientificNames = val.skills + console.log(this.taxonScientificNameForm.value) + + } + get_output_from_BiologicalMaterialPreprocessingForm(val: any) { + console.log(this.BiologicalMaterialPreprocessingForm.value) + this.BiologicalMaterialPreprocessings = val.skills + console.log(this.BiologicalMaterialPreprocessingForm.value) + + } + onTaxonChanged(event) { + console.log(event.target.value) + } + onAddScientificNames(event) { + if (event.key === "Enter" || event.key === ",") { + this.addScientificNamesToArray(this.taxonScientificNameForm.value['keyTaxonScientificNames']); + } + } + onAddBiologicalMaterialPreprocessings(event) { + if (event.key === "Enter" || event.key === ",") { + this.addBiologicalMaterialPreprocessingsToArray(this.BiologicalMaterialPreprocessingForm.value['keyBiologicalMaterialPreprocessings']); + } + } + onBlurMethod() { + this.addScientificNamesToArray(this.taxonScientificNameForm.value['keyTaxonScientificNames']) + } + onBlurMethodBiologicalMaterialPreprocessing() { + this.addBiologicalMaterialPreprocessingsToArray(this.BiologicalMaterialPreprocessingForm.value['keyBiologicalMaterialPreprocessings']) + } + + addBiologicalMaterialPreprocessingsToArray(biologicalMaterialPreprocessing) { + if ((biologicalMaterialPreprocessing|| '').trim()) { + this.BiologicalMaterialPreprocessings.push({ name: biologicalMaterialPreprocessing.trim() }); + } + this.taxonScientificNameForm.reset(); + event.preventDefault(); + } + addScientificNamesToArray(taxonScientificName) { + if ((taxonScientificName || '').trim()) { + this.taxonScientificNames.push({ name: taxonScientificName.trim() }); + } + this.taxonScientificNames=Array.from(new Set(this.taxonScientificNames)) + this.taxonScientificNameForm.reset(); + event.preventDefault(); + } ngOnInit() { - for (var i:number=1;i<101;i++){ + for (var i: number = 1; i < 101; i++) { this.numbers.push(i) } } + async searchTaxonScientificNameStart(event) { + this.TaxonScientificName = event.target.value; + if (this.TaxonScientificName === "" || this.TaxonScientificName.length < 3) { + //this.active_list = false + console.log("empty search") + } + else { + //console.log(this.search_string) + this.selected_species = [] + const res = await this.globalService.get_ncbi_taxon_data_by_species_regex(this.TaxonScientificName).toPromise() + console.log(res) + this.selected_species = res + } + } + async searchTaxonStart(event) { + this.Taxon = event.target.value; + if (this.Taxon === "" || this.Taxon.length < 3) { + //this.active_list = false + console.log("empty search") + } + else { + //console.log(this.search_string) + this.selected_taxons = [] + const res = await this.globalService.get_ncbi_taxon_data_by_taxon_regex(this.Taxon).toPromise() + console.log(res) + this.selected_taxons = res + } + } + save() { +/* console.log(this.biological_material_n) + console.log(this.replication) + console.log(this.MaterialID.split('\n')) + console.log(this.TaxonScientificName) + console.log(this.taxonScientificNames) + console.log(this.Institution) + console.log(this.Taxon) */ + //this.MaterialpastedIds=this.MaterialpastedIds.concat(this.MaterialID.split('\n')) + //console.log(this.MaterialpastedIds) + /* if (this.PasteMaterialIds===""){ + console.log(this.MaterialID) + this.MaterialpastedIds.push(this.MaterialID) + } + else{ + this.MaterialpastedIds=this.MaterialpastedIds.concat(this.MaterialID.split('\n')) + console.log(this.MaterialpastedIds) + } */ + //let bm_list:BiologicalMaterial[]=[] + this.bm_list=[] + this.taxonScientificNames.forEach(tsn => { + this.MaterialpastedIds.forEach(mat_id => { + if (this.labelPosition === 'autogenerate ids') { + for (let repindex = 1; repindex < this.replication + 1; repindex++) { + for (let bmindex = 1; bmindex < this.biological_material_n + 1; bmindex++) { + let bm_id = this.Institution + "_" + mat_id + "_rep" + repindex + "_" + bmindex + console.log(bm_id) + let bm: BiologicalMaterial = new BiologicalMaterial(bm_id) + bm['Material source ID (Holding institute/stock centre, accession)'] = this.Institution + "_" + mat_id + bm['Material source DOI'] = "" + bm['Material source altitude'] = "" + bm['Material source description'] = "Material from " + this.Institution + " - Lot name: " + "" + " - Panel names:" + "" + " - Panel sizes: " + "" + bm['Material source latitude'] = "" + bm['Material source longitude'] = "" + bm['Biological material preprocessing'] = this.BiologicalMaterialPreprocessings.map(bm=>bm.name).join("/") + bm.Genus = tsn.name.split(" ")[0] + bm.replication = this.replication + bm.Species = tsn.name.split(" ")[1] + bm.Organism = this.Taxon + bm['Infraspecific name'] = tsn.name + this.bm_list.push(bm) + } + } + } + else { + this.BiologicalMaterialpastedIds = this.BiologicalMaterialpastedIds.concat(this.BiologicalMaterialId.split('\n')) + for (let index = 0; index < this.BiologicalMaterialpastedIds.length; index++) { + const element = this.BiologicalMaterialpastedIds[index]; + let bm_id = this.Institution + "_" + mat_id + "_" + element + console.log(bm_id) + let bm: BiologicalMaterial = new BiologicalMaterial(bm_id) + bm['Material source ID (Holding institute/stock centre, accession)'] = this.Institution + "_" + mat_id + bm['Material source DOI'] = "" + bm['Material source altitude'] = "" + bm['Material source description'] = "Material from " + this.Institution + " - Lot name: " + " " + " - Panel names:" + " " + " - Panel sizes: " + " " + bm['Material source latitude'] = "" + bm['Material source longitude'] = "" + bm['Biological material preprocessing'] = this.BiologicalMaterialPreprocessings.map(bm=>bm.name).join("/") + bm.Genus = element["Genus"] + bm.replication = this.replication + bm.Species = tsn.name.split(" ")[1] + bm.Organism = this.Taxon + bm['Infraspecific name'] =tsn.name + this.bm_list.push(bm) + + } + } + }); + }); + console.log(this.bm_list) + + } + onGlobalOntologyTermSelection(ontology_id: string, key: string, multiple: boolean = true) { + const dialogRef = this.dialog.open(OntologyTreeComponent, { disableClose: true, width: '1000px', autoFocus: true, maxHeight: '100vh', data: { ontology_id: ontology_id, selected_term: null, selected_set: [], selected_key: "", uncheckable: false, multiple: multiple, model_type: 'biological_material', mode_simplified: false, observed: false, sub_class_of: "" } }); + dialogRef.afterClosed().subscribe(result => { + if (result !== undefined) { + if (!multiple) { + if (result.selected_set !== undefined) { + if (key === "Biological Material Preprocessing") { + this.BiologicalMaterialPreprocessing = result.selected_set[0]['id'] + this.BiologicalMaterialPreprocessings.push({ name: result.selected_set[0]['id'].trim() }); + this.validated_term[key] = { selected: true, values: result.selected_set[0]['id'] }; + } + + } + } + } + }); + } + onTaskAdd(event) { + ////console.log(event.target.value) + } + onBiologicalMaterialPaste(event: ClipboardEvent) { + let clipboardData = event.clipboardData; + let pastedText = clipboardData.getData('text'); + console.log(pastedText) + this.BiologicalMaterialpastedIds = this.BiologicalMaterialpastedIds.concat(pastedText.split('\n')) + } + onMaterialPaste(event: ClipboardEvent) { + let clipboardData = event.clipboardData; + let pastedText = clipboardData.getData('text'); + console.log(pastedText) + this.MaterialpastedIds = this.MaterialpastedIds.concat(pastedText.split('\n')) + } + get_selected_species() { + return this.selected_species + } + get_selected_taxons() { + return this.selected_taxons + } + get_selected_institutions() { + return this.selected_institutions + } + + onBiologicalMaterialInput(content: string) { + console.log(content) + this.BiologicalMaterialId = content + } + onMaterialInput(content: string) { + console.log(content) + this.MaterialpastedIds=[] + this.MaterialID = content + this.MaterialpastedIds = this.MaterialpastedIds.concat(this.MaterialID.split('\n')) + + } + onNoClick(): void { this.dialogRef.close(); } onOkClick(): void { - console.log(this.biological_material_n) - this.dialogRef.close({event:"Confirmed", biological_material_n:(this.biological_material_n as number), replication:(this.replication as number ) }); + + this.dialogRef.close({ event: "Confirmed", biological_material_n: (this.biological_material_n as number), replication: (this.replication as number), mode: 'autogenerated', bm_list:this.bm_list }); + + } } \ No newline at end of file diff --git a/src/app/modules/application/dialogs/confirmation.component.ts b/src/app/modules/application/dialogs/confirmation.component.ts index eedc72e8..54793f08 100644 --- a/src/app/modules/application/dialogs/confirmation.component.ts +++ b/src/app/modules/application/dialogs/confirmation.component.ts @@ -23,7 +23,19 @@ interface DialogData { styleUrls: ['./confirmation.component.css'] }) export class ConfirmationComponent implements OnInit { - mode_text = { 'remove': { 'title': "Confirm remove", 'content': " Are you sure to delete ? " },'unsaved_changes': { 'title': "Confirm cancel", 'content': " Are you sure to cancel ? You have unsaved changes " }, 'link_study': { 'title': "Confirm change column definition", 'content': " Do you want to link this column with existing study ? " }, 'change_field': { 'title': "Confirm change column definition", 'content': " Are you sure to reset this column and all the components associated ? " }, 'remove_brief': { 'title': "Confirm remove", 'content': " Are you sure to delete ? " }, 'extract_env_var': { 'title': "Confirm extraction", 'content': " Are you sure to extract data? " }, 'extract_existing_env_var':{'title': "Confirm new extraction", 'content': " Are you sure to link with this exisitng observed variable ?"}, 'extract_env_var_again': { 'title': "Confirm unlink component", 'content': " Are you sure to unlink this component ? This will unlink corresponding components"}} + mode_text = { + 'removesample': { 'title': "Confirm remove", 'content': " Are you sure to delete associated samples? " }, + 'unlinkbm': { 'title': "Confirm remove", 'content': " Are you sure to unlink this biological material and all associated observation units, samples and observations? " }, + 'removeobs_unit': { 'title': "Confirm remove", 'content': " Are you sure to delete this observation unit and all samples and observations? " }, + 'remove': { 'title': "Confirm remove", 'content': " Are you sure to delete ? " }, + 'unsaved_changes': { 'title': "Confirm cancel", 'content': " Are you sure to cancel ? You have unsaved changes " }, + 'link_study': { 'title': "Confirm change column definition", 'content': " Do you want to link this column with existing study ? " }, + 'change_field': { 'title': "Confirm change column definition", 'content': " Are you sure to reset this column and all the components associated ? " }, + 'remove_brief': { 'title': "Confirm remove", 'content': " Are you sure to delete ? " }, + 'extract_env_var': { 'title': "Confirm extraction", 'content': " Are you sure to extract data? " }, + 'extract_existing_env_var':{'title': "Confirm new extraction", 'content': " Are you sure to link with this exisitng observed variable ?"}, + 'extract_env_var_again': { 'title': "Confirm unlink component", 'content': " Are you sure to unlink this component ? This will unlink corresponding components"} + } validated: boolean; all_childs: boolean = false use_template: boolean = false diff --git a/src/app/modules/application/dialogs/define.component.html b/src/app/modules/application/dialogs/define.component.html index b8e5762f..1cd78df8 100644 --- a/src/app/modules/application/dialogs/define.component.html +++ b/src/app/modules/application/dialogs/define.component.html @@ -107,9 +107,9 @@

    Studies informations

    --> -
    +

    Column informations

    - + @@ -117,8 +117,8 @@

    Column informations

    - - + + @@ -175,7 +175,7 @@

    Extraction informations

    Detected value(s)
    -
    +

    Study informations

    diff --git a/src/app/modules/application/dialogs/define.component.ts b/src/app/modules/application/dialogs/define.component.ts index b72b7eba..7b4587b8 100644 --- a/src/app/modules/application/dialogs/define.component.ts +++ b/src/app/modules/application/dialogs/define.component.ts @@ -67,7 +67,7 @@ export class DefineComponent implements OnInit, OnDestroy { private headers: string[] = [] private projectPersons: { 'project_ids': string[], 'persons': PersonInterface[], 'roles': string[], 'groups': string[] }; private studyPersons: { 'studies': StudyInterface[], 'persons': PersonInterface[], 'roles': string[] }; - private existing_studies_ids: string[] = [] + private existing_studies_names: string[] = [] private existing_studies: StudyInterface[] = [] private studies_to_remove: string[] = [] private parent_id: string; @@ -107,9 +107,13 @@ export class DefineComponent implements OnInit, OnDestroy { dtOptions: DataTables.Settings = {}; //use when no study associated header exists - private extract_study_options = [ + /* private extract_study_options = [ { disabled: true, header: "", associated_linda_id: "", name: 'Assign MIAPPE components', value: '', fields: [] }, { disabled: false, header: "", associated_linda_id: "", name: 'Study', value: 'study', fields: ['Study unique ID',] } + ] */ + private extract_study_options = [ + { disabled: true, header: "", associated_linda_id: "", name: 'Assign MIAPPE components', value: '', fields: [] }, + { disabled: false, header: "", associated_linda_id: "", name: 'Study', value: 'study', fields: ['Study Name',] } ] private extract_component_options = { 'options': [ @@ -243,26 +247,26 @@ export class DefineComponent implements OnInit, OnDestroy { //this.cleaned_study_model = this.get_model('study'); //this.cleaned_experimental_factor_model = this.get_model('experimental_factor'); // this.cleaned_event_model = this.get_model('event'); - this.existing_studies_ids = [] + this.existing_studies_names = [] const edges = await this.globalService.get_studies_and_persons(this.parent_id.split('/')[1]).toPromise() - //console.log(edges) + console.log(edges) // get persons and person roles by projects with _to contains "persons" edge to get all persons found in this investigations - edges.filter(edge => edge['e']['_to'].includes("persons") && edge['e']['_from'].includes("investigations")).forEach(edge => { this.projectPersons.persons.push(edge["v"]); this.projectPersons.roles.push(edge["e"]["role"]); edge["e"]["group_keys"].forEach(element => { this.projectPersons.groups.push(element) }) }) + edges.filter(edge => edge['e']['_to'].includes("persons") && edge['e']['_from'].includes("investigations")).forEach(edge => { this.projectPersons.persons.push(edge["v"] as PersonInterface); this.projectPersons.roles.push(edge["e"]["role"]); edge["e"]["group_keys"].forEach(element => { this.projectPersons.groups.push(element) }) }) //console.log(this.projectPersons) // get studies in this investigation with _to contains "studies" - edges.filter(edge => edge['e']['_to'].includes("studies")).forEach(edge => { this.existing_studies_ids.push(edge["v"]["Study unique ID"]) }) - edges.filter(edge => edge['e']['_to'].includes("studies")).forEach(edge => { this.existing_studies.push(edge["v"]) }) + edges.filter(edge => edge['e']['_to'].includes("studies")).forEach(edge => { this.existing_studies_names.push(edge["v"]["Study Name"]) }) + edges.filter(edge => edge['e']['_to'].includes("studies")).forEach(edge => { this.existing_studies.push(edge["v"] as StudyInterface) }) // then find all persons roles by studies //this.definecolumnForm.get('Detected studies').setValue(this.existing_studies_ids); edges.filter(edge => edge['e']['_from'].includes("studies")).forEach(edge => { //this.existing_studies_ids.push(edge["e"]['_from']); - this.studyPersons.persons.push(edge["v"]); + this.studyPersons.persons.push(edge["v"] as PersonInterface); this.studyPersons.roles.push(edge["e"]["role"]) }) - for (let index = 0; index < this.existing_studies_ids.length; index++) { - const element = this.existing_studies_ids[index]; - edges.filter(edge => edge['e']['_to'].includes("studies") && edge['e']['_to'] === element).forEach(edge => { this.studyPersons.studies.push(edge["v"]) }) + for (let index = 0; index < this.existing_studies_names.length; index++) { + const element = this.existing_studies_names[index]; + edges.filter(edge => edge['e']['_to'].includes("studies") && edge['e']['_to'] === element).forEach(edge => { this.studyPersons.studies.push(edge["v"] as StudyInterface) }) } //edges.filter(edge=> edge['e']['_to'].includes("studies")).forEach(edge=>{this.studyPersons.studies.push(edge["v"])}) //console.log(this.studyPersons) @@ -286,29 +290,12 @@ export class DefineComponent implements OnInit, OnDestroy { this.studyValuesDictionary = this.data_file.Data.reduce((prev, curr) => { return { ...prev, - [curr["Study linda ID"]]: curr[this.column_original_label] + [curr["Study Name"]]: curr[this.column_original_label] } }, {}) - //console.log(this.studyValuesDictionary) + console.log(this.studyValuesDictionary) //console.log(this.existing_studies_ids) } - get get_studyValuesDictionary() { - return this.studyValuesDictionary - } - get_associated_studies(): string[] { - return Object.keys(this.studyValuesDictionary) - } - get_associated_study(key: string, index: number) { - /* const valuesDictionary = this.data_file.Data.reduce((prev, curr) => { - return { - ...prev, - //[curr[this.column_original_label]]: curr["Study linda ID"] - [curr["Study linda ID"]]: curr[this.column_original_label] - } - }, {}) - //console.log(valuesDictionary) */ - return Object.keys(this.studyValuesDictionary)[index] - } onModify(values: string) { var data_model = { ...this.data_file }; @@ -416,6 +403,8 @@ export class DefineComponent implements OnInit, OnDestroy { } } + + filteredByField(obj: {}) { if (obj[this.column_original_label] === this.current_study) { return true @@ -427,7 +416,6 @@ export class DefineComponent implements OnInit, OnDestroy { } onChangeHeader(){ this.generalForm.get('Header').enable() - } async onSaveHeader(){ this.while_added = true @@ -460,16 +448,14 @@ export class DefineComponent implements OnInit, OnDestroy { } } - /*STUDY PART ROUTINES*/ - async onExtractStudy(component_value, index: number) { this.while_added = true //console.log(component_value) //console.log(this.extraction_component) //console.log(this.extraction_component_field) if (this.extraction_component === "study") { - if (this.extraction_component_field === "Study unique ID") { + if (this.extraction_component_field === "Study Name") { this.show_infos() /* let study_model_dict = {} this.cleaned_study_model.forEach(attr => { study_model_dict[attr["key"]] = "" }); @@ -477,9 +463,9 @@ export class DefineComponent implements OnInit, OnDestroy { study_model['Study unique ID'] = component_value */ //var data_model = { ...this.data_file }; let study_model = new Study() - study_model['Study unique ID'] = component_value + //study_model['Study unique ID'] = component_value study_model['Study Name'] = component_value - if (!this.existing_studies_ids.includes(component_value)) { + if (!this.existing_studies_names.includes(component_value)) { let add_study_res = await this.globalService.add(study_model, 'study', this.parent_id, false, this.group_key).toPromise() if (add_study_res["success"]) { //console.log(add_study_res) @@ -517,7 +503,7 @@ export class DefineComponent implements OnInit, OnDestroy { dialogRef.afterClosed().subscribe(async (result) => { if (result) { if (result.event == 'Confirmed') { - const add_study_res = await this.globalService.get_lindaID_by_studyID(component_value, this.parent_id.split('/')[1]).toPromise() + const add_study_res = await this.globalService.get_lindaID_by_studyName(component_value, this.parent_id.split('/')[1]).toPromise() if (add_study_res['success']) { let study_id = add_study_res["_id"] this.data_file.associated_headers.filter(prop => prop.header === this.column_original_label)[0].associated_parent_id.push(this.parent_id) @@ -555,19 +541,22 @@ export class DefineComponent implements OnInit, OnDestroy { let values: StudyInterface[] = [] let values_to_link: string[] = [] let parent_ids: string[] =[] + console.log(this.existing_studies_names) for (let index = 0; index < this.detected_values.length; index++) { const element = this.detected_values[index]; - if (!this.existing_studies_ids.includes(element)) { - values.push(new Study(element)) + if (!this.existing_studies_names.includes(element)) { + values.push(new Study(element,element)) } else { values_to_link.push(element) } parent_ids.push(this.parent_id) } + console.log(values) + console.log(values_to_link) if (values.length > 0) { - let add_study_res = await this.globalService.add_multiple(values, 'study', 'investigations', false, this.group_key, this.data_file._key, this.column_original_label, 'Study unique ID', parent_ids).toPromise() + let add_study_res = await this.globalService.add_multiple(values, 'study', 'investigations', false, this.group_key, this.data_file._key, this.column_original_label, 'Study Name', parent_ids).toPromise() if (add_study_res['success']) { // if some studies are already present (values_to_link >0), just link the asssociated heaers to the corresponding study_id if (values_to_link.length !== 0) { @@ -578,7 +567,7 @@ export class DefineComponent implements OnInit, OnDestroy { let keys: string[] = [] for (let index = 0; index < values_to_link.length; index++) { const element = values_to_link[index]; - const add_study_res = await this.globalService.get_lindaID_by_studyID(element, this.parent_id.split('/')[1]).toPromise() + const add_study_res = await this.globalService.get_lindaID_by_studyName(element, this.parent_id.split('/')[1]).toPromise() if (add_study_res['success']) { keys.push(add_study_res["_id"].split("/")[1]) } @@ -606,7 +595,9 @@ export class DefineComponent implements OnInit, OnDestroy { let keys: string[] = [] for (let index = 0; index < values_to_link.length; index++) { const element = values_to_link[index]; - const add_study_res = await this.globalService.get_lindaID_by_studyID(element, this.parent_id.split('/')[1]).toPromise() + console.log(element) + const add_study_res = await this.globalService.get_lindaID_by_studyName(element, this.parent_id.split('/')[1]).toPromise() + console.log(add_study_res) if (add_study_res['success']) { keys.push(add_study_res["_id"].split("/")[1]) } @@ -750,10 +741,10 @@ export class DefineComponent implements OnInit, OnDestroy { async onUnlinkAllStudies() { } has_study_associated_header(): boolean { - return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study unique ID').length > 0 + return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study Name').length > 0 } get study_associated_header() { - return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study unique ID')[0] + return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study Name')[0] } @@ -940,6 +931,9 @@ export class DefineComponent implements OnInit, OnDestroy { has_event_associated_header(): boolean { return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Event accession number').length > 0 } + + /*BiologicalMaterial PART ROUTINES*/ + /*ExperimentalFactor PART ROUTINES*/ async onExtractAllExperimentalFactors() { this.while_added = true @@ -1205,12 +1199,8 @@ export class DefineComponent implements OnInit, OnDestroy { return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Experimental Factor accession number').length > 0 } - - - - /*Environment PART ROUTINES*/ - /*EVENT PART ROUTINES*/ + async onExtractAllEnvironments(){ this.while_added = true let values: Environment[] = [] @@ -1380,9 +1370,6 @@ export class DefineComponent implements OnInit, OnDestroy { detected_environment.associated_linda_id.filter(x => !this.selected_value.ids.includes(x)).length === 0 ) } - - - /*Observed variable PART ROUTINES*/ async onExtractAllObservedVariables(){ this.while_added = true @@ -1399,7 +1386,7 @@ export class DefineComponent implements OnInit, OnDestroy { env_model['Variable accession number'] = this.detected_values[index] values.push(env_model) } - let add_env_res = await this.globalService.add_multiple(values, 'observed_variable', 'observed_variables', false, this.group_key, this.data_file._key, this.column_original_label, this.extraction_component_field, parent_ids).toPromise() + let add_env_res = await this.globalService.add_multiple(values, 'observed_variable', 'studies', false, this.group_key, this.data_file._key, this.column_original_label, this.extraction_component_field, parent_ids).toPromise() if (add_env_res['success']) { this.data_file = add_env_res['datafile'] this.while_added = false @@ -1634,6 +1621,23 @@ export class DefineComponent implements OnInit, OnDestroy { }) return column_values } + get get_studyValuesDictionary() { + return this.studyValuesDictionary + } + get_associated_studies(): string[] { + return Object.keys(this.studyValuesDictionary) + } + get_associated_study(key: string, index: number) { + /* const valuesDictionary = this.data_file.Data.reduce((prev, curr) => { + return { + ...prev, + //[curr[this.column_original_label]]: curr["Study linda ID"] + [curr["Study linda ID"]]: curr[this.column_original_label] + } + }, {}) + //console.log(valuesDictionary) */ + return Object.keys(this.studyValuesDictionary)[index] + } @@ -1787,9 +1791,25 @@ export class DefineComponent implements OnInit, OnDestroy { let study_linda_id = this.study_associated_header.associated_linda_id[this.study_associated_header.associated_values.indexOf(study_unique_id)] return this.associated_header.associated_linda_id.filter(linda_id => linda_id === study_linda_id).length > 0 } + has_associated_header_linda_id_by_values(_values: string[]) { + ////console.log(_value) + let found = true + for (let index = 0; index < _values.length; index++) { + const element = _values[index]; + this.data_file.Data.filter(line => line[this.column_original_label] === element).forEach(l => { + if (l["Study linda ID"] === "") { + found = false + } + }) + + } + + return found + } has_associated_header_linda_id_by_value(_value: string) { ////console.log(_value) let found = true + this.data_file.Data.filter(line => line[this.column_original_label] === _value).forEach(l => { if (l["Study linda ID"] === "") { found = false @@ -1806,7 +1826,8 @@ export class DefineComponent implements OnInit, OnDestroy { } */ //return this.associated_header.associated_linda_id.filter(value => value === key).length !== 0 } - has_associated_header_parent_id_by_index(_parent_id: string, index: number) { + has_associated_header_parent_id_by_index(_study_id: string, index: number) { + var _parent_id=this.study_associated_header.associated_linda_id[this.study_associated_header.associated_values.indexOf(_study_id)] return this.associated_header.associated_parent_id.filter(parent_id => parent_id === _parent_id).length > 0 } has_associated_header_linda_id_by_index(key: string, index: number) { @@ -1863,7 +1884,7 @@ export class DefineComponent implements OnInit, OnDestroy { get detected_studies() { if (this.has_study_associated_header()) { - return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study unique ID')[0].associated_values + return this.data_file.associated_headers.filter(associated_header => associated_header.associated_component_field === 'Study Name')[0].associated_values } else { return [] @@ -1873,7 +1894,7 @@ export class DefineComponent implements OnInit, OnDestroy { ////console.log(this.get_data_by_header(this.column_original_label)) if (this.extraction_component === 'study') { ////console.log(this.get_data_by_header(this.column_original_label)) - if (this.extraction_component_field === 'Study unique ID') { + if (this.extraction_component_field === 'Study Name') { ////console.log(this.get_data_by_header(this.column_original_label)) return Array.from(new Set(this.get_data_by_header(this.column_original_label))); } @@ -1953,7 +1974,7 @@ export class DefineComponent implements OnInit, OnDestroy { return this.studyPersons } get get_existing_studies_ids() { - return this.existing_studies_ids + return this.existing_studies_names } get_component(field: string) { return this.extract_component_options.options.filter(prop => prop.fields.includes(field))[0]['value'] diff --git a/src/app/modules/application/dialogs/dialog.module.ts b/src/app/modules/application/dialogs/dialog.module.ts index 2dab4470..b3e354bf 100644 --- a/src/app/modules/application/dialogs/dialog.module.ts +++ b/src/app/modules/application/dialogs/dialog.module.ts @@ -21,6 +21,7 @@ import { GlobalService} from '../../../services'; import { MatButtonModule } from '@angular/material/button'; import { MatButtonToggleModule } from '@angular/material/button-toggle'; import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatRadioModule} from '@angular/material/radio' import { MatDialogModule } from '@angular/material/dialog'; import { ReactiveFormsModule,FormsModule } from '@angular/forms'; import { MatFormFieldModule} from '@angular/material/form-field'; @@ -36,6 +37,7 @@ import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { MatSlideToggleModule } from '@angular/material/slide-toggle' import { MatSliderModule } from '@angular/material/slider' +import { MatGridListModule } from '@angular/material/grid-list'; import { TextFieldModule} from '@angular/cdk/text-field'; import { ScrollingModule} from '@angular/cdk/scrolling'; import { FormModule } from '../forms/form.module'; @@ -56,6 +58,12 @@ import { ProgressBarModule } from 'src/app/components/progress-bar/progress-bar. import { AssociateBiologicalMaterial } from './associate-biological-material.component'; import { MatInputModule } from '@angular/material/input'; import { AssociateObservationUnit } from './associate-observation-unit.component'; +import { MatMenuModule } from '@angular/material'; +import {ChipListComponent} from 'src/app/components/chip-list/chip-list.component' +import { AssociateObservedVariable } from './associate-observed-variable.component'; +import { PlotOverviewComponent } from './plot-overview.component'; +import { AssociateExperimentalFactorComponent } from './associate-experimental-factor.component'; +import { AssociateObservationsMeasurementComponent } from './associate-observations-measurement.component'; @NgModule({ declarations: [ @@ -83,7 +91,12 @@ import { AssociateObservationUnit } from './associate-observation-unit.component EditFormComponent, ProjectLoaderComponent, AssociateBiologicalMaterial, - AssociateObservationUnit + AssociateObservationUnit, + AssociateObservedVariable, + ChipListComponent, + PlotOverviewComponent, + AssociateExperimentalFactorComponent, + AssociateObservationsMeasurementComponent ], imports: [ CommonModule, @@ -97,9 +110,11 @@ import { AssociateObservationUnit } from './associate-observation-unit.component MatPaginatorModule, MatProgressBarModule, MatFormFieldModule, + MatMenuModule, MatInputModule, ProgressBarModule, MatExpansionModule, + MatGridListModule, MatTreeModule, MatCardModule, MatIconModule, @@ -107,6 +122,7 @@ import { AssociateObservationUnit } from './associate-observation-unit.component MatSliderModule, TextFieldModule, ScrollingModule, + MatRadioModule, MatTableModule, FormModule, MaterialFormModule, @@ -144,7 +160,12 @@ import { AssociateObservationUnit } from './associate-observation-unit.component EditFormComponent, ProjectLoaderComponent, AssociateBiologicalMaterial, - AssociateObservationUnit + AssociateObservationUnit, + AssociateObservedVariable, + AssociateExperimentalFactorComponent, + AssociateObservationsMeasurementComponent, + ChipListComponent, + PlotOverviewComponent ], entryComponents:[ ConfirmationComponent, @@ -171,7 +192,12 @@ import { AssociateObservationUnit } from './associate-observation-unit.component EditFormComponent, ProjectLoaderComponent, AssociateBiologicalMaterial, - AssociateObservationUnit + AssociateObservationUnit, + AssociateObservedVariable, + AssociateExperimentalFactorComponent, + AssociateObservationsMeasurementComponent, + ChipListComponent, + PlotOverviewComponent ] }) export class DialogModule { } diff --git a/src/app/modules/application/dialogs/files-loader.component.html b/src/app/modules/application/dialogs/files-loader.component.html index 25e913fe..70520f27 100644 --- a/src/app/modules/application/dialogs/files-loader.component.html +++ b/src/app/modules/application/dialogs/files-loader.component.html @@ -22,8 +22,29 @@

    Download local data files

    -

    Here you can integrate experimental data and metadata to enrich your projects or your studies. Use these - datafiles to create or describe your experimental design, your observations units, and many more.

    +

    Here you can integrate experimental data and metadata to enrich your projects or your studies. Use + datafiles to create or describe your experimental design, your observations units, and many more. +

    +

    Usage

    +

    + You can create and describe most of the MIAPPE components here using tabular files. +

    +

    + Two ways are available depending on data at your disposal but in each case, + the only mandatory column needed in each file is the Study Name column. +

    +
    build your own data file
    +
      +
    • + First select add data file from empty file by clicking on add menu . +
    • +
    • + Secondly, you have to precise file name and your Study Name column(s) +
    • +
    • + Finally, import your datafile +
    • +
    @@ -42,14 +63,32 @@

    Download local data files

    Build your own data files

    -

    Here you can create a datafile skeleton by simply paste Sutdy unique IDs. For each study IDs, a study will b i,ntegrrated in your project. Use these - datafiles later, to create or describe your experimental design, your observations units, and many more.

    +

    Here you can create a datafile skeleton by simply paste Study names. For each Study Names, a study will be integrated in your project. Use these + datafiles later, to create or describe your experimental design, your observations units, and many more. +

    +

    + You can create and describe most of the MIAPPE components here using tabular files. +

    +

    Usage

    +
      +
    • + First select name of your file. (.csv extension needed). +
    • +
    • + Secondly, you have to fill text area with your Study Name column(s) (one study name by row). You can use button to load the existing study name(s). +
    • +
    • + Finally, click on +
    • +
    - FreeText - + +
    + filename + extension + - FreeText - + Study Names +
    diff --git a/src/app/modules/application/dialogs/files-loader.component.ts b/src/app/modules/application/dialogs/files-loader.component.ts index dc655bf1..dfca42a6 100644 --- a/src/app/modules/application/dialogs/files-loader.component.ts +++ b/src/app/modules/application/dialogs/files-loader.component.ts @@ -10,10 +10,12 @@ import { AssociatedHeadersInterface} from 'src/app/models/linda/data_files' import { DataFileInterface} from 'src/app/models/linda/data_files' import { timeStamp } from 'console'; import {CdkTextareaAutosize} from '@angular/cdk/text-field'; +import { Study } from 'src/app/models/linda/study'; interface DialogData { parent_id: string; + group_key: string; mode:string; } @@ -25,7 +27,7 @@ interface DialogData { export class FilesLoaderComponent implements OnInit { //@ViewChild('autosize', {static: true}) autosize: CdkTextareaAutosize; errorMessage: string; - myTextarea='' + myStudyNames='' successMessage: string; parent_id:string="" mode:string="" @@ -46,6 +48,8 @@ export class FilesLoaderComponent implements OnInit { private cleaned_data_file_model = [] private data_model:{'Data file description':string,'Data file version':string, 'Data file link':string, 'Data':any[],'associated_headers':AssociatedHeadersInterface[], 'headers':string[]}; form: FormGroup; + + private group_key: string; private loaded:boolean=false private added:boolean=false private preview_request:boolean=false @@ -59,6 +63,7 @@ export class FilesLoaderComponent implements OnInit { public delimdialog: MatDialog) { this.parent_id=this.data.parent_id this.mode=this.data.mode + this.group_key = this.data.group_key console.log(this.parent_id) console.log(this.mode) @@ -219,6 +224,19 @@ export class FilesLoaderComponent implements OnInit { isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } + async add_existing_studies(){ + const studies=await this.globalService.get_type_child_from_parent(this.parent_id.split("/")[0],this.parent_id.split("/")[1],'studies').toPromise() + console.log(studies) + for (let index = 0; index < studies.length; index++) { + const study:Study = studies[index]; + if (index===studies.length-1){ + this.myStudyNames+=study['Study Name'] + } + else{ + this.myStudyNames+=study['Study Name']+"\n" + } + } + } Preview() { if (this.added) { this.preview_request=true @@ -314,41 +332,52 @@ export class FilesLoaderComponent implements OnInit { } get_text_area(value){ console.log(value) - console.log(this.myTextarea=value ) - this.added=this.myTextarea!=='' && this.fileName!=='' + console.log(this.myStudyNames=value ) + this.added=this.myStudyNames!=='' && this.fileName!=='' } get_filename(value){ this.fileName=value - this.added=this.myTextarea!=='' && this.fileName!=='' + this.added=this.myStudyNames!=='' && this.fileName!=='' } onNoClick(): void { this.dialogRef.close({event:"Cancelled"}); } - onSubmit(): void { + async onSubmit(): Promise { if (this.mode==='local_import'){ - this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise().then( - data => { - console.log(data); - this.dialogRef.close({event:"Confirmed"}); - }) + const data= await this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise()//.then( + console.log(data); + this.dialogRef.close({event:"Confirmed"}); } else{ - console.log(this.myTextarea.split('\n')) - //remove ddooublons + console.log(this.myStudyNames.split('\n')) + //remove doublons this.data_model['Data file description'] = 'Data have been extracted from ' + this.fileName this.data_model['Data file version'] = '1.0' this.data_model['Data file link'] = this.fileName let model_data=[] - this.myTextarea.split('\n').forEach(_study_id=>{ - model_data.push({'Study id':_study_id, 'Study linda ID':""}) - }) - this.data_model['Data'] = model_data + let study_names=[] + let study_ids=[] + let parent_ids=[] + console.log(this.parent_id) + //this.data_model['Data'] = model_data this.data_model['associated_headers'] = [ { + "header": "Study Name", + "selected": true, + "associated_term_id": "", + "associated_component": "study", + "associated_component_field": "Study Name", + "associated_values": [], + "associated_linda_id": [], + "associated_parent_id": [], + "is_time_values": false, + "is_numeric_values": false + }, + /* { "header": "Study id", "selected": true, "associated_term_id": "", @@ -359,7 +388,7 @@ export class FilesLoaderComponent implements OnInit { "associated_parent_id": [], "is_time_values": false, "is_numeric_values": false - }, + }, */ { "header": "Study linda ID", "selected": false, @@ -372,19 +401,90 @@ export class FilesLoaderComponent implements OnInit { "is_time_values": false, "is_numeric_values": false } + ] - this.data_model['headers'] = ["Study id"] - this.data_model['headers'].push('Study linda ID') - this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise().then( + this.data_model['headers'] = ["Study Name","Study linda ID"] + //this.data_model['headers'] = ["Study Name","Study id","Study linda ID"] + console.log(this.data_model) + this.myStudyNames.split('\n').forEach(async _study_name=>{ + study_names.push(_study_name) + }); + for (let index = 0; index < study_names.length; index++) { + const _study_name = study_names[index]; + //let study_model = new Study(_study_name,_study_name) + //study_model['Study unique ID'] = _study_name + //study_model['Study Name'] = _study_name + //need to add studies before ? + /* let add_study_res = await this.globalService.add(study_model, 'study', this.parent_id, false, this.group_key).toPromise() + if (add_study_res["success"]) { + console.log(add_study_res) + //console.log(add_study_res["message"]) + let study_id = add_study_res["_id"] + study_ids.push(study_id) + this.data_model['Data'].push({'Study linda ID':study_id, 'Study Name':_study_name}) + //this.data_model['Data'].push({'Study id':study_id, 'Study linda ID':study_id, 'Study Name':_study_name}) + this.data_model['associated_headers'][0]['associated_values'].push(_study_name) + this.data_model['associated_headers'][0]['associated_linda_id'].push(study_id) + this.data_model['associated_headers'][0]['associated_parent_id'].push(this.parent_id) + //this.data_model['associated_headers'][1]['associated_values'].push(study_id) + //this.data_model['associated_headers'][1]['associated_linda_id'].push(study_id) + //this.data_model['associated_headers'][1]['associated_parent_id'].push(this.parent_id) + this.data_model['associated_headers'][1]['associated_linda_id'].push(study_id) + console.log(this.data_model); + + } */ + + this.data_model['Data'].push({'Study linda ID':"", 'Study Name':_study_name}) + //this.data_model['Data'].push({'Study id':study_id, 'Study linda ID':study_id, 'Study Name':_study_name}) + //this.data_model['associated_headers'][0]['associated_values'].push(_study_name) + //this.data_model['associated_headers'][0]['associated_linda_id'].push(study_id) + //this.data_model['associated_headers'][0]['associated_parent_id'].push(this.parent_id) + //this.data_model['associated_headers'][1]['associated_values'].push(study_id) + //this.data_model['associated_headers'][1]['associated_linda_id'].push(study_id) + //this.data_model['associated_headers'][1]['associated_parent_id'].push(this.parent_id) + //this.data_model['associated_headers'][1]['associated_linda_id'].push(study_id) + + } + const data= await this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise()//.then( + console.log(data); + /* this.myStudyNames.split('\n').forEach(async _study_name=>{ + study_names.push(_study_name) + parent_ids.push(this.parent_id) + + let study_model = new Study() + study_model['Study unique ID'] = _study_name + study_model['Study Name'] = _study_name + let add_study_res = await this.globalService.add(study_model, 'study', this.parent_id, false, this.group_key).toPromise() + if (add_study_res["success"]) { + console.log(add_study_res) + //console.log(add_study_res["message"]) + let study_id = add_study_res["_id"] + study_ids.push(study_id) + this.data_model['Data'].push({'Study id':study_id, 'Study linda ID':study_id, 'Study Name':_study_name}) + this.data_model['associated_headers'][0]['associated_values'].push(_study_name) + this.data_model['associated_headers'][0]['associated_linda_id'].push(study_id) + this.data_model['associated_headers'][0]['associated_parent_id'].push(this.parent_id) + this.data_model['associated_headers'][1]['associated_values'].push(study_id) + this.data_model['associated_headers'][1]['associated_linda_id'].push(study_id) + this.data_model['associated_headers'][1]['associated_parent_id'].push(this.parent_id) + this.data_model['associated_headers'][2]['associated_linda_id'].push(study_id) + console.log(this.data_model); + const data= await this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise()//.then( + console.log(data); + } + }); */ + /* this.myStudyNames.split('\n').forEach(_study_id=>{ + model_data.push({'Study id':"", 'Study linda ID':"", 'Study Name':_study_id}) + }) */ + + + this.dialogRef.close({event:"Confirmed"}); + /* this.fileService.upload4(this.data_model, this.parent_id).pipe(first()).toPromise().then( data => { console.log(data); this.dialogRef.close({event:"Confirmed"}); - }) - - + }) */ } - - } } diff --git a/src/app/modules/application/dialogs/ontology-tree.component.html b/src/app/modules/application/dialogs/ontology-tree.component.html index f757d239..bab840b4 100644 --- a/src/app/modules/application/dialogs/ontology-tree.component.html +++ b/src/app/modules/application/dialogs/ontology-tree.component.html @@ -80,7 +80,7 @@

    Please select a term in {{data['ontology_type']}} Ontology< - +
    @@ -191,20 +191,19 @@

    Please select a term in {{data['ontology_type']}} Ontology< {{node.name}} --> - + {{node.name}} - + {{node.name}} + - {{node.name}} +

    TRAIT

    VARIABLE

    METHOD

    SCALE

    - - diff --git a/src/app/modules/application/dialogs/ontology-tree.component.ts b/src/app/modules/application/dialogs/ontology-tree.component.ts index 8c75f64b..ed99867b 100644 --- a/src/app/modules/application/dialogs/ontology-tree.component.ts +++ b/src/app/modules/application/dialogs/ontology-tree.component.ts @@ -51,7 +51,7 @@ export class OntologyTreeComponent { private mode_simplified: boolean = false private sub_class_of:string=""; private model_type:string=""; - private multiple: boolean + private multiple: boolean =false panel_disabled:boolean=true panel_expanded:boolean=true //model ontology @@ -117,6 +117,11 @@ export class OntologyTreeComponent { this.model_type=this.data.model_type } console.log("sub_class_of is given: ", this.sub_class_of) + console.log("uncheckable is given: ", this.uncheckable) + console.log("multiple is given: ", this.multiple) + console.log("selected_key is given: ", this.selected_key) + console.log("mode_simplified is given: ", this.mode_simplified) + console.log("observed is given: ", this.observed) this.ontology_tree = []; this.ontologyTerms = []; this.ontologyContext = []; @@ -156,7 +161,7 @@ export class OntologyTreeComponent { this.ontology = data; this.ontologyNode = []; this.search_string = ""; - var ontologies_list = ["EnvO", "PECO", "BTO", "PO", "CO_20", "EFO", "CO_715", "OBI", "Solanacae"]; + var ontologies_list = ["EnvO", "PECO", "BTO", "PO", "CO_20", "EFO", "CO_715", "OBI", "Solanacae", "Trait Ontology"]; if (this.ontology_id === "XEO") { this.ontologyNode = this.build_xeo_isa_hierarchy(this.ontology); } @@ -356,6 +361,13 @@ export class OntologyTreeComponent { var cpt = 0; this.show_spinner = true; + + console.log(ontology) + console.log(ontology['term'].filter(_term=>_term["id"].includes(" TO") && ! _term["id"].startsWith("PATO"))) + if (this.ontology_id==='Trait Ontology'){ + ontology['term']=ontology['term'].filter(_term=>_term["id"].includes("TO")&& ! _term["id"].startsWith("PATO")) + } + console.log(ontology) //console.log(this.show_spinner) //this.matSpinner.value= 0 //this.ontology_tree_loading_progress_value = 0 diff --git a/src/app/modules/application/dialogs/plot-overview.component.css b/src/app/modules/application/dialogs/plot-overview.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/modules/application/dialogs/plot-overview.component.html b/src/app/modules/application/dialogs/plot-overview.component.html new file mode 100644 index 00000000..aa68b99f --- /dev/null +++ b/src/app/modules/application/dialogs/plot-overview.component.html @@ -0,0 +1,43 @@ +

    Plot detailss

    + + + +
    +
    +

    Plot inforrmations

    + +

    This module is still in developmment (coming soon)

    +
    + +

    Associated biological materials

    + + + +

    This module is still in developmment (coming soon)

    +
    + +

    Associated experimental factors

    + + +

    This module is still in developmment (coming soon)

    +
    +
    +

    Associated samples

    + + +

    This module is still in developmment (coming soon)

    +
    +
    +

    Associated observations

    + + +

    This module is still in developmment (coming soon)

    +
    +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/src/app/modules/application/dialogs/plot-overview.component.spec.ts b/src/app/modules/application/dialogs/plot-overview.component.spec.ts new file mode 100644 index 00000000..c1acf74c --- /dev/null +++ b/src/app/modules/application/dialogs/plot-overview.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PlotOverviewComponent } from './plot-overview.component'; + +describe('PlotOverviewComponent', () => { + let component: PlotOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PlotOverviewComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PlotOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/modules/application/dialogs/plot-overview.component.ts b/src/app/modules/application/dialogs/plot-overview.component.ts new file mode 100644 index 00000000..f1485585 --- /dev/null +++ b/src/app/modules/application/dialogs/plot-overview.component.ts @@ -0,0 +1,86 @@ +import { ChangeDetectorRef, Component, Inject, OnInit, ViewChild } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { GlobalService, AlertService } from '../../../services'; +import { SelectionModel } from '@angular/cdk/collections'; +import { MatSort } from '@angular/material/sort'; +import { MatTableDataSource } from '@angular/material/table'; +import {BiologicalMaterialDialogModel } from '../../../models/biological_material_models' +import {ExperimentalFactorDialogModel} from '../../../models/experimental_factor_models' +import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { BiologicalMaterialFullInterface } from 'src/app/models/linda/biological-material'; +import { Router } from '@angular/router'; +import { PlotDesign } from 'src/app/models/linda/experimental-design'; + +interface DialogData { + model_id: string; + parent_id: string; + model_type: string; + plot_design:PlotDesign; + role:string; + grand_parent_id:string; + group_key:string; +} +export interface PlotMaterial{ + biological_material_id:string; + row_num:number; + column_num:number; + harvested_date:Date; + alive:boolean; +} + +@Component({ + selector: 'app-plot-overview', + templateUrl: './plot-overview.component.html', + styleUrls: ['./plot-overview.component.css'] +}) +export class PlotOverviewComponent implements OnInit { + @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator; + @ViewChild(MatSort, { static: false }) sort: MatSort; + private model_id: string; + model_type: string; + private parent_id: string; + role:string="" + grand_parent_id:string="" + total_available_material_by_plots:number=0 + group_key:string="" + loaded:boolean=false + plot_design:PlotDesign; + selected_material:PlotMaterial; + private dataSource: MatTableDataSource; + private displayedColumns: string[] = []; + + constructor( + private globalService: GlobalService, + private alertService:AlertService, + public dialogRef: MatDialogRef, + private router: Router, + private _cdr: ChangeDetectorRef, + @Inject(MAT_DIALOG_DATA) public data: DialogData + ) { + this.model_id = this.data.model_id + this.model_type = this.data.model_type + this.parent_id = this.data.parent_id + this.plot_design=this.data.plot_design + this.role = this.data.role + this.grand_parent_id = this.grand_parent_id + this.group_key = this.data.group_key + console.log(this.plot_design) +} + + ngOnInit() { + this.loaded=true + } + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.dataSource.filter = filterValue.trim().toLowerCase(); + + if (this.dataSource.paginator) { + this.dataSource.paginator.firstPage(); + } + } + onClose(): void { + this.dialogRef.close({event:"Close"}); + } + + +} diff --git a/src/app/modules/application/dialogs/project-loader.component.ts b/src/app/modules/application/dialogs/project-loader.component.ts index dcda0f27..a7d29f48 100644 --- a/src/app/modules/application/dialogs/project-loader.component.ts +++ b/src/app/modules/application/dialogs/project-loader.component.ts @@ -74,6 +74,7 @@ export class ProjectLoaderComponent implements OnInit { this.parent_id = this.data.parent_id this.group_key = this.data.group_key console.log(this.parent_id) + this.currentUser = JSON.parse(localStorage.getItem('currentUser')); } ngOnInit() { diff --git a/src/app/modules/application/dialogs/sample-selection.component.html b/src/app/modules/application/dialogs/sample-selection.component.html index 1894a03a..1f3f79cc 100644 --- a/src/app/modules/application/dialogs/sample-selection.component.html +++ b/src/app/modules/application/dialogs/sample-selection.component.html @@ -17,6 +17,10 @@

    Biological(s) Material(s)

    --> + + Filter + + @@ -61,12 +65,12 @@

    Describe biological sample(s)

    - + - Advanced options + Global options

    Sample collection date

    @@ -107,28 +111,17 @@

    Plant structure development stage

    Total sample by material

    -

    Auto generate sample ID

    - - - ID autogenerate - -

    - generate incremental sample identifier using material source and biological material identifier. -

    -

    Replicate number

    - Technical replicate

    Define the number of technical replicate(s) by sample -

    +

    --> - +
    +

    Sample ID

    + +

    + You can use your own sample IDs by selecting Paste sample ids. +

    +
    + +
    + + Autogenerate external ids + Paste sample ids + +
    + + +

    you are ready to autogenerate sample Ids for {{get_total}} biological materials selected !!

    +
    + +

    Paste your list of Ids here !!
    + + Each Id has to be separated by a new line !! + Take care to have the same number of line than the total biological materials selected !
    + For instance, you need {{get_total}} sample Id(s) to match number of materials selected +

    + + +
    +
    + + + +
    + +
    +
    +
    diff --git a/src/app/modules/application/dialogs/sample-selection.component.ts b/src/app/modules/application/dialogs/sample-selection.component.ts index 8b1679cc..ac0a5072 100644 --- a/src/app/modules/application/dialogs/sample-selection.component.ts +++ b/src/app/modules/application/dialogs/sample-selection.component.ts @@ -15,6 +15,7 @@ import { BiologicalMaterialDialogModel } from '../../../models/biological_materi import { MatPaginator } from '@angular/material'; import { date, RxwebValidators } from "@rxweb/reactive-form-validators" import { RxReactiveFormsModule } from "@rxweb/reactive-form-validators" +import { ExperimentalDesign } from 'src/app/models/linda/experimental-design'; interface DialogData { model_id: string; @@ -22,7 +23,8 @@ interface DialogData { model_type: string; bm_data: []; values: []; - observation_id: string[] + observation_id: string[]; + design:ExperimentalDesign; } export interface Sample { @@ -52,6 +54,8 @@ export class SampleSelectionComponent implements OnInit { sampleTable: FormGroup; sampleControl: FormArray; sampleTouchedRows: any; + private initialSelection = [] + selection = new SelectionModel(true, this.initialSelection /* multiple */); panel_disabled: boolean = true panel_expanded: boolean = false model_loaded: boolean = false @@ -72,15 +76,14 @@ export class SampleSelectionComponent implements OnInit { technicalReplicateIsChecked: boolean = false TechnicalReplicateNumber: number = 1; displayedMaterialColumns: string[] = ['biologicalMaterialId', 'materialId', 'genus', 'species', 'lindaID', 'select']; - + labelPosition_sample_ID: 'autogenerate ids' | 'paste ids' = 'autogenerate ids'; //displayedMaterialColumns: string[] = ['Biological material ID', 'Material source ID (Holding institute/stock centre, accession)', 'Genus', 'Species', 'Database id', 'select']; displayedSampleColumns: string[] = ['Sample ID', 'Plant anatomical entity', 'Plant structure development stage', 'Sample description', 'External ID', 'Collection date', 'Edit']; private sampledataSource: MatTableDataSource = new MatTableDataSource([]); materialdataSource = new MatTableDataSource(BM_ELEMENT_DATA); @ViewChild(MatSort, { static: true }) sort: MatSort; @ViewChild(MatTable, { static: false }) table: MatTable - private initialSelection = [] - selection = new SelectionModel(true, this.initialSelection /* multiple */); + sample_index_row: number = 0; SampleDate: Date; sample_ready: boolean = false; @@ -89,19 +92,22 @@ export class SampleSelectionComponent implements OnInit { SampleDescription: string = ""; PlantAnatomicalEntity: string = ""; PlantStructureDevelopmentStage: string = "" - + pasted_ids:string[]=[] + design:ExperimentalDesign; constructor( private fb: FormBuilder, private globalService: GlobalService, private _cdr: ChangeDetectorRef, private alertService: AlertService, - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: DialogData, public dialog: MatDialog) { + public dialog: MatDialog, + public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData + ) { this.model_id = this.data.model_id; this.model_type = this.data.model_type; this.parent_id = this.data.parent_id; this.bm_data = this.data.bm_data this.observation_id = this.data.observation_id + this.design=this.data.design this.result = [] this.sampleTable = this.fb.group({ sampleRows: this.fb.array([]) @@ -133,7 +139,6 @@ export class SampleSelectionComponent implements OnInit { this._cdr.detectChanges() } - load_material(): BiologicalMaterialDialogModel[] { return this.bm_data.filter(element => this.observation_id.includes(element["obsUUID"])) @@ -254,41 +259,45 @@ export class SampleSelectionComponent implements OnInit { this.sampleControl = this.sampleTable.get('sampleRows') as FormArray; this.sampleControl.clear() this.totalSample = 0 - for (var i = 0; i < this.getTechnicalReplicateNumber(); i++) { - for (var j = 0; j < this.selection.selected.length; j++) { - for (var k = 0; k < this.totalSampleByMaterial; k++) { - var select = this.selection.selected[j] - //console.log("selected: ", select) - var bm_id = select["bmUUID"] - //console.log(bm_id) - this.sampleControl.push(this.initiateSampleForm(select)) - - if (this.autogenerateIsChecked) { - let rep_label = "_rep_" + (k + 1) + if (this.selection.selected.length===0){ + this.alertService.error("You have to select at least one material in the upper table !! ") + this.ready_to_show = false + } + else{ + for (var i = 0; i < this.getTechnicalReplicateNumber(); i++) { + for (var j = 0; j < this.selection.selected.length; j++) { + for (var k = 0; k < this.totalSampleByMaterial; k++) { var select = this.selection.selected[j] //console.log("selected: ", select) - + var bm_id = select["bmUUID"] //console.log(bm_id) - - /* for (var j = 0; j < this.sampleControl.controls.length; j++) { */ - //console.log(this.sampleControl.controls[j].value) - var auto_generated_sampleid = select['biologicalMaterialId'] + '_sample_' + (i + 1) + rep_label - //this.sampleControl.controls[j].patchValue({'Sample ID': select['biologicalMaterialId'] }) - this.sampleControl.controls[this.totalSample].get('Sample ID').patchValue(auto_generated_sampleid) - this.sampleControl.controls[this.totalSample].get('Sample ID').setValue(auto_generated_sampleid) - + this.sampleControl.push(this.initiateSampleForm(select)) + + if (this.autogenerateIsChecked) { + let rep_label = "_rep_" + (k + 1) + var select = this.selection.selected[j] + //console.log("selected: ", select) + + //console.log(bm_id) + + /* for (var j = 0; j < this.sampleControl.controls.length; j++) { */ + //console.log(this.sampleControl.controls[j].value) + var auto_generated_sampleid = select['biologicalMaterialId'] + '_sample_' + (i + 1) + rep_label + //this.sampleControl.controls[j].patchValue({'Sample ID': select['biologicalMaterialId'] }) + this.sampleControl.controls[this.totalSample].get('Sample ID').patchValue(auto_generated_sampleid) + this.sampleControl.controls[this.totalSample].get('Sample ID').setValue(auto_generated_sampleid) + + } + this.totalSample++ } - this.totalSample++ } } + this.autoGenerateID() + this.sampledataSource = new MatTableDataSource((this.sampleTable.get('sampleRows') as FormArray).controls); + this.sampledataSource.paginator = this.sampleselectionpaginator; + this._cdr.detectChanges() + this.ready_to_show = true } - /* if (this.autogenerateIsChecked){ - this.autoGenerateID() - } */ - this.sampledataSource = new MatTableDataSource((this.sampleTable.get('sampleRows') as FormArray).controls); - this.sampledataSource.paginator = this.sampleselectionpaginator; - this._cdr.detectChanges() - this.ready_to_show = true } autoGenerateID() { this.sampleControl = this.sampleTable.get('sampleRows') as FormArray; @@ -298,7 +307,8 @@ export class SampleSelectionComponent implements OnInit { //console.log('this.selection.selected.length: ',this.selection.selected.length) //console.log("autogenerate id activated") this.totalSample = 0 - for (var k = 0; k < this.totalSampleByMaterial; k++) { + console.log(this.design['Associated sample'].value.length) + for (var k = this.design['Associated sample'].value.length; k < (this.totalSampleByMaterial+this.design['Associated sample'].value.length); k++) { for (var j = 0; j < this.selection.selected.length; j++) { for (var i = 0; i < this.getTechnicalReplicateNumber(); i++) { let rep_label = "_rep_" + (i + 1) @@ -339,6 +349,43 @@ export class SampleSelectionComponent implements OnInit { this.ready_to_show = false } } + + onInput(content: string, type:string) { + if (type==='extid'){ + if ([...new Set(content.split("\n"))].length!==this.selection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.selection.selected.length){ + this.alertService.error("you need to have same number of sample IDs than biological materials selected. in your case, you need " +this.selection.selected.length + " samples Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + } + onPaste(event: ClipboardEvent) { + let clipboardData = event.clipboardData; + let content = clipboardData.getData('text'); + if ([...new Set(content.split("\n"))].length!==this.selection.selected.length){ + this.alertService.error("you have duplicated Ids !!! ") + } + else{ + if (content.split("\n").length!==this.selection.selected.length){ + this.alertService.error("you need to have same number of sample IDs than biological materials selected. in your case, you need " +this.selection.selected.length + " samples Ids") + } + else{ + this.alertService.success("Correct number of observation IDs !! ") + this.pasted_ids=content.split("\n") + } + } + } + get get_total():number{ + let total=this.selection.selected.length*this.TechnicalReplicateNumber*this.totalSampleByMaterial + return total + } get get_sampledataSource() { return this.sampledataSource } get getSampleDescription() { @@ -384,10 +431,12 @@ export class SampleSelectionComponent implements OnInit { this.selection.toggle(row) if (this.selection.selected.length === 0) { this.panel_disabled = true + this.panel_expanded = false } - else ( + else { this.panel_disabled = false - ) + this.panel_expanded = true + } } /** Selects all rows if they are not all selected; otherwise clear selection. */ masterToggle() { @@ -402,10 +451,27 @@ export class SampleSelectionComponent implements OnInit { onSampleNumberChange(value: number) { this.TechnicalReplicateNumber = value } + applyFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.materialdataSource.filter = filterValue.trim().toLowerCase(); + + if (this.materialdataSource.paginator) { + this.materialdataSource.paginator.firstPage(); + } + } onGlobalOntologyTermSelection(ontology_id: string, key: string, multiple: boolean = true) { //this.show_spinner = true; //console.log(key) //console.log(ontology_id) + let subClassof="" + if (key ==='Plant anatomical entity'){ + subClassof="PO:0025131" + } + else{ + subClassof="PO:0009012" + + } + const dialogRef = this.dialog.open(OntologyTreeComponent, { disableClose: true, width: '1000px', autoFocus: true, maxHeight: '100vh', data: { ontology_id: ontology_id, selected_term: null, selected_set: [], selected_key: "", uncheckable: false, multiple: multiple, model_type: this.model_type, mode_simplified: false, observed: false, sub_class_of: "" } }); // dialogRef..afterOpened().subscribe(result => { // this.show_spinner = false; @@ -495,7 +561,7 @@ export class SampleSelectionComponent implements OnInit { this.dialogRef.close({ event: "Confirmed", sample_data: sample_data }); } else ( - this.alertService.error("Some sample do not have ID associated") + this.alertService.error("Some fields are still empty !! ") ) diff --git a/src/app/modules/application/dialogs/selection.component.html b/src/app/modules/application/dialogs/selection.component.html index b879c2f3..c8bd6cd0 100644 --- a/src/app/modules/application/dialogs/selection.component.html +++ b/src/app/modules/application/dialogs/selection.component.html @@ -23,8 +23,6 @@

    Select {{model_type}}

    - -
    diff --git a/src/app/modules/application/dialogs/selection.component.ts b/src/app/modules/application/dialogs/selection.component.ts index e44c7ed0..d6485188 100644 --- a/src/app/modules/application/dialogs/selection.component.ts +++ b/src/app/modules/application/dialogs/selection.component.ts @@ -88,7 +88,7 @@ export class SelectionComponent implements OnInit, AfterViewInit { this.result = data; } ); - } + } ngAfterViewInit() { if (this.model_type==='experimental_factor'){ this.sources[this.model_type].sort= this.sortef; diff --git a/src/app/modules/application/dialogs/template-selection.component.html b/src/app/modules/application/dialogs/template-selection.component.html index 02692023..eb9e9bc3 100644 --- a/src/app/modules/application/dialogs/template-selection.component.html +++ b/src/app/modules/application/dialogs/template-selection.component.html @@ -4,10 +4,39 @@

    Select {{search_type}}

    Which {{search_type}}s do you plan to use ?

    -
    + + + + + + + + + + + + + + +
    {{displayedColumns[i]}} {{element[column]}} + + + + + +
    + + + +
    diff --git a/src/app/modules/application/dialogs/template-selection.component.ts b/src/app/modules/application/dialogs/template-selection.component.ts index ba966878..35106bf9 100644 --- a/src/app/modules/application/dialogs/template-selection.component.ts +++ b/src/app/modules/application/dialogs/template-selection.component.ts @@ -1,5 +1,10 @@ -import { Component, OnInit, Inject } from '@angular/core'; +import { SelectionModel } from '@angular/cdk/collections'; +import { Component, OnInit, Inject, ViewChild, ChangeDetectorRef } from '@angular/core'; +import { MatPaginator, MatSort, MatTable, MatTableDataSource } from '@angular/material'; import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; +import { timeStamp } from 'console'; +import { ObservedVariableInterface } from 'src/app/models/linda/observed-variable'; +import { TemplateElement } from 'src/app/models/template_models'; import { GlobalService} from '../../../services'; @@ -13,20 +18,35 @@ interface DialogData { values:{}; } +const TEMPLATE_ELEM: TemplateElement[] = [] +const OBSERVED_VARIABLE_ELEM: ObservedVariableInterface[] = [] @Component({ selector: 'app-template-selection', templateUrl: './template-selection.component.html', styleUrls: ['./template-selection.component.css'] }) export class TemplateSelectionComponent implements OnInit { + @ViewChild('paginator', { static: true }) paginator: MatPaginator; + @ViewChild(MatSort, { static: true }) sort: MatSort; + @ViewChild(MatTable, { static: false }) table: MatTable private model_id: string; private user_key: string; private result:[] private model_type: string; private parent_id: string; search_type:string + + dataSource = new MatTableDataSource(OBSERVED_VARIABLE_ELEM); + displayedColumns: string[] = ['Template type', 'select']; + private initialSelection = [] + selection = new SelectionModel(false, this.initialSelection /* multiple */); + panel_disabled: boolean=false; + - constructor(private globalService : GlobalService,public dialogRef: MatDialogRef, + constructor( + private globalService : GlobalService, + private _cdr: ChangeDetectorRef, + public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData) { this.search_type= this.data.search_type @@ -43,6 +63,15 @@ export class TemplateSelectionComponent implements OnInit { this.globalService.get_templates_by_user(this.user_key,this.model_type).toPromise().then( data => { this.result=data; + console.log(data) + this.displayedColumns=Object.keys(data[0]).filter(key=>!key.startsWith('_')) + this.displayedColumns.push('select') + //console.log(this.materialdataSource) + this.dataSource.data = data + this.dataSource.sort = this.sort + this.dataSource.paginator = this.paginator; + this._cdr.detectChanges() + } ); } @@ -66,7 +95,8 @@ export class TemplateSelectionComponent implements OnInit { var parent_name=this.data.parent_id.split("/")[0] var parent_key=this.data.parent_id.split("/")[1] - + console.log(parent_name) + console.log(parent_key) var child_type="observed_variables" this.globalService.get_type_child_from_parent(parent_name,parent_key,child_type) .toPromise().then( @@ -96,7 +126,7 @@ export class TemplateSelectionComponent implements OnInit { } onSelect(values:string){ - + console.log(values) this.data.model_id=values this.result.forEach( attr => { @@ -109,17 +139,39 @@ export class TemplateSelectionComponent implements OnInit { get get_parent_id(){ return this.parent_id } + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.dataSource.data.length; + return numSelected == numRows; + } + rowToggle(row) { + this.selection.toggle(row) + if (this.selection.selected.length === 0) { + this.panel_disabled = true + } + else ( + this.panel_disabled = false + ) + } + /** Selects all rows if they are not all selected; otherwise clear selection. */ + masterToggle() { + this.isAllSelected() ? + this.selection.clear() : + this.dataSource.data.forEach(row => this.selection.select(row)); this.panel_disabled = false + } + get get_result(){ + return this.result; + } onNoClick(): void { this.dialogRef.close(); } onOkClick(): void { //this.data.template_id=this.template_id - this.dialogRef.close(this.data); + console.log(this.selection.selected[0]) + this.dialogRef.close(this.selection.selected[0]); } - get get_result(){ - return this.result; - } + } diff --git a/src/app/modules/application/documentation/ontology-description.component.html b/src/app/modules/application/documentation/ontology-description.component.html index 5d950ff7..caab627c 100644 --- a/src/app/modules/application/documentation/ontology-description.component.html +++ b/src/app/modules/application/documentation/ontology-description.component.html @@ -145,7 +145,7 @@

    CROP Ontology 715

    - +

    diff --git a/src/app/modules/application/documentation/ontology-description.component.ts b/src/app/modules/application/documentation/ontology-description.component.ts index 856fc906..19e84513 100644 --- a/src/app/modules/application/documentation/ontology-description.component.ts +++ b/src/app/modules/application/documentation/ontology-description.component.ts @@ -16,7 +16,7 @@ export class OntologyDescriptionComponent implements OnInit { onSelect(values:string) { console.log(values) - const dialogRef = this.dialog.open(OntologyTreeComponent, { disableClose: true, width: '1000px', autoFocus: false, maxHeight: '90vh', data: { ontology_id: values, selected_term: null, selected_key:"", selected_set: [], multiple: false, uncheckable: true, observed: true, mode_simplified:true } }); + const dialogRef = this.dialog.open(OntologyTreeComponent, { disableClose: true, width: '1000px', autoFocus: false, maxHeight: '90vh', data: { ontology_id: values, selected_term: null, selected_key:"", selected_set: [], multiple: false, uncheckable: true, observed: true, mode_simplified:false } }); //const dialogRef = this.dialog.open(OntologyTreeComponent, { width: '1000px', autoFocus: false, maxHeight: '90vh', data: { ontology_id: values, selected_term: null, selected_set:[], uncheckable: true, multiple:false}}); dialogRef.afterClosed().subscribe(result => { if (result!==undefined){ diff --git a/src/app/modules/application/file_handlers/download.component.html b/src/app/modules/application/file_handlers/download.component.html index c0dad0ff..6b667cd0 100644 --- a/src/app/modules/application/file_handlers/download.component.html +++ b/src/app/modules/application/file_handlers/download.component.html @@ -255,7 +255,7 @@
    Notes
    [xAxis]="xAxis" [yAxis]="yAxis" [xAxisLabel]="xAxisLabel" - [maxXAxisTickLength]=10 + [maxXAxisTickLength]="10" [yAxisLabel]="yAxisLabel" [timeline]="timeline" [rotateXAxisTicks]="rotateXAxisTicks" diff --git a/src/app/modules/application/file_handlers/download.component.ts b/src/app/modules/application/file_handlers/download.component.ts index b1c67ead..1d9a2d93 100644 --- a/src/app/modules/application/file_handlers/download.component.ts +++ b/src/app/modules/application/file_handlers/download.component.ts @@ -245,6 +245,9 @@ export class DownloadComponent implements OnInit, OnDestroy { this.model_key = params['model_key']; this.mode = params['mode']; this.parent_id = params['parent_id'] + if (!this.mode){ + this.mode='create' + } } ); this.selectedOption = { name: 'Assign MIAPPE components', value: '' } @@ -265,13 +268,13 @@ export class DownloadComponent implements OnInit, OnDestroy { ngOnInit() { this.observation_unit_type = "select observation unit type" this.selected_file = "" - console.log(this.mode) - console.log(this.model_type) - console.log(this.parent_id) + //console.log(g(this.mode) + //console.log(g(this.model_type) + //console.log(g(this.parent_id) if (this.mode.includes('edit')) { this.globalService.get_by_key(this.model_key, this.model_type).pipe(first()).toPromise().then(received_data => { this.data = received_data; - console.log(this.data) + //console.log(g(this.data) this.selected_file = this.data["filename"] this.headers = this.data["headers"]; this.associated_headers = this.data["associated_headers"]; @@ -337,7 +340,7 @@ export class DownloadComponent implements OnInit, OnDestroy { this.extract_fields_options['options'].push({ header: "", associated_linda_id: "", name: "associated_biological_material_id", value: "" }) } - console.log(this.data_files) + //console.log(g(this.data_files) if (this.data_files.length === 2) { this.data_files[0].forEach(data_file => { if (!this.filename_used.includes(data_file.filename)) { @@ -623,8 +626,8 @@ export class DownloadComponent implements OnInit, OnDestroy { } onModify(values: string, key: string, filename: string) { - console.log(values) - console.log(key) + //console.log(g(values) + //console.log(g(key) // Mark this associated_header as selected this.associated_headers_by_filename[filename].filter(prop => prop.header == key).forEach(prop => { prop.selected = true; }); if (values === "time") { @@ -656,16 +659,16 @@ export class DownloadComponent implements OnInit, OnDestroy { this.associated_headers_by_filename[filename].filter(prop => prop.header == key).forEach(prop => { prop.is_time_values = false; }); //this.associated_headers[key]={selected:true, associated_term_id:"", associated_component:values, is_time_values:false} - console.log(this.associated_headers_by_filename[filename]) + //console.log(g(this.associated_headers_by_filename[filename]) } } onExtractField(values: string, key: string, filename: string) { - console.log(values) + //console.log(g(values) } // Only used for model_type metadata file onExtractStudy(values: string, key: string) { - console.log(values) - console.log(key) + //console.log(g(values) + //console.log(g(key) if (values === "time") { const dialogRef = this.dialog.open(DateformatComponent, { disableClose: true, width: '1000px', data: { date_format: "" } }); dialogRef.afterClosed().subscribe(result => { @@ -736,7 +739,7 @@ export class DownloadComponent implements OnInit, OnDestroy { //} } Focused(values: string, key: string) { - console.log(values) + //console.log(g(values) } onShowHelp(page: string) { // Add argument for mode : @@ -747,7 +750,7 @@ export class DownloadComponent implements OnInit, OnDestroy { dialogRef.afterClosed().subscribe(result => { if (result) { if (result.event == 'Confirmed') { - console.log("hello") + //console.log(g("hello") } } }); @@ -806,8 +809,8 @@ export class DownloadComponent implements OnInit, OnDestroy { } // used for visualization itemSelectionDataFileToggle(key: string, filename: string): void { - console.log(this.associated_headers) - console.log(this.associated_headers_by_filename[this.fileName]) + //console.log(g(this.associated_headers) + //console.log(g(this.associated_headers_by_filename[this.fileName]) this.checklistSelection.toggle(key); // selected row if (this.checklistSelection.isSelected(key)) { @@ -854,8 +857,8 @@ export class DownloadComponent implements OnInit, OnDestroy { /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */ // used only for (model_type==='data_file' || model_type==='study') && (mode==='extract-again' || mode==='download') itemSelectionToggle(key: string): void { - console.log(this.associated_headers) - console.log(this.associated_headers_by_filename[this.fileName]) + //console.log(g(this.associated_headers) + //console.log(g(this.associated_headers_by_filename[this.fileName]) this.checklistSelection.toggle(key); // selected row if (this.checklistSelection.isSelected(key)) { @@ -916,7 +919,7 @@ export class DownloadComponent implements OnInit, OnDestroy { * @beta */ onSelectChart(data): void { - console.log('Item clicked', JSON.parse(JSON.stringify(data))); + //console.log(g('Item clicked', JSON.parse(JSON.stringify(data))); } /** * display Stringify Json data from chart when chart is activated - Event function from ngx-charts-line-chart @@ -930,7 +933,7 @@ export class DownloadComponent implements OnInit, OnDestroy { * @beta */ onActivate(data): void { - console.log('Activate', JSON.parse(JSON.stringify(data))); + //console.log(g('Activate', JSON.parse(JSON.stringify(data))); } /** * display Stringify Json data from chart when chart is deactivated - Event function from ngx-charts-line-chart @@ -944,7 +947,7 @@ export class DownloadComponent implements OnInit, OnDestroy { * @beta */ onDeactivate(data): void { - console.log('Deactivate', JSON.parse(JSON.stringify(data))); + //console.log(g('Deactivate', JSON.parse(JSON.stringify(data))); } /** * get scale type for data @@ -1237,10 +1240,10 @@ export class DownloadComponent implements OnInit, OnDestroy { } onNext(index: any) { // this.demo_subset+=1 - console.log(index) - console.log(this.loaded) + //console.log(g(index) + //console.log(g(this.loaded) if (index == "load_csv") { - console.log("step2") + //console.log(g("step2") this.fileName = "my_data.csv" var csv_text = "Study_ID,plotID,treatment,plant.height,code_ID\nMaizeStudy1,plot1,rainfed,23,B73\nMaizeStudy1,plot2,rainfed,22,PH207\nMaizeStudy1,plot3,rainfed,24,Oh43\nMaizeStudy1,plot4,rainfed,21.8,W64A\nMaizeStudy1,plot5,rainfed,23.4,EZ47\nMaizeStudy1,plot6,watered,48.3,B73\nMaizeStudy1,plot7,watered,49.5,PH207\nMaizeStudy1,plot8,watered,52,Oh43\nMaizeStudy1,plot9,watered,48,W64A\nMaizeStudy1,plot10,watered,45,EZ47" this.load_csv(csv_text, 100, 100, ",") @@ -1275,7 +1278,7 @@ export class DownloadComponent implements OnInit, OnDestroy { } onClickTour() { this.currentUser = JSON.parse(localStorage.getItem('currentUser')); - console.log(this.currentUser) + //console.log(g(this.currentUser) if (this.currentUser['tutoriel_step'] === "13") { this.joyrideService.startTour( { steps: ['StepMenuForm', 'StepExampleForm', 'StepTableForm', 'Row0', 'Row1', 'Row2', 'Row3', 'Row4', 'StepUpload1Form', 'StepUpload2Form', 'StepUpload3Form'], stepDefaultPosition: 'bottom' } // Your steps order @@ -1287,20 +1290,20 @@ export class DownloadComponent implements OnInit, OnDestroy { /** * // TODO: need to review this part => Now files are child of investigations and study will be created in extract.component.ts */ - onSubmit() { + async onSubmit() { //metadatafiles creation (obsolete ? ) if (this.mode === "create") { - console.log(this.csv_lines_array.length) + //console.log(this.csv_lines_array.length) if (this.csv_lines_array.length !== 0) { - console.log(this.csv_lines_dict) + //console.log(this.csv_lines_dict) const formData = new FormData(); formData.append('file', this.form.get('file').value); let user = JSON.parse(localStorage.getItem('currentUser')); //let parent_id="studies/981995" //this.associated_headers['associated_linda_id']=this.parent_id - //this.fileService.upload2(this.fileName,this.csv_lines_array,this.headers,this.associated_headers,this.parent_id).pipe(first()).toPromise().then(data => {console.log(data);}) + //this.fileService.upload2(this.fileName,this.csv_lines_array,this.headers,this.associated_headers,this.parent_id).pipe(first()).toPromise().then(data => {//console.log(g(data);}) - this.fileService.upload3(this.fileName, this.csv_lines_dict, this.headers, this.associated_headers, this.parent_id).pipe(first()).toPromise().then(data => { console.log(data); }) + const data=await this.fileService.upload3(this.fileName, this.csv_lines_dict, this.headers, this.associated_headers, this.parent_id).pipe(first()).toPromise()//.then(data => { //console.log(g(data); }) //this.router.navigate(['/projects_tree'], { queryParams: { key: user._key } }); this.router.navigate(['/projects_page']); @@ -1312,11 +1315,11 @@ export class DownloadComponent implements OnInit, OnDestroy { ///extract from files else if (this.mode === "download") { /* if (Object.keys(this.data_to_extract).length === 0) { - console.log(this.data_to_extract) + //console.log(g(this.data_to_extract) this.alertService.error("You need to assign one original header for Study component Label; see Help button for more details") } - console.log(this.data_to_extract) - */ + //console.log(g(this.data_to_extract) + */ if (this.data_to_extract['Study unique ID']) { let groups_label = [] @@ -1383,7 +1386,7 @@ export class DownloadComponent implements OnInit, OnDestroy { this.globalService.add_parent_and_childs(study_model, data_model, 'study', this.parent_id, 'data_file').pipe(first()).toPromise().then( add_study_res => { if (add_study_res["success"]) { - console.log(add_study_res["message"]) + //console.log(g(add_study_res["message"]) this.router.navigate(['/projects_page']); } }); @@ -1394,7 +1397,7 @@ export class DownloadComponent implements OnInit, OnDestroy { this.globalService.add(study_model, 'study', this.parent_id, false).pipe(first()).toPromise().then( add_study_res => { if (add_study_res["success"]) { - console.log(add_study_res["message"]) + //console.log(g(add_study_res["message"]) this.router.navigate(['/projects_tree']); } } @@ -1414,7 +1417,7 @@ export class DownloadComponent implements OnInit, OnDestroy { var study_component_set_array = Array.from(study_component_set); // foreach study identifier found other than Study unique ID for (var i = 0; i < study_component_set_array.length; i++) { - console.log(study_component_set_array[i]) + //console.log(g(study_component_set_array[i]) let unique_study_label = study_component_set_array[i] // // get the header label for study column in the csv file // var study_column_name = this.data_to_extract['study'] @@ -1461,12 +1464,12 @@ export class DownloadComponent implements OnInit, OnDestroy { // console.log(unique_study_label) // console.log(this.parent_id.split("/")[1]) data['study_ids'].forEach(study_id => { - console.log(study_id) + //console.log(g(study_id) this.fileService.upload4(data_model, study_id).pipe(first()).toPromise().then( data_upload => { - console.log(data_upload) + //console.log(g(data_upload) if (data_upload[0]["id"]) { - console.log(data_upload[0]["new"]["Data file description"]) + //console.log(g(data_upload[0]["new"]["Data file description"]) if (!this.currentUser.tutoriel_done) { @@ -1500,10 +1503,10 @@ export class DownloadComponent implements OnInit, OnDestroy { if (this.labelPosition === "no_study_id") { return this.userService.get_person_id(this.currentUser._key).toPromise().then( person_id => { - console.log(person_id) + //console.log(g(person_id) this.globalService.get_studies(this.parent_id.split("/")[1],person_id[0].split("/")[1]).pipe(first()).toPromise().then( data => { - console.log(data) + //console.log(g(data) let unique_study_label="" // add dataffiles to all studies found let data_model_dict = {} @@ -1515,17 +1518,17 @@ export class DownloadComponent implements OnInit, OnDestroy { data_model['Data'] = this.csv_lines_dict data_model['associated_headers'] = this.associated_headers_by_filename[this.fileName] data_model['headers'] = this.headers - console.log(data_model) + //console.log(g(data_model) data.forEach(study => { let study_id=study['_id'] data_model['Data file description'] = 'Data have been extracted for ' + study_id + ' from ' + this.fileName - console.log(study_id) + //console.log(g(study_id) this.fileService.upload4(data_model, study_id).pipe(first()).toPromise().then( data_upload => { - console.log(data_upload) + //console.log(g(data_upload) if (data_upload[0]["id"]) { - console.log(data_upload[0]["new"]["Data file description"]) + //console.log(g(data_upload[0]["new"]["Data file description"]) if (!this.currentUser.tutoriel_done) { @@ -1564,7 +1567,7 @@ export class DownloadComponent implements OnInit, OnDestroy { if (this.csv_lines_array.length !== 0) { let user = JSON.parse(localStorage.getItem('currentUser')); //let parent_id="studies/981995" - this.globalService.update_document(this.model_key, this.data, this.model_type).pipe(first()).toPromise().then(data => { console.log(data); }) + const data=await this.globalService.update_document(this.model_key, this.data, this.model_type).pipe(first()).toPromise()//.then(data => { console.log(data); }) this.router.navigate(['/projects_tree']); } else { @@ -1573,7 +1576,7 @@ export class DownloadComponent implements OnInit, OnDestroy { } ///observations unit mode else if (this.mode === 'extract-form') { - console.log("extract observation units") + //console.log("extract observation units") } //mode extract-again diff --git a/src/app/modules/application/forms/form.component.html b/src/app/modules/application/forms/form.component.html index 67ff19d4..0725ae3f 100644 --- a/src/app/modules/application/forms/form.component.html +++ b/src/app/modules/application/forms/form.component.html @@ -1,76 +1,87 @@ -
    - -
    - - - - - - - - + (next)="on_Next()"> + +
    + + + - - - -

    Data submission

    - -
    -

    Feel free to complete the form !
    - When it's done, click on to submit your form !!

    -
    -
    -

    As you can see, your form has been filled with the corresponding values ! Feel free to complete the form ! - You can also save this form as template for further reuses !
    - When it's done, click on to submit your form !!

    -
    -
    - - -
    - - - - - - + + +

    Data submission

    + +
    +

    Feel free to complete the form !
    + When it's done, click on to submit your form !! +

    +
    +
    +

    As you can see, your form has been filled with the corresponding values ! Feel free to complete + the form ! + You can also save this form as template for further reuses !
    + When it's done, click on to submit your form !! +

    +
    +
    + + +
    + + + + + +
    - +
    @@ -91,7 +102,7 @@
    Definition
    growth facility). Like the investigation, it contains a unique identifier field. An investigation must have one or more studies.

    -->
    - +

    Experimental factors

    - - -
    Available actions
    -

    The highlighted menu allows you to navigate through form pages (Not all forms have multiple pages !! ).

    -
      -
      - -
    • Click on if you want to go back in previous form page

    • - -
      -
      - -
    • Click on if you want to go back in previous form page

    • - -
      - - -
    • Click on if you want to cancel the current form

    • -
    • Click on when you have completed the form

    • -
    • Click on to replay tutorial for this form

    • - -
      - -
    • Click on if you want to go to next form page

    • - -
      -
      - -
    • Click on if you want to go to next form page

    • - -
      -
    -
      -
    • - checkbox on the left will save your form as a template form, available for furthers reuses

    • -
    -
    - -
    - -
    Available ontologies
    + + +
    Available actions
    +

    The highlighted menu allows you to navigate through form pages (Not all forms have multiple pages !! + ).

    +
      +
      + +
    • +

      Click on if you want to go back in previous + form page

      +
    • + +
      +
      + +
    • +

      Click on if you want to go back in previous + form page

      +
    • + +
      + + +
    • +

      Click on if you want to cancel the current + form

      +
    • +
    • +

      Click on when you have completed the form

      +
    • +
    • +

      Click on to replay tutorial for this form

      +
    • + +
      + +
    • +

      Click on if you want to go to next form page +

      +
    • + +
      +
      + +
    • +

      Click on if you want to go to next form page +

      +
    • + +
      +
      -
    • EFO : The Experimental Factor Ontology (EFO) provides a systematic description of many experimental variables available in EBI databases, and for projects such as the GWAS catalog.

    • -
    • PECO : A structured, controlled vocabulary which describes the treatments, growing conditions, and/or study types used in plant biology experiments.

    • +
    • +

      + checkbox on + the left will save your form as a template form, available for furthers reuses +

      +
    + +
    + +
    Available ontologies
    +
      +
    • +

      EFO : The Experimental Factor Ontology (EFO) provides a systematic description of + many experimental variables available in EBI databases, and for projects such as the + GWAS catalog.

      +
    • +
    • +

      PECO : A structured, controlled vocabulary which describes the treatments, growing + conditions, and/or study types used in plant biology experiments.

      +
    • +
    +
    - -
    + +
    - -
    + +
    -

    {{ model_type[0].toUpperCase() + model_type.slice(1).replace("_"," ")}}

    -

    {{get_model['Definition']}}

    - -
    -
    -
    -
    - - - - - -
    -
    - -
    - - - +

    {{ model_type[0].toUpperCase() + model_type.slice(1).replace("_"," ")}}

    +

    {{get_model['Definition']}}

    + + +
    +
    +
    + + + - - - - -
    - - -
    -

    studies

    - -

    For study form, there are two field that you can fill using ontology trees

    -
    Type of experimental design (Ontology field example)
    -

    - Click on corresponding ontology button CO_715 or OBI to define your experimental design -

    -
    - -
    Type of growth facility
    -

    - Click on corresponding ontology button CO_715 or OBI to define your experimental design -

    -
    + + +
    +

    studies

    -
    Notes
    -

    You can use the search box in the top of the ontology tree to quickly find terms

    -
    -
    - -
    +

    For study form, there are two field that you can fill using ontology trees

    +
    Type of experimental design (Ontology field example)
    +

    + Click on corresponding ontology button CO_715 or OBI to define your experimental + design +

    + + +
    Type of growth facility
    +

    + Click on corresponding ontology button CO_715 or OBI to define your experimental + design +

    +
    + +
    Notes
    +

    You can use the search box in the top of the ontology tree to quickly find terms +

    +
    +
    -

    Experimental factors

    - -
    Ontology field (Ontology field)
    -

    - Ontology term is required for this field. You can use tree at you disposal to explore the following ontologies -

    -
    - -
    Experimental factor accession number
    -

    - Click on corresponding ontology button EFO or PECO to define your experimental factor using ontology accession number -

    -
    +
    -
    -
    -

    Observed variables

    - -
    Ontology field (Ontology field)
    -

    - Ontology term is required for this field. You can use tree at you disposal to explore the following ontologies -

    -
    - -
    Trait accession number
    -

    - Click on available ontologies (CO_322, CO_325, CO_331, XEO, Solanacae) to define trait accession number. - -

    -
    - -
    Notes
    -

    - You can use the search box in the top of the ontology tree to quickly find terms -

    -

    - If selected ontology term contains definition, this definition will filled the Trait name field -

    -
    -
    - -
    +

    Experimental factors

    + +
    Ontology field (Ontology field)
    +

    + Ontology term is required for this field. You can use tree at you disposal to + explore the following ontologies +

    +
    + +
    Experimental factor accession number
    +

    + Click on corresponding ontology button EFO or PECO to define your experimental + factor using ontology accession number +

    +
    - -
    - -
    -
    - -
    - - -
    -

    Investigation Form

    -
    -
    -

    Study Form

    -
    +
    +

    Observed variables

    -
    Unique identifier field
    -

    - This field requires a unique identifier !!
    +

    Ontology field (Ontology field)
    +

    + Ontology term is required for this field. You can use tree at you disposal to + explore the following ontologies

    - -
    -
    Investigation Unique ID (Unique identifier)
    -

    - Identifier comprising the unique name of the institution/database hosting the submission of the - investigation data, and the accession number of the investigation in that institution. +

    Trait accession number
    +

    + Click on available ontologies (CO_322, CO_325, CO_331, XEO, Solanacae) to define + trait accession number. +

    + +
    Notes
    +

    + You can use the search box in the top of the ontology tree to quickly find terms +

    +

    + If selected ontology term contains definition, this definition will filled the + Trait name field +

    +
    +
    + + + + +
    + +
    +
    + +
    -
    + + +
    +

    Investigation Form

    +
    +
    +

    Study Form

    +
    -
    Study Unique ID (Unique identifier)
    -

    - Unique identifier comprising the name or identifier for the institution/database hosting - the submission of the study data, and the identifier of the study in that institution. +

    Unique identifier field
    +

    + This field requires a unique identifier !!

    + +
    + +
    Investigation Unique ID (Unique identifier)
    +

    + Identifier comprising the unique name of the institution/database + hosting the submission of the + investigation data, and the accession number of the investigation in + that institution. +

    +
    - - -
    Notes
    -

    You must complete this kind of field in order to submit your form !!

    -

    In addition, there may be more than one field requiring a unique identifier in a form !!

    -
    - - -
    -
    - - -
    -
    +
    + + +
    +
    - - - - -
    - - - -
    -

    Investigation Form

    - -
    Associated publication (free text field)
    -

    - An identifier for a literature publication where the investigation is described. Use of DOIs is recommended. -

    -
    -
    -
    -

    Studies

    - - -
    Contact institution (Free text field)
    -

    - Name and adress of the institution responsible for the study -

    -
    -
    - -
    -

    Experimental factors

    - -
    Experimental factor values (Formated text field)
    -

    List of possible values for the factor separated by ;

    -
    +
    -
    - -

    Observed variables

    - -
    Trait (Free text/Ontology field)
    -

    Name of the (plant or environmental) trait under observation

    -
    - -
    Notes
    -

    This field will be automatically filled when selecting Trait accession number with ontology tree;

    -
    + + + +
    +

    Investigation Form

    + +
    Associated publication (free text field)
    +

    + An identifier for a literature publication where the investigation is + described. Use of DOIs is recommended. +

    +
    +
    +
    +

    Studies

    + + +
    Contact institution (Free text field)
    +

    + Name and adress of the institution responsible for the study +

    +
    +
    + +
    +

    Experimental factors

    + +
    Experimental factor values (Formated text field)
    +

    List of possible values for the factor separated by ;

    +
    +
    +
    + +

    Observed variables

    + +
    Trait (Free text/Ontology field)
    +

    Name of the (plant or environmental) trait under observation

    +
    + +
    Notes
    +

    This field will be automatically filled when selecting Trait accession + number with ontology tree;

    +
    +
    + +
    +
    +
    {{field['key']}} is + required
    +
    minimum length is + required
    +
    Unique ID is + required - + already used !!
    - - -
    -
    {{field['key']}} is - required
    -
    minimum length is - required
    -
    Unique ID is required - - already used !!
    -
    - -
    - -
    -
    {{field['key']}} is - required
    - + +
    + +
    +
    {{field['key']}} is + required
    + +
    -
    - - - + + - -
    -

    Investigation Form

    - -
    Field description
    -

    - For each field, you have to described either manually or automatically using differents - kind of widgets thats help you to capture your data. -

    -

    - Some field are mandatory like some unique identifiers (submit button unabled) while others are optional and can be filled later.
    - There are three main types of fields: -

    -
      -
    1. Free text or unique identifier fields

    2. -
    3. Ontology term selection field

    4. -
    5. Date or time range field

    6. -
    -
    - -
    Notes
    -

    - This form must contain informations and details that describe your investigation (8 fields). -

    -
    -
    -
    -

    Studies

    - -
    Field description
    -

    - These form contains twenty fields to fullfill in order to capture informations and details from your study.
    - Like investigation, Study identifier requires to be unique.
    - Let's see what a unique identifier field looks like. -

    -
    - -
    -
    -

    Experimental factors

    - -
    Field description
    -

    - These form contains four fields to fill out over two pages to describe your observed variable..
    - You can use ontologies at your disposal ( EFO and PECO) to fill some of the form fields; -

    -
    -
    -
    -

    Observed variables

    - -
    Field description
    -

    - These form contains informations and details to describe your observed variable.
    - The observed variable form contains twelve fields to fill out over two pages.
    - You can use available ontologies to easily fill this form; -

    -

    - There are four important parts to fill to correctly describe an observed variable -

    -
      -
    1. The observed trait

    2. -
    3. The observed variable

    4. -
    5. The observation method

    6. -
    7. the observation scale

    8. -
    -
    -
    - - - - -
    - +
    +
    - +
    - -
    + -
    -

    Investigation Form

    - -
    Add a new investigation!
    - -

    Click on NEXT to fill a new form for an investigation short-called maizes1 with the following values:

    -
      -
    • Investigation unique ID : Maizes1

    • -
    • Short title : maizes1

    • -
    -
    - -
    Notes
    -

    The other fields can be fullfilled later

    -
    -
    -
    -

    Studies

    - -
    Add a new study!
    -

    Click on NEXT to fill a new form for a study short-called Study1 with the following values:

    -
      -
    • Study unique Id : MaizeStudy1

    • -
    • Short title : MaizeStudy1

    • -
    • Start date of study : 1/06/2021

    • -
    • End date of study : 30/06/2021

    • -
    • Type of experimental design : CO_715:0000145 (Complete block design)

    • -
    • Type of growth facility : CO_715:0000162 (Field environment condition)

    • -
    • Observation unit level hierarchy : block > rep > plot

    • -
    • Description of growth facility : field environement condition

    • -
    • Observation unit description : Observation units consisted in individual plots themselves consisting of a row of 5 plants at a density of 1 plant per square meter

    • -
    • Experimental site name : INRA, UE Diascope - Chemin de Mezouls - Domaine experimental de Melgueil - 34130 Mauguio - France

    • -
    • Study title : 2021 evaluation of hydric stress for a panel of 5 maize line (B73, PH207, Oh43, W64A, EZ47) at the experimental station of Maugio (France).

    • -
    • Cultural practices : Irrigation was applied according needs for one field and not applied for the other during the month of june to compare water stress.

    • - -
    -
    - -
    -
    -

    Experimental factors

    - -
    Add a new experimental factor!
    -

    Click on NEXT to fill a new form for an experimental factor of type Watering with the following values:

    -
      -
    • Experimental Factor type : Watering

    • -
    • Experimental Factor values : rainfed;watered

    • -
    • Experimental Factor accession number : EFO:0000470

    • -
    -
    - - -
    -
    -

    Observed variables

    - -
    Add a new observed variable!
    -

    - Click on NEXT to fill a new form for an observed variable called Plant height with the following values :
    -

    + +
    +

    Investigation Form

    + +
    Add a new investigation!
    + +

    Click on NEXT to fill a new form for an investigation short-called maizes1 with the + following values:

      -
    • Variable ID : PH_M_cm

    • -
    • Trait : Plant height

    • -
    • Method : PH - Measurement

    • -
    • Scale : cm

    • +
    • +

      Investigation unique ID : Maizes1

      +
    • +
    • +

      Short title : maizes1

      +
    -
    - - -
    +
    + +
    Notes
    +

    The other fields can be fullfilled later

    +
    +
    +
    +

    Studies

    + +
    Add a new study!
    +

    Click on NEXT to fill a new form for a study short-called Study1 with the following + values:

    +
      +
    • +

      Study unique Id : MaizeStudy1

      +
    • +
    • +

      Short title : MaizeStudy1

      +
    • +
    • +

      Start date of study : 1/06/2021

      +
    • +
    • +

      End date of study : 30/06/2021

      +
    • +
    • +

      Type of experimental design : CO_715:0000145 (Complete + block design)

      +
    • +
    • +

      Type of growth facility : CO_715:0000162 (Field environment + condition)

      +
    • +
    • +

      Observation unit level hierarchy : block > rep > plot +

      +
    • +
    • +

      Description of growth facility : field environement + condition

      +
    • +
    • +

      Observation unit description : Observation units consisted + in individual plots themselves consisting of a row of 5 plants at a density of 1 plant per + square meter

      +
    • +
    • +

      Experimental site name : INRA, UE Diascope - Chemin de + Mezouls - Domaine experimental de Melgueil - 34130 Mauguio - France

      +
    • +
    • +

      Study title : 2021 evaluation of hydric stress for a panel + of 5 maize line (B73, PH207, Oh43, W64A, EZ47) at the experimental station of Maugio + (France).

      +
    • +
    • +

      Cultural practices : Irrigation was applied according needs + for one field and not applied for the other during the month of june to compare water + stress.

      +
    • + +
    +
    + +
    +
    +

    Experimental factors

    + +
    Add a new experimental factor!
    +

    Click on NEXT to fill a new form for an experimental factor of type Watering with the + following values:

    +
      +
    • +

      Experimental Factor type : Watering

      +
    • +
    • +

      Experimental Factor values : rainfed;watered

      +
    • +
    • +

      Experimental Factor accession number : EFO:0000470

      +
    • +
    +
    + + +
    +
    +

    Observed variables

    + +
    Add a new observed variable!
    +

    + Click on NEXT to fill a new form for an observed variable called Plant height with the + following values :
    +

    +
      +
    • +

      Variable ID : PH_M_cm

      +
    • +
    • +

      Trait : Plant height

      +
    • +
    • +

      Method : PH - Measurement

      +
    • +
    • +

      Scale : cm

      +
    • +
    +
    + + +
    \ No newline at end of file diff --git a/src/app/modules/application/forms/form.component.ts b/src/app/modules/application/forms/form.component.ts index 9000a9da..88042d3f 100644 --- a/src/app/modules/application/forms/form.component.ts +++ b/src/app/modules/application/forms/form.component.ts @@ -110,7 +110,7 @@ export class FormComponent implements OnInit//, AfterViewInit // if (currentUser['tutoriel_checked'] === false){ // this.onClickTour() // } - this.onClickTour() + //this.onClickTour() }; onClickTour(help_mode:boolean=false) { @@ -278,7 +278,6 @@ export class FormComponent implements OnInit//, AfterViewInit return [year, month, day].join('-'); } initiateForm(): FormGroup { - console.log(this.model_id) let attributeFilters = {}; this.cleaned_model.forEach(attr => { this.validated_term[attr["key"]] = { selected: false, values: "" } @@ -286,14 +285,9 @@ export class FormComponent implements OnInit//, AfterViewInit if (attr["key"].includes("ID") || attr["key"].includes("accession number")) { //var uniqueIDValidatorComponent:UniqueIDValidatorComponent=new UniqueIDValidatorComponent() //attributeFilters[attr] = [this.model[attr].Example,[Validators.minLength(4)], UniqueIDValidatorComponent.alreadyThere(this.globalService, this.alertService,this.model_type, attr)]; - if (this.model_id.includes('investigations')){ - attributeFilters[attr["key"]] = [this.model_id, [Validators.required, Validators.minLength(4)], UniqueIDValidatorComponent.alreadyThere(this.globalService, this.alertService, this.model_type, attr["key"], this.parent_id, this.asTemplate)]; + attributeFilters[attr["key"]] = ['', [Validators.required, Validators.minLength(4)], UniqueIDValidatorComponent.alreadyThere(this.globalService, this.alertService, this.model_type, attr["key"], this.parent_id, this.asTemplate)]; - } - else{ - attributeFilters[attr["key"]] = ['', [Validators.required, Validators.minLength(4)], UniqueIDValidatorComponent.alreadyThere(this.globalService, this.alertService, this.model_type, attr["key"], this.parent_id, this.asTemplate)]; - - } + } else if (attr["key"].includes("Short title")) { attributeFilters[attr["key"]] = ['', [Validators.required, Validators.minLength(4)]]; diff --git a/src/app/modules/application/forms/study-form.component.html b/src/app/modules/application/forms/study-form.component.html index 548c5fe2..a365b79a 100644 --- a/src/app/modules/application/forms/study-form.component.html +++ b/src/app/modules/application/forms/study-form.component.html @@ -73,14 +73,22 @@

    Investigation Form

    +
    +

    Studies

    +
    Definition
    +

    Study corresponds to one experiment and defines its location (which by definition must be single per study) + and duration. It lists general fields documenting the experiment (e.g. experimental design, cultural practices, + growth facility). Like the investigation, it contains a unique identifier field. An investigation must have one or more studies. +

    + + +
    @@ -1515,8 +1528,10 @@
    Notes
    General study informations +
    +
    diff --git a/src/app/modules/application/forms/study-form.component.ts b/src/app/modules/application/forms/study-form.component.ts index 843615e5..0d15f7f0 100644 --- a/src/app/modules/application/forms/study-form.component.ts +++ b/src/app/modules/application/forms/study-form.component.ts @@ -66,12 +66,6 @@ export class StudyFormComponent implements OnInit { private readonly joyrideService: JoyrideService, private route: ActivatedRoute, public dialog: MatDialog) { - - /* this.level = 1; - this.model_type = ''; - this.model_key = ''; - this.mode = ''; - this.parent_id = ''; */ this.route.queryParams.subscribe( params => { this.level = params['level']; @@ -86,17 +80,31 @@ export class StudyFormComponent implements OnInit { } ); + console.warn(this.parent_id) + console.warn(this.mode) + console.warn(this.model_key) + console.warn(this.model_type) + console.warn(this.inline ) + console.warn(this.onlyTemplate) + console.warn(this.role) if (this.model_key != "") { - //console.log(this.model_key) + console.log(this.model_key) this.get_model_by_key(); } - //console.log(this.mode) - console.warn(this.role) + + //console.log(this.mode) } - ngOnInit() { + async ngOnInit() { + console.warn(this.parent_id) + console.warn(this.mode) + console.warn(this.model_key) + console.warn(this.model_type) + console.warn(this.inline ) + console.warn(this.onlyTemplate) + console.warn(this.role) ///const id = this.activatedRoute.snapshot.params.id; ////console.log(this.mode) @@ -106,7 +114,9 @@ export class StudyFormComponent implements OnInit { // if (currentUser['tutoriel_checked'] === false){ // this.onClickTour() // } - this.onClickTour() + let sites=await this.globalService.get_by_key("Experimental_sites", "experimental_site").toPromise() + console.log(sites) + //this.onClickTour() }; onClickTour(help_mode: boolean = false) { @@ -387,7 +397,7 @@ export class StudyFormComponent implements OnInit { } */ } - ////console.log(this.modelForm.value) + console.log(this.modelForm.value) } }); }; @@ -552,7 +562,7 @@ export class StudyFormComponent implements OnInit { } else { this.globalService.get_by_key(this.model_key, this.model_type).toPromise().then(data => { - //console.log(data) + console.log(data) this.model_to_edit = data; this.modelForm.patchValue(this.model_to_edit); this.startfilling = true; diff --git a/src/app/modules/application/map/map.component.ts b/src/app/modules/application/map/map.component.ts index 080c937a..6a316ac3 100644 --- a/src/app/modules/application/map/map.component.ts +++ b/src/app/modules/application/map/map.component.ts @@ -24,15 +24,10 @@ export class MapComponent implements OnInit { private geoCoder; public searchElementRef: ElementRef; - constructor( private mapsAPILoader: MapsAPILoader, private ngZone: NgZone ) { } - - - - ngOnInit() { this.mapsAPILoader.load().then(() => { @@ -41,7 +36,6 @@ export class MapComponent implements OnInit { }); let map: google.maps.Map; const center: google.maps.LatLngLiteral = {lat: 30, lng: -110}; - } private setCurrentLocation() { @@ -54,7 +48,6 @@ export class MapComponent implements OnInit { }); } } - getAddress(latitude, longitude) { diff --git a/src/app/modules/application/material-forms/material-form.component.html b/src/app/modules/application/material-forms/material-form.component.html index 7533f475..14203a96 100644 --- a/src/app/modules/application/material-forms/material-form.component.html +++ b/src/app/modules/application/material-forms/material-form.component.html @@ -64,11 +64,11 @@
    Data submission

    {{ model_type[0].toUpperCase() + model_type.slice(1).replace("_"," ")}}

    -

    {{model.Definition}}

    +

    Definition: The biological material being studied (e.g. plants grown from a certain bag or seed, or plants grown in a particular field). The original source of that material (e.g., the seeds or the original plant cloned) is called the material source, which, when held by a material repository, should have its stock identified.

    Material Lot Name grouped by taxon group and Material accession name

    -

    Pick and choose material from INRAE Collection mmaterial sources

    +

    Pick and choose germplasm(s) from multiple holding institution material sources

    diff --git a/src/app/modules/application/projects/pages/data-file-page.component.html b/src/app/modules/application/projects/pages/data-file-page.component.html index 08b93ee9..952cd0e4 100644 --- a/src/app/modules/application/projects/pages/data-file-page.component.html +++ b/src/app/modules/application/projects/pages/data-file-page.component.html @@ -27,48 +27,28 @@

    - +
    +

    Usage

    +

    + Each column in your datafile needs to be linked as a MIAPPE component if possible. + Each datafile needs to have a column called Study name. + If you started from empty files, the study name has already be associated but not mapped as a real MIAPPE component. + To do this, you need to extract value in your column and create corresponding studies +

    +
    -
    - - - - + @@ -79,34 +59,6 @@
    {{column}}
    -
    - +
    - {{get_column_extracted(column).associated_component_field}} + {{get_column_extracted(column).associated_component_field}} Not defined
    -
    - - - - - - \ No newline at end of file +
    \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/data-file-page.component.ts b/src/app/modules/application/projects/pages/data-file-page.component.ts index c26df8a1..939a161c 100644 --- a/src/app/modules/application/projects/pages/data-file-page.component.ts +++ b/src/app/modules/application/projects/pages/data-file-page.component.ts @@ -75,6 +75,7 @@ export class DataFilePageComponent implements AfterViewInit, OnDestroy, OnInit { //this.globalService.start() this.myEventSubscription = this.globalService.get_data_file(this.model_key).subscribe( data => { + console.log(data) this.data_file = Object.assign(data) this.tableData = this.data_file.Data this.columns = [] @@ -152,7 +153,7 @@ export class DataFilePageComponent implements AfterViewInit, OnDestroy, OnInit { data_model.headers.splice(index, 1) } } - let unique_field = ['Study unique ID', 'Event accession number', 'Experimental Factor accession number', "Environment parameter accession number"] + let unique_field = ['Study Name', 'Event accession number', 'Experimental Factor accession number', "Environment parameter accession number"] // check if associated_component_field is in [Study unique ID, Event accession number, Experimental Factor accession number] // clean all childs // if Study id column, clean all others associate headers @@ -287,10 +288,10 @@ export class DataFilePageComponent implements AfterViewInit, OnDestroy, OnInit { } else { if (ass_headers.associated_linda_id.length == 0) { - return "LightSeaGreen" + return "#c0e4e3" } else { - return "DarkCyan" + return "#1b7170" } } diff --git a/src/app/modules/application/projects/pages/data-files-page.component.html b/src/app/modules/application/projects/pages/data-files-page.component.html index 477f8266..d7c31993 100644 --- a/src/app/modules/application/projects/pages/data-files-page.component.html +++ b/src/app/modules/application/projects/pages/data-files-page.component.html @@ -1,6 +1,7 @@
    - + +
    @@ -10,31 +11,22 @@ [matMenuTriggerFor]="HelpSubMenu">Help - - - \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/data-files-page.component.ts b/src/app/modules/application/projects/pages/data-files-page.component.ts index 399a8049..8dd30b2d 100644 --- a/src/app/modules/application/projects/pages/data-files-page.component.ts +++ b/src/app/modules/application/projects/pages/data-files-page.component.ts @@ -63,7 +63,7 @@ export class DataFilesPageComponent implements OnInit { this.collection = params['collection']; this.parent_id = params['parent_id']; this.model_key = params['model_key']; - this.role == params['role']; + this.role = params['role']; this.group_key = params['group_key']; @@ -185,7 +185,7 @@ export class DataFilesPageComponent implements OnInit { // dependding on parent id, remove either in investigations_edge, studies_edeg } onAdd(mode:string) { - const dialogRef = this.dialog.open(FilesLoaderComponent, {disableClose: true, width: '1000px', data: { parent_id: this.parent_id, mode:mode } }); + const dialogRef = this.dialog.open(FilesLoaderComponent, {disableClose: true, width: '1000px', data: { parent_id: this.parent_id, mode:mode,group_key:this.group_key } }); dialogRef.afterClosed().subscribe(result => { if (result) { if (result.event == 'Confirmed') { diff --git a/src/app/modules/application/projects/pages/environment-variables-page.component.html b/src/app/modules/application/projects/pages/environment-variables-page.component.html index 02d7e790..08800835 100644 --- a/src/app/modules/application/projects/pages/environment-variables-page.component.html +++ b/src/app/modules/application/projects/pages/environment-variables-page.component.html @@ -1,6 +1,6 @@
    - +
    @@ -22,11 +22,11 @@ [style.top]="contextMenuPosition.y" [matMenuTriggerFor]="contextMenu">
    - + - + @@ -56,8 +56,10 @@ - + +
    diff --git a/src/app/modules/application/projects/pages/environment-variables-page.component.ts b/src/app/modules/application/projects/pages/environment-variables-page.component.ts index f68220df..2e0781c5 100644 --- a/src/app/modules/application/projects/pages/environment-variables-page.component.ts +++ b/src/app/modules/application/projects/pages/environment-variables-page.component.ts @@ -10,6 +10,7 @@ import { FormGenericComponent } from 'src/app/modules/application/dialogs/form-g import { MatDialog } from '@angular/material/dialog'; import { UserInterface } from 'src/app/models/linda/person'; import { EnvironmentInterface, Environment } from 'src/app/models/linda/environment'; +import { TemplateSelectionComponent } from '../../dialogs/template-selection.component'; @Component({ selector: 'app-environment-variables-page', @@ -131,7 +132,7 @@ export class EnvironmentVariablesPageComponent implements OnInit { } }); } - add() { + add(template:boolean=false) { let user = JSON.parse(localStorage.getItem('currentUser')); let new_step = 0 if (!this.currentUser.tutoriel_done) { @@ -147,22 +148,46 @@ export class EnvironmentVariablesPageComponent implements OnInit { //let exp_factor: ExperimentalFactor = new ExperimentalFactor() console.log(this.model_type) console.log(this.parent_id) - const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); - formDialogRef.afterClosed().subscribe((result) => { - if (result) { - if (result.event == 'Confirmed') { + if (template){ + const dialogRef = this.dialog.open(TemplateSelectionComponent, {disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'environment', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { console.log(result) - let environment: Environment= result["formData"]["form"] - this.globalService.add(environment, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( - data => { - if (data["success"]) { - console.log(data) - this.ngOnInit() + result = Object.keys(result).filter(key => !key.startsWith("_")).reduce((obj, key) => {obj[key] = result[key];return obj;}, {}); + let exp_factor: Environment= result + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + + this.reloadComponent() + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + } + else { this.alertService.error("this form contains errors! " + data["message"]);} } - });; + ); + } - } - }); + }); + } + else{ + const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let environment: Environment= result["formData"]["form"] + this.globalService.add(environment, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + this.ngOnInit() + } + });; + } + } + }); + } } diff --git a/src/app/modules/application/projects/pages/events-page.component.html b/src/app/modules/application/projects/pages/events-page.component.html index d174b9c2..4eb3a62d 100644 --- a/src/app/modules/application/projects/pages/events-page.component.html +++ b/src/app/modules/application/projects/pages/events-page.component.html @@ -1,6 +1,6 @@
    - +
    @@ -26,7 +26,7 @@ - + diff --git a/src/app/modules/application/projects/pages/events-page.component.ts b/src/app/modules/application/projects/pages/events-page.component.ts index 10ba679e..80396bb4 100644 --- a/src/app/modules/application/projects/pages/events-page.component.ts +++ b/src/app/modules/application/projects/pages/events-page.component.ts @@ -11,6 +11,7 @@ import { first } from 'rxjs/operators'; import { FormGenericComponent } from 'src/app/modules/application/dialogs/form-generic.component' import { MatDialog } from '@angular/material/dialog'; import { UserInterface } from 'src/app/models/linda/person'; +import { TemplateSelectionComponent } from '../../dialogs/template-selection.component'; @Component({ selector: 'app-events-page', @@ -129,7 +130,7 @@ export class EventsPageComponent implements OnInit, AfterViewInit { this.router.onSameUrlNavigation = 'reload'; this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "events", role: this.role, group_key: this.group_key } }); } - add() { + add(template:boolean=false) { let user = JSON.parse(localStorage.getItem('currentUser')); let new_step = 0 if (!this.currentUser.tutoriel_done) { @@ -142,22 +143,45 @@ export class EventsPageComponent implements OnInit, AfterViewInit { this.alertService.error("You are not in the right form as requested by the tutorial") } } - const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); - formDialogRef.afterClosed().subscribe((result) => { - if (result) { - if (result.event == 'Confirmed') { - //console.log(result) - let event: LindaEvent= result["formData"]["form"] - this.globalService.add(event, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( - data => { - if (data["success"]) { - //console.log(data) - this.ngOnInit() + if (template){ + const dialogRef = this.dialog.open(TemplateSelectionComponent, {disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'event', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) + result = Object.keys(result).filter(key => !key.startsWith("_")).reduce((obj, key) => {obj[key] = result[key];return obj;}, {}); + let exp_factor: LindaEvent= result + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + + this.reloadComponent() + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + } + else { this.alertService.error("this form contains errors! " + data["message"]);} } - });; + ); } - } - }); + }); + } + else{ + const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + //console.log(result) + let event: LindaEvent= result["formData"]["form"] + this.globalService.add(event, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + //console.log(data) + this.ngOnInit() + } + });; + } + } + }); + } } diff --git a/src/app/modules/application/projects/pages/experimental-design-page.component.html b/src/app/modules/application/projects/pages/experimental-design-page.component.html index d8231d5c..b9124234 100644 --- a/src/app/modules/application/projects/pages/experimental-design-page.component.html +++ b/src/app/modules/application/projects/pages/experimental-design-page.component.html @@ -1,208 +1,287 @@
    - - + + -
    -
    -

    Describe your experimental design

    - +
    + +

    Build your experimental design

    +
    - +
    +
    - - - -

    Experimental design representation

    -
    - - - - - - - - -
    -
    - + + + + + Block design settings + + + +

    Experimental design representation

    +
    + + + + + + + + +
    +
    +
    +
    + + - - - {{'Block ' + bd['Block number'].value}} + + + {{'Block ' + bd['Block number'].value}} - - - - - -

    Select Factor repartition

    - -

    Completely randomized design

    -

    - The simplest, least restrictive experimental design is the Completely Randomized Design (CRD). In a CRD, the treatments are assigned - to the plots without restriction. That is, with the CRD, every plot is equally likely to be assigned in any treatment -

    -

    Randomized complete block design

    -

    - The Randomized complete Block Design (RBD) is the design use most often in agricultural research. In a RBD, the plots (experimental units) are first classified into groups, - or blocks, of plots within blocks in such a way that each treatment occurs the same number of time, usually once within each block. - The object is to make the variation from plot to plot as small as possible within the blocks while maximizing the variation among blocks -

    -

    Latin Square Design

    -

    - In the latin square, the number of plots is the square of the number of treatments. For practical purposes, its use is restricted to trials with more than four - but fewer than 10 treatments. -

    -
    - - - {{available_design}} - - -

    block design representation (rows and columns)

    -
    - - - - - - - - - - -
    - + +
    +
    + + + + + + Plot design settings + + + + +

    block design representation (rows and columns)

    +
    + + + + + + + + + + +
    +
    +
    + + +
    - - Plot Design in block {{get_design.Blocking.value[block_index]['Block number'].value}} + + Plot Design in block + {{get_design.Blocking.value[block_index]['Block number'].value}} + +
    + +
    + + + {{factor}} + + + +
    - - - {{get_associated_material_source(pd)}} - - - -

    You have {{get_design.Blocking.value[block_index]['Plot design'].value.length}} plots defined in block {{get_design.Blocking.value[block_index]['Block number'].value}} -

    -
    +

    + You have {{get_design.Blocking.value[block_index]['Plot design'].value.length}} + plots defined in block + {{get_design.Blocking.value[block_index]['Block number'].value}} +

    + + + {{get_associated_material_source(pd)}} + + + + +
    - + -

    Experimental design table and observationsassociation

    - - + - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - -
    Block number Blocks per trialObservation Unit external idAssociated samplesAssociated observations
    - - - {{experimental_design_block['Block number'].value}}{{experimental_design_block['Blocks per trial'].value}}{{get_observation_units(get_design)}}{{get_samples(get_design)}}
    - - - + + + + + + +
    + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Plot numberRow numberColumn numberAssociated material source# biological material replicate numberObservation unit uuid
    + + + {{plotInfo['Plot number'].value}}{{rowInfo['Row number'].value}}{{plotInfo['Column number'].value}}{{get_associated_material_source(plotInfo)}}{{get_associated_biological_material(plotInfo)}}{{get_replicate_number(plotInfo)}}{{get_observation_uuid(plotInfo)}}
    + + + + + + + + + + + + + + + + + + + + + +
    Collection dateSamples
    + + + {{date}}{{get_associated_sample(plotInfo, date)}} +
    + + + + + + + + + + + + + + + +
    Associated sample ID + Sample descriptionBiological material UUID +
    {{comp['Sample ID']}} + {{comp['Sample description']}} + {{comp['bmUUID']}}
    +
    + + + + + + + + + + + + + + + + + + + +
    Observation dateObservations
    + + + {{obsdate}}{{get_associated_observation(plotInfo, obsdate)}} +
    + + + + + + + + + + + + + + + + + + + + + + Trait + + + + +
    Associated observation + IDObservation descriptionObservation traitObservation measurementObservation unitObs UUID
    {{comp['Observation ID']}} + {{comp['Observation description']}}{{comp['Observed trait']}}{{comp['Observed variable measure']}}{{comp['Observed variable unit']}}{{comp['obsUUID']}}
    +
    +
    +
    - - + - - + \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/experimental-design-page.component.ts b/src/app/modules/application/projects/pages/experimental-design-page.component.ts index 008406cf..d6b62975 100644 --- a/src/app/modules/application/projects/pages/experimental-design-page.component.ts +++ b/src/app/modules/application/projects/pages/experimental-design-page.component.ts @@ -2,27 +2,30 @@ import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, ViewChild, A import { GlobalService, AlertService, OntologiesService } from '../../../../services'; import { Router, ActivatedRoute } from '@angular/router'; import { MatMenuTrigger } from '@angular/material/menu'; -import { MatPaginator, PageEvent} from '@angular/material/paginator'; -import { MatSort} from '@angular/material/sort' +import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort' import { first } from 'rxjs/operators'; import structuredClone from '@ungap/structured-clone'; import * as uuid from 'uuid'; -import { +import {ChipListComponent} from 'src/app/components/chip-list/chip-list.component' + +import { ExperimentalDesign, BlockDesign, Replication, PlotDesign, RowDesign, BlockDesignInterface, - CompleteBlockDesign, - IncompleteBlockDesign, + CompleteBlockDesign, + IncompleteBlockDesign, ExperimentalDesignInterface, CompleteBlockDesignInterface, - IncompleteBlockDesignInterface, - PlotDesignInterface} from 'src/app/models/linda/experimental-design'; + IncompleteBlockDesignInterface, + PlotDesignInterface +} from 'src/app/models/linda/experimental-design'; import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms'; -import { MatTableDataSource} from '@angular/material/table'; +import { MatTableDataSource } from '@angular/material/table'; import { ConfirmationComponent } from '../../dialogs/confirmation.component' import { MatDialog } from '@angular/material/dialog'; import { UserInterface } from 'src/app/models/linda/person'; @@ -32,16 +35,31 @@ import { AssociateObservationUnit } from '../../dialogs/associate-observation-un import { BiologicalMaterialFullInterface } from 'src/app/models/linda/biological-material'; import { timeStamp } from 'console'; import { SampleSelectionComponent } from '../../dialogs/sample-selection.component'; +import { AssociateObservedVariable } from '../../dialogs/associate-observed-variable.component'; +import { PlotOverviewComponent } from '../../dialogs/plot-overview.component'; +import { AssociateExperimentalFactorComponent } from '../../dialogs/associate-experimental-factor.component'; +import { ExperimentalFactor } from 'src/app/models/linda/experimental_factor'; +import { indexOf } from 'lodash'; +import { AssociateObservationsMeasurementComponent } from '../../dialogs/associate-observations-measurement.component'; + +export interface subComponent{ + 'Associated biological material':[] + 'Associated sample':[] +} + +export interface ExperimentalFactorNames { + name: string; + } @Component({ - selector: 'app-experimental-design-page', - templateUrl: './experimental-design-page.component.html', - styleUrls: ['./experimental-design-page.component.css'] + selector: 'app-experimental-design-page', + templateUrl: './experimental-design-page.component.html', + styleUrls: ['./experimental-design-page.component.css'] }) export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, AfterViewInit { // Input args @Input('level') level: number; - @Input('parent_id') parent_id:string; + @Input('parent_id') parent_id: string; @Input('model_id') model_id: string; @Input('model_type') model_type: string; @Input('model_key') model_key: string; @@ -54,50 +72,73 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After @Output() notify: EventEmitter<{}> = new EventEmitter<{}>(); BlockDesignForm = new FormGroup({ - totalBlockControl : new FormControl(''), - totalRowPerBlockControl : new FormControl(''), - totalColumnPerBlockControl : new FormControl(''), - totalRowPerPlotControl : new FormControl(''), - totalBlockPerRowControl : new FormControl('') + totalBlockControl: new FormControl(''), + totalRowPerBlockControl: new FormControl(''), + totalColumnPerBlockControl: new FormControl(''), + totalRowPerPlotControl: new FormControl(''), + totalBlockPerRowControl: new FormControl('') }) - - - - - + plot_sub_components:subComponent[] = [] bm_data = [] //experimental_design_blocks:BlockDesign[]=[] - design_types=["CompleteBlockDesign","IncompleteBlockDesign"] - private design:ExperimentalDesign; - private block_design_type:string="" - private total_block_number:number=0 - private total_column_per_block:number=0 - private total_row_per_block:number=0 - private total_row_per_plot:number=0 - private total_block_per_row:number=0 + design_types = ["CompleteBlockDesign", "IncompleteBlockDesign"] + private design: ExperimentalDesign; + private block_design_type: string = "" + private total_block_number: number = 0 + private total_column_per_block: number = 0 + private total_row_per_block: number = 0 + private total_row_per_plot: number = 0 + private total_block_per_row: number = 0 private dataSource: MatTableDataSource; private displayedColumns: string[] = ['Blocks per trial', 'edit']; - private study_id:string - private experimental_designs:ExperimentalDesignInterface[]=[] - private currentUser:UserInterface - public designLoaded:boolean=false - public blockDesignLoaded:boolean=false - public biologicalMaterialLoaded:boolean=false - public observationUnitLoaded:boolean=false - public complete_block_design_type:CompleteBlockDesign; - public incomplete_block_design_type:IncompleteBlockDesign; - public available_designs:string[] - public block_design_subtype:string - public block_index:number=0 - public plot_index:number=0 - public material_id:string="" + private study_id: string + private experimental_designs: ExperimentalDesignInterface[] = [] + private currentUser: UserInterface + public designLoaded: boolean = false + public blockDesignLoaded: boolean = false + public biologicalMaterialLoaded: boolean = false + public observationUnitLoaded: boolean = false + public observationLoaded:boolean=false + public sampleLoaded: boolean = false; + public complete_block_design_type: CompleteBlockDesign; + public incomplete_block_design_type: IncompleteBlockDesign; + public available_designs: string[] + public block_design_subtype: string + public block_index: number = 0 + public plot_index: number = 0 + public material_id: string = "" + public selected_factor_id:string="" + public selected_factor_values:string[]=[] + factors_col = [ + 'LightCoral', + 'lightblue', + 'Silver', + 'lightgreen', + 'Gainsboro', + 'LightPink', + 'Orange', + 'DarkKhaki', + 'AntiqueWhite', + 'CornflowerBlue', + 'DarkMagenta', + 'LavenderBlush', + 'Turquoise' + ] sample_data = [] + panel_disabled: boolean = false + panel_expanded: boolean = false ///// TESST PART - hideme = []; - secondhideme = []; - Index: any; - SecondIndex: any; + hideme = []; + secondhideme = []; + thirdhideme = []; + obsthirdhideme = []; + Index: any; + SecondIndex: any; + ThirdIndex: any; + obsThirdIndex: any; + experimentalFactorNames: ExperimentalFactorNames[]=[]; + /* products = []; countryCode: any; currencySymbol:any; @@ -113,32 +154,32 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After private router: Router, private alertService: AlertService, private route: ActivatedRoute, - private formBuilder:FormBuilder, + private formBuilder: FormBuilder, private _cdr: ChangeDetectorRef, - public dialog: MatDialog){ - this.block_index=0 - this.route.queryParams.subscribe( - params => { - this.level = params['level']; - this.model_type = params['model_type']; - this.model_key = params['model_key']; - this.model_id = params['model_id']; - this.mode = params['mode']; - this.parent_id = params['parent_id'] - this.group_key = params['group_key'] - this.role = params['role'] - this.grand_parent_id = params['grand_parent_id'] - this.activeTab=params['activeTab'] - } - ); - if (this.model_key!==""){ - this.get_design_by_key() - } - - } - async ngOnInit(){ - this.activeTab="exp_design_info" - this.block_design_type="" + public dialog: MatDialog) { + this.block_index = 0 + this.route.queryParams.subscribe( + params => { + this.level = params['level']; + this.model_type = params['model_type']; + this.model_key = params['model_key']; + this.model_id = params['model_id']; + this.mode = params['mode']; + this.parent_id = params['parent_id'] + this.group_key = params['group_key'] + this.role = params['role'] + this.grand_parent_id = params['grand_parent_id'] + this.activeTab = params['activeTab'] + } + ); + if (this.model_key !== "") { + this.get_design_by_key() + } + + } + async ngOnInit() { + this.activeTab = "exp_design_info" + this.block_design_type = "" console.warn(this.level) console.warn(this.model_type) console.warn(this.model_key) @@ -150,86 +191,124 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After console.warn(this.grand_parent_id) console.warn(this.activeTab) //this._cdr.detectChanges() - this.design=new ExperimentalDesign() - this.currentUser = JSON.parse(localStorage.getItem('currentUser')); - + this.design = new ExperimentalDesign() + this.currentUser = JSON.parse(localStorage.getItem('currentUser')); + } - ngAfterViewInit(){ + ngOnDestroy(): void { + //Called once, before the instance is destroyed. + //Add 'implements OnDestroy' to the class. + } + ngAfterViewInit() { /* this.route.queryParams.subscribe(params => { this.activeTab = params['activeTab']; this._cdr.detectChanges() }); */ } - get_design_by_key(){ + get_collection_dates(blocknum:number,plotnum:number){ + return Array.from(new Set(this.design.Blocking.value.filter(block=> block['Block number'].value===blocknum)[0]['Plot design'].value.filter(plot=>plot['Plot number'].value===plotnum)[0].get_samples().map(sample=>sample['Collection date']))) + } + get_observation_dates(blocknum:number,plotnum:number){ + return Array.from(new Set(this.design.Blocking.value.filter(block=> block['Block number'].value===blocknum)[0]['Plot design'].value.filter(plot=>plot['Plot number'].value===plotnum)[0].get_observations().map(observation=>observation['Observation date']))) + } + get_sample_plot_sub_components(blocknum:number, plotnum:number, date:Date){ + return this.design.Blocking.value.filter(block=> block['Block number'].value===blocknum)[0]['Plot design'].value.filter(plot=>plot['Plot number'].value===plotnum)[0].get_samples().filter(sample=>sample['Collection date']===date) + } + get_observation_plot_sub_components(blocknum:number, plotnum:number, date:Date){ + return this.design.Blocking.value.filter(block=> block['Block number'].value===blocknum)[0]['Plot design'].value.filter(plot=>plot['Plot number'].value===plotnum)[0].get_observations().filter(observation=>observation['Observation date']===date) + } + + get_design_by_key() { this.globalService.get_experimental_design_by_key(this.model_key).toPromise().then(async res => { - if (res.success){ - let data=res.data + if (res.success) { + let data = res.data console.log(data['Blocking'].value[0]['Plot design'].value) - - let tmp_column_num=[] - data['Blocking'].value[0]['Plot design'].value.filter(val=>tmp_column_num.push(val['Column number'].value)) - let tmp_row_num=[] - let RowPerPlot=0 + + let tmp_column_num = [] + data['Blocking'].value[0]['Plot design'].value.filter(val => tmp_column_num.push(val['Column number'].value)) + let tmp_row_num = [] + let RowPerPlot = 0 //data['Blocking'].value[0]['Plot design'].value[0]['Row design'].value.filter(val=>tmp_row_num.push(val['Row number'].value)) //let plot_designs=data['Blocking'].value[0]['Plot design'].value - data['Blocking'].value[0]['Plot design'].value.forEach(val=>{ - val['Row design'].value.forEach(val2=>{ + data['Blocking'].value[0]['Plot design'].value.forEach(val => { + val['Row design'].value.forEach(val2 => { tmp_row_num.push(val2['Row number'].value) - RowPerPlot=val2['Row per plot'].value + RowPerPlot = val2['Row per plot'].value }) - - }) - if (data['Blocking'].value[0]['Complete Block Design'].value.length>0){ - this.block_design_type='CompleteBlockDesign' - this.available_designs=Object.keys(data['Blocking'].value[0]['Complete Block Design'].value[0]) - this.available_designs.forEach(available_design=>{ - if (data['Blocking'].value[0]['Complete Block Design'].value[0][available_design].value===true){ - this.block_design_subtype=available_design + + }) + if (data['Blocking'].value[0]['Complete Block Design'].value.length > 0) { + this.block_design_type = 'CompleteBlockDesign' + this.available_designs = Object.keys(data['Blocking'].value[0]['Complete Block Design'].value[0]) + this.available_designs.forEach(available_design => { + if (data['Blocking'].value[0]['Complete Block Design'].value[0][available_design].value === true) { + this.block_design_subtype = available_design } }) console.log(Object.keys(data['Blocking'].value[0]['Complete Block Design'].value[0] as CompleteBlockDesign)) - this.complete_block_design_type=data['Blocking'].value[0]['Complete Block Design'].value[0] as CompleteBlockDesign + this.complete_block_design_type = data['Blocking'].value[0]['Complete Block Design'].value[0] as CompleteBlockDesign } - else{ - this.block_design_type='IncompleteBlockDesign' - this.available_designs=Object.keys(data['Blocking'].value[0]['Incomplete Block Design'].value[0] as IncompleteBlockDesign) - this.available_designs.forEach(available_design=>{ - if (data['Blocking'].value[0]['Incomplete Block Design'].value[0][available_design].value===true){ - this.block_design_subtype=available_design + else { + this.block_design_type = 'IncompleteBlockDesign' + this.available_designs = Object.keys(data['Blocking'].value[0]['Incomplete Block Design'].value[0] as IncompleteBlockDesign) + this.available_designs.forEach(available_design => { + if (data['Blocking'].value[0]['Incomplete Block Design'].value[0][available_design].value === true) { + this.block_design_subtype = available_design } }) - - this.incomplete_block_design_type=data['Blocking'].value[0]['Incomplete Block Design'].value[0] as IncompleteBlockDesign + + this.incomplete_block_design_type = data['Blocking'].value[0]['Incomplete Block Design'].value[0] as IncompleteBlockDesign } - - - let column_num= Array.from(new Set(tmp_column_num)) - let row_num= Array.from(new Set(tmp_row_num)) - this.design=new ExperimentalDesign() - var replication:Replication=new Replication() + + + let column_num = Array.from(new Set(tmp_column_num)) + let row_num = Array.from(new Set(tmp_row_num)) + this.design = new ExperimentalDesign() + var replication: Replication = new Replication() Object.assign(replication, data.Replication.value) this.design.set_replication(replication) - - if (data['Associated observation units'].value!==null){ + if (data['Associated sample ID'].value!==null){ + this.design.set_sample_id(data['Associated sample ID'].value) + } + if (data['Associated observed variable IDs'].value.length > 0){ + this.design.set_observed_variable_id(data['Associated observed variable IDs'].value) + } + if (data['Associated experimental factor IDs'].value.length > 0){ + this.design.set_experimental_factor_id(data['Associated experimental factor IDs'].value) + data['Associated experimental factor IDs'].value.forEach(factor=>{ + this.experimentalFactorNames.push({ name: factor}) + }) + this.selected_factor_id=data['Associated experimental factor IDs'].value[0] + + + } + if (data['Associated observations'].value.length > 0){ + this.design.set_associated_observations(data['Associated observations'].value) + } + if (data['Associated sample'].value.length > 0) { + this.design.set_associated_samples(data['Associated sample'].value) + this.sampleLoaded = true + } + if (data['Associated observation units'].value !== null) { this.design.set_observation_unit_id(data['Associated observation units'].value) - const observation_unit_childs_data=await this.globalService.get_all_observation_unit_childs_by_type(data['Associated observation units'].value.split("/")[1], 'biological_materials').toPromise()//.then(observation_unit_childs_data => { + const observation_unit_childs_data = await this.globalService.get_all_observation_unit_childs_by_type(data['Associated observation units'].value.split("/")[1], 'biological_materials').toPromise()//.then(observation_unit_childs_data => { console.log(observation_unit_childs_data) //get all biological materials - if (observation_unit_childs_data.length>0){ - let data=[] - data=observation_unit_childs_data + if (observation_unit_childs_data.length > 0) { + let data = [] + data = observation_unit_childs_data var child_id: string = data[0]['e']['_to'] var tmp_bm: [] = data[0]['e']['biological_materials'] this.bm_data = this.bm_data.concat(tmp_bm) } - - - + + + } - + //this.design=ExperimentalDesign.create_design(data) console.log(this.design) ///Object.assign(this.design, data); @@ -237,30 +316,40 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After //this.design=JSON.parse(JSON.stringify(data)) //this.design=structuredClone(data) //this.design=JSON.parse(JSON.stringify(data)); - data.Blocking.value.forEach(block=>{ - let new_block_design=new BlockDesign(block['Block number'].value,data.Blocking.value.length) - if (block['Complete Block Design'].value.length>0){ + data.Blocking.value.forEach(block => { + let new_block_design = new BlockDesign(block['Block number'].value, data.Blocking.value.length) + if (block['Complete Block Design'].value.length > 0) { new_block_design.add_complete_block_design(this.complete_block_design_type) } - else{ + else { new_block_design.add_incomplete_block_design(this.incomplete_block_design_type) } //new_block_design=BlockDesign.create_block_design(block) - block['Plot design'].value.forEach(plot_design=>{ - let new_plot_design=new PlotDesign(plot_design['Column number'].value,plot_design['Plot number'].value,plot_design['Associate_material_source'].value, plot_design['Associated_biological_material'].value, plot_design['Replicate number'].value) + block['Plot design'].value.forEach(plot_design => { + if (!this.selected_factor_values.includes(plot_design.Associated_factor_values.value[0])){ + this.selected_factor_values.push(plot_design.Associated_factor_values.value[0]) + } + let new_plot_design = new PlotDesign(plot_design['Column number'].value, plot_design['Plot number'].value, plot_design['Associate_material_source'].value, plot_design['Associated_biological_material'].value,plot_design.Associated_factor_values.value, plot_design['Replicate number'].value) //new_plot_design=PlotDesign.create_plot_design(plot_design) //Object.assign(new_plot_design, plot_design) - if (plot_design['Observation uuid'].value!==null){ - new_plot_design.set_observation_uuid(plot_design['Observation uuid'].value) + if (plot_design['Observation unit uuid'].value !== null) { + new_plot_design.set_observation_uuid(plot_design['Observation unit uuid'].value) + } + if (plot_design['Associated samples'].value !== null) { + new_plot_design.set_samples(plot_design['Associated samples'].value) + } + if (plot_design['Associated plot observations'].value !== null) { + new_plot_design.set_observations(plot_design['Associated plot observations'].value) + this.observationLoaded=true } - plot_design['Row design'].value.forEach(row_design=>{ + plot_design['Row design'].value.forEach(row_design => { //let new_row_design=new RowDesign() - let new_row_design=RowDesign.create_row_design(row_design) + let new_row_design = RowDesign.create_row_design(row_design) //Object.assign(new_row_design, row_design) - this.total_row_per_plot=row_design['Row per plot'].value + this.total_row_per_plot = row_design['Row per plot'].value new_plot_design['Row design'].value.push(new_row_design) //Object.assign(new_row_design, row_design) - }) + }) new_block_design['Plot design'].value.push(new_plot_design) //Object.assign(new_plot_design, plot_design) }) @@ -268,15 +357,16 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After //Object.assign(new_block_design, block) }) //replication.set_replicate_number(data.Replication.value.get_replicate_number()) - this.total_block_number=data.Blocking.value.length - this.total_column_per_block=column_num.length - this.total_row_per_block=row_num.length - let total_entries=this.total_block_number*this.total_column_per_block*(this.total_row_per_block/this.total_row_per_plot) + this.total_block_number = data.Blocking.value.length + this.total_column_per_block = column_num.length + this.total_row_per_block = row_num.length + let total_entries = this.total_block_number * this.total_column_per_block * (this.total_row_per_block / this.total_row_per_plot) this.design.set_number_of_entries(total_entries) - if (data["Associated biological Materials"].value!==null){ - this.material_id=data["Associated biological Materials"].value + if (data["Associated biological Materials"].value !== null) { + this.material_id = data["Associated biological Materials"].value this.design.set_biological_material_id(data["Associated biological Materials"].value) } + this.design.set_block_per_row(data['Block per Row'].value) //this.design=data //this.design=data as ExperimentalDesign //console.log(Object.keys(this.design).filter((key) => typeof this.design[key] === 'function').map((key) => this.design[key])) @@ -289,314 +379,797 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After this.totalRowPerPlotControl.setValue(RowPerPlot) this.totalRowPerBlockControl.patchValue(row_num.length) this.totalRowPerBlockControl.setValue(row_num.length) - this.totalBlockPerRowControl.patchValue(4) - this.totalBlockPerRowControl.setValue(4) + console.log(data['Block per Row'].value) + this.totalBlockPerRowControl.patchValue(this.get_design.get_block_per_row()) + this.totalBlockPerRowControl.setValue(this.get_design.get_block_per_row()) console.log(this.design) - this.designLoaded=true - this.blockDesignLoaded=true - if (data['Blocking'].value[0]['Plot design'].value[0]['Associate_material_source'].value!==null){ - this.biologicalMaterialLoaded=true + this.designLoaded = true + this.blockDesignLoaded = true + if (data['Blocking'].value[0]['Plot design'].value[0]['Associate_material_source'].value !== null) { + this.biologicalMaterialLoaded = true } - if (data['Associated observation units'].value!==null){ - this.observationUnitLoaded=true + if (data['Associated observation units'].value !== null) { + this.observationUnitLoaded = true } + this.get_collection_dates(1,1) } }); - + } - onDesignTypeChange(value:string){ - this.block_design_type=value + onDesignTypeChange(value: string) { + this.block_design_type = value console.log(this.block_design_type) - this.available_designs=[] - if (this.block_design_type==="CompleteBlockDesign"){ - this.complete_block_design_type=new CompleteBlockDesign(false,false,false) + this.available_designs = [] + if (this.block_design_type === "CompleteBlockDesign") { + this.complete_block_design_type = new CompleteBlockDesign(false, false, false) console.log(this.complete_block_design_type) - this.available_designs=Object.keys(this.complete_block_design_type) + this.available_designs = Object.keys(this.complete_block_design_type) + this.available_designs.push } - else{ - this.incomplete_block_design_type=new IncompleteBlockDesign(false,false) - this.available_designs=Object.keys(this.incomplete_block_design_type) + else { + this.incomplete_block_design_type = new IncompleteBlockDesign(false, false) + this.available_designs = Object.keys(this.incomplete_block_design_type) console.log(this.incomplete_block_design_type) } - console.log(this.available_designs) + console.log(this.available_designs) } - onExtractDesign(){ - this.designLoaded=false - this.blockDesignLoaded=false + onExtractDesign() { + this.designLoaded = false + this.blockDesignLoaded = false + if (this.design['Associated biological Materials'].value!==null){ + this.removeBiologicalMaterial() + } + console.warn(this.BlockDesignForm.controls) this.BlockDesignForm.get('totalBlockControl').value - this.total_block_number= this.BlockDesignForm.get('totalBlockControl').value - this.total_column_per_block= this.BlockDesignForm.get('totalColumnPerBlockControl').value - this.total_row_per_block= this.BlockDesignForm.get('totalRowPerBlockControl').value - this.total_row_per_plot=this.BlockDesignForm.get('totalRowPerPlotControl').value + this.total_block_number = this.BlockDesignForm.get('totalBlockControl').value + this.total_column_per_block = this.BlockDesignForm.get('totalColumnPerBlockControl').value + this.total_row_per_block = this.BlockDesignForm.get('totalRowPerBlockControl').value + this.total_row_per_plot = this.BlockDesignForm.get('totalRowPerPlotControl').value + this.total_block_per_row = this.totalBlockPerRowControl.value console.warn(this.total_row_per_plot) - // this.experimental_design_blocks=[] + // this.experimental_design_blocks=[] /* let blocks=this.total_block_number let columns=this.total_column_per_block let rows=this.total_row_per_block */ delete this.design - - this.design=new ExperimentalDesign() - var replication:Replication=new Replication() + + this.design = new ExperimentalDesign() + var replication: Replication = new Replication() replication.set_replicate_number(3) this.design.set_replication(replication) + this.design.set_block_per_row(this.total_block_per_row) //this.design.set_number_of_entries(this.total_block_number*this.total_column_per_block*this.total_row_per_block) - for (var block=1;block<(this.total_block_number+1);block++){ - var block_design:BlockDesign=new BlockDesign(block, this.total_block_number) + for (var block = 1; block < (this.total_block_number + 1); block++) { + var block_design: BlockDesign = new BlockDesign(block, this.total_block_number) //console.log(block_design) //this.experimental_design_blocks.push(block_design) this.design.add_block_design(block_design) } - this.designLoaded=true + this.designLoaded = true console.log(this.design) console.log(Object.keys(this.design).filter((key) => typeof this.design[key] === 'function').map((key) => this.design[key])) //console.log(this.design.get_block_design(4)) //console.log(this.experimental_design_blocks) } - onExtractBlockDesign(){ - this.blockDesignLoaded=false + onExtractBlockDesign() { + this.blockDesignLoaded = false + if (this.design['Associated biological Materials'].value!==null){ + this.removeBiologicalMaterial() + } console.warn(this.BlockDesignForm.controls) this.BlockDesignForm.get('totalBlockControl').value - this.total_block_number= this.BlockDesignForm.get('totalBlockControl').value - this.total_column_per_block= this.BlockDesignForm.get('totalColumnPerBlockControl').value - this.total_row_per_block= this.BlockDesignForm.get('totalRowPerBlockControl').value - this.total_row_per_plot=this.BlockDesignForm.get('totalRowPerPlotControl').value + this.total_block_number = this.BlockDesignForm.get('totalBlockControl').value + this.total_column_per_block = this.BlockDesignForm.get('totalColumnPerBlockControl').value + this.total_row_per_block = this.BlockDesignForm.get('totalRowPerBlockControl').value + this.total_row_per_plot = this.BlockDesignForm.get('totalRowPerPlotControl').value console.warn(this.total_row_per_plot) - // this.experimental_design_blocks=[] + // this.experimental_design_blocks=[] /* let blocks=this.total_block_number let columns=this.total_column_per_block let rows=this.total_row_per_block */ //delete this.design - - - /* var replication:Replication=new Replication() - replication.set_replicate_number(3) - this.design.set_replication(replication) */ + + + /* var replication:Replication=new Replication() + replication.set_replicate_number(3) + this.design.set_replication(replication) */ console.warn(this.total_block_number) console.warn(this.total_column_per_block) console.warn(this.total_row_per_block) console.log(this.design) - let total_entries=this.total_block_number*this.total_column_per_block*(this.total_row_per_block/this.total_row_per_plot) + let total_entries = this.total_block_number * this.total_column_per_block * (this.total_row_per_block / this.total_row_per_plot) this.design.set_number_of_entries(total_entries) - var plot=1 - this.design.Blocking.value.forEach(block_design=>{ + var plot = 1 + this.design.Blocking.value.forEach(block_design => { block_design.clean_plot_design() + block_design['Complete Block Design'].value=[] + block_design['Incomplete Block Design'].value=[] }) - if (!this.block_design_subtype){ + + this.design.Blocking.value.forEach(block_design => { + if (this.block_design_type === "CompleteBlockDesign") { + //this.complete_block_design_type[this.block_design_subtype].value = true + block_design['Complete Block Design'].value.push(this.complete_block_design_type) + } + else { + //this.incomplete_block_design_type[this.block_design_subtype] = true + block_design['Incomplete Block Design'].value.push(this.incomplete_block_design_type) + } + for (var column = 1; column < this.total_column_per_block + 1; column++) { + //var plot_design=new PlotDesign() + for (var row = 1; row < this.total_row_per_block + 1; row++) { + var row_design: RowDesign = new RowDesign() + row_design.set_row_number(row) + row_design.set_row_per_plot(this.total_row_per_plot) + + if (row % this.total_row_per_plot === 0) { + var plot_design = new PlotDesign() + plot_design.set_column_number(column) + plot_design.set_plot_number(plot) + plot_design.add_row_design(row_design) + block_design.add_plot_design(plot_design) + //var plot_design:PlotDesign=new PlotDesign() + plot++ + } + else { + plot_design.add_row_design(row_design) + } + /* else{ + block_design.add_plot_design(plot_design) + } */ + } + } + }) + this.blockDesignLoaded = true + + /* if (!this.block_design_subtype) { this.alertService.error("You have to define which design subtypes first") } - else{ - this.design.Blocking.value.forEach(block_design=>{ - - if (this.block_design_type==="CompleteBlockDesign"){ - this.complete_block_design_type[this.block_design_subtype].value=true + else { + this.design.Blocking.value.forEach(block_design => { + if (this.block_design_type === "CompleteBlockDesign") { + this.complete_block_design_type[this.block_design_subtype].value = true block_design['Complete Block Design'].value.push(this.complete_block_design_type) } - else{ - this.incomplete_block_design_type[this.block_design_subtype]=true + else { + this.incomplete_block_design_type[this.block_design_subtype] = true block_design['Incomplete Block Design'].value.push(this.incomplete_block_design_type) } - for (var column=1;column { - if (result.event==='Confirmed') { + if (result.event === 'Confirmed') { console.log(result.observation_unit_id) this.design.set_observation_unit_id(result.observation_unit_id) - this.design.Blocking.value.forEach(block=>{ - block['Plot design'].value.forEach(plot=>{ + this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { plot.set_observation_uuid(result.obsuuids[plot['Plot number'].value]) - this.observationUnitLoaded=true + this.observationUnitLoaded = true }) }) - const observation_unit_childs_data=await this.globalService.get_all_observation_unit_childs_by_type(result.observation_unit_id.split("/")[1], 'biological_materials').toPromise()//.then(observation_unit_childs_data => { + const observation_unit_childs_data = await this.globalService.get_all_observation_unit_childs_by_type(result.observation_unit_id.split("/")[1], 'biological_materials').toPromise()//.then(observation_unit_childs_data => { console.log(observation_unit_childs_data) - //get all biological materials - if (observation_unit_childs_data.length>0){ - let data=[] - data=observation_unit_childs_data - var child_id: string = data[0]['e']['_to'] - var tmp_bm: [] = data[0]['e']['biological_materials'] - this.bm_data = this.bm_data.concat(tmp_bm) + //get all biological materials + if (observation_unit_childs_data.length > 0) { + let data = [] + data = observation_unit_childs_data + var child_id: string = data[0]['e']['_to'] + var tmp_bm: [] = data[0]['e']['biological_materials'] + this.bm_data = this.bm_data.concat(tmp_bm) + if (this.mode==='create'){ + this.onAdd() } + else{ + this.onSave() + } + } } }); - console.log(this.design) + console.log(this.design) } - removeObservationUnits(){ - this.design.set_observation_unit_id(null) - this.design.Blocking.value.forEach(block_design=>{ - block_design['Plot design'].value.forEach(plot_design=>{ - plot_design['Observation uuid'].value=null - }) - }) - this.observationUnitLoaded=false + async removeObservationUnits(confirm:boolean=true) { + if (confirm){ + const dialogRef = this.dialog.open(ConfirmationComponent, { disableClose: true, width: '500px', data: { validated: false, only_childs: false, all_childs: true, mode: 'removeobs_unit', model_type: "observation_unit" } }); + dialogRef.afterClosed().subscribe(async (result) => { + if (result) { + if (result.event == 'Confirmed') { + let obs_unit_id_to_remove = this.design.get_observation_unit_id() + this.design.set_observation_unit_id(null) + this.design.Blocking.value.forEach(block_design => { + block_design['Plot design'].value.forEach(plot_design => { + plot_design['Observation unit uuid'].value = null + }) + }); + this.observationUnitLoaded = false + await this.globalService.remove_observation_unit(obs_unit_id_to_remove).toPromise() + this.removeSample(false) + if (this.mode==='create'){ + this.onAdd() + } + else{ + this.onSave() + } + } + } + }); + } + else{ + let obs_unit_id_to_remove = this.design.get_observation_unit_id() + this.design.set_observation_unit_id(null) + this.design.Blocking.value.forEach(block_design => { + block_design['Plot design'].value.forEach(plot_design => { + plot_design['Observation unit uuid'].value = null + }) + }); + this.observationUnitLoaded = false + await this.globalService.remove_observation_unit(obs_unit_id_to_remove).toPromise() + this.removeSample(false) + if (this.mode==='create'){ + this.onAdd() + } + else{ + this.onSave() + } + } + + } + addExperimentalFactor() { + console.log(this.parent_id) + const dialogRef = this.dialog.open(AssociateExperimentalFactorComponent, { + disableClose: true, + width: '1400px', + autoFocus: true, + maxHeight: '800px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "experimental_factor", + total_available_plots: this.design['number of entries'].value, + role: this.role, + grand_parent_id: this.grand_parent_id, + available_designs:this.available_designs, + group_key: this.group_key, + design:this.design, + total_blocks_per_row:this.totalBlockPerRowControl.value, + block_design_type:this.block_design_type, + total_columns_per_block:this.totalColumnPerBlockControl.value + } + }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) + result.selected_experimental_factor.forEach(async exp_fac=>{ + let selected_experimental_factor: ExperimentalFactor = exp_fac + if (!this.design.get_experimental_factor_ids().includes(selected_experimental_factor._id)){ + this.design.add_experimental_factor_id(selected_experimental_factor._id) + this.selected_factor_id=selected_experimental_factor._id + this.experimentalFactorNames.push({ name: selected_experimental_factor._id}); + this.selected_factor_values=selected_experimental_factor['Experimental Factor values'].split(';') + let plot_index=0 + this.design.Blocking.value.forEach(block => { + if (this.block_design_type === "CompleteBlockDesign") { + block['Complete Block Design'].value[0][result.block_design_subtype].value=true + } + else{ + block['Incomplete Block Design'].value[0][result.block_design_subtype].value=true + } + block['Plot design'].value.forEach(plot => { + plot.add_factor_values(result.experimental_factor_values[plot_index+1]['factor_value']) + console.log(plot.Associated_factor_values.value) + //plot.add_factor_values('test') + plot_index++ + }); + }); + // update all observation unit factor value + console.log(result.experimental_factor_values) + console.log(this.design.get_observation_unit_id()) + let factor_values:string[]=[] + Object.keys(result.experimental_factor_values).forEach(key=>{ + factor_values.push(result.experimental_factor_values[key]['factor_value']) + }) + console.log(factor_values) + const data2 = await this.globalService.add_observation_unit_factor(selected_experimental_factor,this.design.get_observation_unit_id()).toPromise() + const data = await this.globalService.add_observation_units_factor_value(factor_values, this.design.get_observation_unit_id(), selected_experimental_factor['Experimental Factor type']).toPromise() + } + else{ + this.alertService.error("this factor is already associated with this design") + } + }); + + + + } + }); } + get_background_color(index: number, subtype: string = "") { + /* console.log(index) + if (subtype === 'completely randomized design') { + console.log(subtype) + } + else if (subtype === 'Randomized complete block design') { + console.log(subtype) + } + else if (subtype === 'Balanced incomplete design') { + console.log(subtype) + } + else if (subtype === 'Partially balanced design') { + console.log(subtype) + } + else if (subtype === 'Latin square') { + console.log(subtype) + } + else { + console.log(subtype) + } */ + if (this.design.get_experimental_factor_ids().length>0){ + //get factor index + let factor_value_index=indexOf(this.design.get_experimental_factor_ids(), this.selected_factor_id) + //console.log(indexOf(this.selected_factor_values,this.design.get_block_plot_design(index+1).get_factor_values()[factor_value_index])) + //console.log(this.selected_factor_values) + + //get factor values + //console.log(this.design.get_block_plot_design(index).Associated_factor_values) + //console.log(this.experimentalFactorNames) + + return this.factors_col[indexOf(this.selected_factor_values,this.design.get_block_plot_design(index+1).get_factor_values()[factor_value_index])] + } + else{ + return 'lightgreen' + } + + - addExperimentalFactor(){ + } + onBlockIndexChange(value){ + console.log(value) + this.block_index = value -1 } - removeExperimentalFactor(){ + get get_block_index(){ + return this.block_index } - - addBiologicalMaterial(){ - const dialogRef = this.dialog.open(AssociateBiologicalMaterial,{ - disableClose: true, - width: '1400px', - autoFocus: true, - maxHeight: '800px', - data: { - model_id: "", - parent_id: this.parent_id, - model_type: "biological_material", - total_available_plots:this.design['number of entries'].value, - role:this.role, - grand_parent_id:this.grand_parent_id, - group_key:this.group_key - } }); + get_output_from_ExpFactorNamesForm(val: any) { + + //remove factor mode + if(val.skills.length { + block['Plot design'].value.forEach(plot => { + if (!this.selected_factor_values.includes(plot.get_factor_values()[factor_value_index])) + this.selected_factor_values.push(plot.get_factor_values()[factor_value_index]) + }) + }) + + // get index off this factor in design + // get all factor values in each plot at this index + // get unique entry + } + //add factor + else{ + this.selected_factor_id=val.selected_skill + this.selected_factor_values=[] + console.log(val.selected_skill) + this.experimentalFactorNames = val.skills + let factor_value_index=indexOf(this.design.get_experimental_factor_ids(), this.selected_factor_id) + this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { + if (!this.selected_factor_values.includes(plot.get_factor_values()[factor_value_index])) + this.selected_factor_values.push(plot.get_factor_values()[factor_value_index]) + }) + }) + } + } + get_background_code_color(index: number) { + + return this.factors_col[index] + } + get get_factor_values(){ + return this.selected_factor_values + } + removeExperimentalFactor() { + const dialogRef = this.dialog.open(AssociateExperimentalFactorComponent, { + disableClose: true, + width: '1400px', + autoFocus: true, + maxHeight: '800px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "biological_material", + total_available_plots: this.design['number of entries'].value, + role: this.role, + grand_parent_id: this.grand_parent_id, + group_key: this.group_key, + design:this.design + } + }); dialogRef.afterClosed().subscribe(result => { if (result) { - console.log(result) - let selected_material:BiologicalMaterialFullInterface=result.selected_material - let mat_list=selected_material['Material source ID (Holding institute/stock centre, accession)'] - let plot_num=1 - let rep=parseInt(selected_material.replication[0]) - this.design.set_biological_material_id(selected_material["_id"]) - this.material_id=selected_material["_id"] - for (let replicate_index = 0; replicate_index < parseInt(selected_material.replication[0]); replicate_index++) { - console.log(replicate_index) - for (let matindex = 0; matindex < mat_list.length; matindex++) { - //console.log(matindex) - const element = mat_list[matindex]; - //console.log(plot_num) - //console.log(this.design.get_block_plot_design(plot_num)) - //this.design.get_block_plot_design(plot_num) as PlotDesign - this.design.get_block_plot_design(plot_num).add_material(element) - this.design.get_block_plot_design(plot_num).set_replicate_number(replicate_index+1) - let bm_list=selected_material['Biological material ID'][matindex] - bm_list=bm_list.filter(biomat=>biomat.includes("rep"+(replicate_index+1)+"_")) - for (let bmindex = 0; bmindex < bm_list.length; bmindex++) { - const element2 = bm_list[bmindex]; - this.design.get_block_plot_design(plot_num).add_biological_material(element2) - } - plot_num++ - this.biologicalMaterialLoaded=true - } + console.log(result) + } - } - }) - /* const dialogRef = this.dialog.open(SelectionComponent, - { width: '1400px', autoFocus: true, disableClose: true, maxHeight: '800px', data: { model_id: "", parent_id: this.parent_id, model_type: "biological_material", values: [], already_there: []} } - ); - dialogRef.afterClosed().subscribe(result => { + }); + } + addBiologicalMaterial() { + const dialogRef = this.dialog.open(AssociateBiologicalMaterial, { + disableClose: true, + width: '1400px', + autoFocus: true, + maxHeight: '800px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "biological_material", + total_available_plots: this.design['number of entries'].value, + role: this.role, + grand_parent_id: this.grand_parent_id, + group_key: this.group_key + } + }); + dialogRef.afterClosed().subscribe(result => { if (result) { - console.log(result) - + console.log(result) + let selected_material: BiologicalMaterialFullInterface = result.selected_material + let mat_list = selected_material['Material source ID (Holding institute/stock centre, accession)'] + let plot_num = 1 + let rep = parseInt(selected_material.replication[0]) + this.design.set_biological_material_id(selected_material["_id"]) + this.material_id = selected_material["_id"] + for (let replicate_index = 0; replicate_index < parseInt(selected_material.replication[0]); replicate_index++) { + console.log(replicate_index) + for (let matindex = 0; matindex < mat_list.length; matindex++) { + //console.log(matindex) + const element = mat_list[matindex]; + //console.log(plot_num) + //console.log(this.design.get_block_plot_design(plot_num)) + //this.design.get_block_plot_design(plot_num) as PlotDesign + this.design.get_block_plot_design(plot_num).add_material(element) + this.design.get_block_plot_design(plot_num).set_replicate_number(replicate_index + 1) + let bm_list = selected_material['Biological material ID'][matindex] + bm_list = bm_list.filter(biomat => biomat.includes("rep" + (replicate_index + 1) + "_")) + for (let bmindex = 0; bmindex < bm_list.length; bmindex++) { + const element2 = bm_list[bmindex]; + this.design.get_block_plot_design(plot_num).add_biological_material(element2) + } + plot_num++ + this.biologicalMaterialLoaded = true + } + } } - }) - */ - } - removeBiologicalMaterial(){ - this.design.Blocking.value.forEach(block_design=>{ - block_design['Plot design'].value.forEach(plot_design=>{ - plot_design.Associate_material_source.value=null - plot_design.Associated_biological_material.value=[] - plot_design['Replicate number'].value=null - }) }) - this.biologicalMaterialLoaded=false - } - + /* const dialogRef = this.dialog.open(SelectionComponent, + { width: '1400px', autoFocus: true, disableClose: true, maxHeight: '800px', data: { model_id: "", parent_id: this.parent_id, model_type: "biological_material", values: [], already_there: []} } + ); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) - extractSample(){ + } + }) + */ + } + removeBiologicalMaterial() { + const dialogRef = this.dialog.open(ConfirmationComponent, { disableClose: true, width: '500px', data: { validated: false, only_childs: false, all_childs: true, mode: 'unlinkbm', model_type: "biological_material" } }); + dialogRef.afterClosed().subscribe(async (result) => { + if (result) { + if (result.event == 'Confirmed') { + this.design['Associated biological Materials'].value=null + this.design['Associated sample ID'].value=null + this.design.Blocking.value.forEach(block_design => { + block_design['Plot design'].value.forEach(plot_design => { + plot_design.Associate_material_source.value = null + plot_design.Associated_biological_material.value = [] + plot_design['Replicate number'].value = null + }) + }) + this.biologicalMaterialLoaded = false + if (this.design.get_observation_unit_id()!==null){ + this.removeObservationUnits(false) + } + if (this.design.get_sample_id()!==null){ + this.removeSample(false) + } + if (this.mode==='create'){ + this.onAdd() + } + else{ + this.onSave() + } + } + } + }); + } + extractSample() { //first get bm data - let obs_uuids=[] - this.design.Blocking.value.forEach(block=>{ - block['Plot design'].value.forEach(plot=>{ + let obs_uuids = [] + this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { obs_uuids.push(plot.get_observation_uuid()) }) }) const dialogRef = this.dialog.open(SampleSelectionComponent, - {disableClose: true, width: '1400px', autoFocus: true, restoreFocus: false, maxHeight: '800px', data: { model_id: "", parent_id: this.parent_id, bm_data: this.bm_data, model_type: "sample", values: [], observation_id: obs_uuids} } - ); - dialogRef.afterClosed().subscribe(async res => { - if (res.event==='Confirmed') { - console.log(res.sample_data) - let result:[]=res.sample_data - const data= await this.globalService.add_observation_units_samples({"samples":result}, this.design['Associated observation units'].value).toPromise() - - let message = "experimental factor selected! " - this.alertService.success(message); + { + disableClose: true, + width: '1400px', + autoFocus: true, + restoreFocus: false, + maxHeight: '800px', + data: { + model_id: "", + parent_id: this.parent_id, + bm_data: this.bm_data, + model_type: "sample", + values: [], + observation_id: obs_uuids, + design:this.design + } + } + ); + dialogRef.afterClosed().subscribe(async res => { + if (res.event === 'Confirmed') { + console.log(res.sample_data) + let result: [] = res.sample_data + const data = await this.globalService.add_observation_units_samples({ "samples": result }, this.design['Associated observation units'].value).toPromise() + this.design.add_associated_samples(result) + this.design.set_sample_id(data['_id']) + + this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { + plot.add_samples(result.filter(sample => sample['obsUUID'] === plot.get_observation_uuid())) + }) + }) + /* result.forEach(sample => { + sample + }) */ + let message = "experimental factor selected! " + this.alertService.success(message); + this.sampleLoaded = true + if (this.mode==='create'){ + this.onAdd() + } + else{ + this.onSave() + } + } + }); + } + async removeSample(confirm:boolean=true) { + if (confirm){ + const dialogRef = this.dialog.open(ConfirmationComponent, { + disableClose: true, + width: '500px', + data: { + validated: false, + only_childs: false, + all_childs: true, + mode: 'removesample', + model_type: "sample" + } + }); + dialogRef.afterClosed().subscribe(async (result) => { + if (result) { + if (result.event == 'Confirmed') { + this.design['Associated sample'].value = [] + this.design.Blocking.value.forEach(block_design => { + block_design['Plot design'].value.forEach(plot_design => { + plot_design['Associated samples'].value = [] + }) + }) + this.sampleLoaded = false + await this.globalService.remove(this.design['Associated sample ID'].value).toPromise() + this.design['Associated sample ID'].value = null + if (this.mode==='create'){ + this.onAdd() + } + else{ + this.onSave() + } + } + } + }); + } + else{ + this.design['Associated sample'].value = [] + this.design.Blocking.value.forEach(block_design => { + block_design['Plot design'].value.forEach(plot_design => { + plot_design['Associated samples'].value = [] + }) + }) + this.sampleLoaded = false + await this.globalService.remove(this.design['Associated sample ID'].value).toPromise() + this.design['Associated sample ID'].value = null + if (this.mode==='create'){ + this.onAdd() } - }); + else{ + this.onSave() + } + + } + } - removeSample(){ + addObservations(){ + const dialogRef = this.dialog.open( + AssociateObservedVariable, + { + disableClose: true, + width: '95%', + autoFocus: true, + maxHeight: '1000px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "observed_variable", + bm_data: this.bm_data, + material_id: this.material_id, + total_available_plots: this.design['number of entries'].value, + design: this.design, + } + }); + dialogRef.afterClosed().subscribe(async result => { + if (result.event === 'Confirmed') { + console.log(result) + result.selected_observed_variable.forEach(async obs_var=>{ + this.design['Associated observed variable IDs'].value.push(obs_var['_id']) + this.design.set_associated_observations(result.observations) + this.design.Blocking.value.forEach(block => { + block['Plot design'].value.forEach(plot => { + plot.add_observations(result.observations.filter(observation => observation['obsUUID'] === plot.get_observation_uuid())) + this.observationLoaded=true + }) + }) + + /* result.observations.forEach(observation=>{ + console.log(observation['obsUUID']) + this.design.Blocking.value.forEach(block=>{ + console.log(block) + block['Plot design'].value.filter(plot=> + plot.get_observation_uuid()===observation['obsUUID'] + )[0].add_observation(observation) + }) + }) */ + + const data = await this.globalService.add_observation_units_observed_variables({ "observations": result.observations }, this.design['Associated observation units'].value, obs_var['_id']).toPromise() + }) + } + }); } + addObservationsMeasures(){ + const dialogRef = this.dialog.open( + AssociateObservationsMeasurementComponent, + { + disableClose: true, + width: '95%', + autoFocus: true, + maxHeight: '1000px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "observed_variable", + total_available_plots: this.design['number of entries'].value, + design: this.design, + } + }); - ngOnDestroy(): void { - //Called once, before the instance is destroyed. - //Add 'implements OnDestroy' to the class. + dialogRef.afterClosed().subscribe(async result => { + if (result.event === 'Confirmed') { + console.log(result) + } + }) } + + //edit mode submission - onSave(){ - this.globalService.update_document(this.model_key, this.design, this.model_type, false).pipe(first()).toPromise().then( - data => { - if (data["success"]) { - var message = this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " has been successfully updated in your history !!" - this.alertService.success(message) - return true; - } - else { - this.alertService.error("this form contains errors! " + data["message"]); - return false; - }; + onSave() { + if (this.design.get_total_block()!==this.totalBlockControl.value){ + this.removeBiologicalMaterial() + } + if(this.totalColumnPerBlockControl.value*this.totalRowPerBlockControl.value!==this.design.get_total_plot_per_block()){ + this.removeBiologicalMaterial() + } + if (this.totalRowPerPlotControl.value!==this.design.Blocking.value[0]['Plot design'].value[0].get_row_design(1)['Row per plot'].value){ + this.removeBiologicalMaterial() + } + else{ + /* if(this.totalColumnPerBlockControl.value!==this.design.get_total_column_per_block() || this.totalRowPerBlockControl.value!==this.design.get_total_row_per_block()){ + this.total_row_per_plot=this.totalRowPerPlotControl.value + this.design.Blocking.value.forEach(block_design => { + let plot=1 + + for (var column = 1; column < this.totalColumnPerBlockControl.value + 1; column++) { + //var plot_design=new PlotDesign() + for (var row = 1; row < this.totalRowPerBlockControl.value + 1; row++) { + var plot_design=block_design.get_plot_design(plot) + var row_design: RowDesign = new RowDesign() + row_design.set_row_number(row) + row_design.set_row_per_plot(this.total_row_per_plot) + if (row % this.total_row_per_plot === 0) { + + plot_design.set_column_number(column) + plot++ + } + else { + plot_design.add_row_design(row_design) + } + } + } + }); + } */ + this.design.set_block_per_row(this.totalBlockPerRowControl.value) + //check that block or plot design + this.globalService.update_document(this.model_key, this.design, this.model_type, false).pipe(first()).toPromise().then( + data => { + if (data["success"]) { + var message = this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " has been successfully updated in your history !!" + this.alertService.success(message) + return true; + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + return false; + }; - } - ); + + } + ); + } } //create mode submission - onAdd(){ + onAdd() { this.globalService.add(this.design, this.model_type, this.parent_id, false).pipe(first()).toPromise().then( data => { if (data["success"]) { //this.ngOnInit(); - this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "studydesign", role: this.role, group_key: this.group_key } }); + this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "studydesign", role: this.role, group_key: this.group_key } }); return true; } @@ -607,9 +1180,9 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After } ); } - onRemove(element:ExperimentalDesignInterface) { + onRemove(element: ExperimentalDesignInterface) { console.log(element) - const dialogRef = this.dialog.open(ConfirmationComponent, { disableClose: true,width: '500px', data: { validated: false, only_childs: false, mode: 'remove', model_type: this.model_type } }); + const dialogRef = this.dialog.open(ConfirmationComponent, { disableClose: true, width: '500px', data: { validated: false, only_childs: false, mode: 'remove', model_type: this.model_type } }); dialogRef.afterClosed().subscribe((result) => { if (result) { if (result.event == 'Confirmed') { @@ -631,24 +1204,62 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After //this.reloadComponent(['/projects']) }); } - removeBlock(_block){ - this.get_design.Blocking.value.forEach( (block, index) => { - if(block === _block) this.get_design.Blocking.value.splice(index,1); + removeBlock(_block) { + this.get_design.Blocking.value.forEach((block, index) => { + if (block === _block) this.get_design.Blocking.value.splice(index, 1); }); } - display_block(_block:BlockDesignInterface){ + display_block(_block: BlockDesignInterface) { console.log(_block['Block number'].value) console.log(this.get_design.Blocking.value) - console.log(this.get_design.Blocking.value.filter(block => - block['Block number'].value===_block['Block number'].value - )) - this.block_index=_block['Block number'].value-1 + this.block_index = _block['Block number'].value - 1 + } + changeTab(tab: string) { + this.activeTab = tab + console.log(this.activeTab) + } + showBlockInfo(i, value) { + this.hideme[i] = !this.hideme[i]; + this.Index = i; + } + showPlotInfo(j: number, value) { + this.secondhideme[j] = !this.secondhideme[j]; + this.SecondIndex = j; } - display_plot(_plot:PlotDesignInterface){ + showSampleDateInfo(k: number, value) { + this.thirdhideme[k] = !this.thirdhideme[k]; + this.ThirdIndex = k; + } + showObservationDateInfo(l: number, value) { + this.obsthirdhideme[l] = !this.obsthirdhideme[l]; + this.obsThirdIndex = l; + } + display_plot(_plot: PlotDesignInterface) { console.log(_plot['Plot number'].value) - this.plot_index=_plot['Plot number'].value-1 + this.plot_index = _plot['Plot number'].value - 1 + + /* const dialogRef = this.dialog.open(PlotOverviewComponent, { + disableClose: true, + width: '1400px', + autoFocus: true, + maxHeight: '800px', + data: { + model_id: "", + parent_id: this.parent_id, + model_type: "biological_material", + plot_design: _plot, + role: this.role, + grand_parent_id: this.grand_parent_id, + group_key: this.group_key + } + }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + console.log(result) + } + }); */ } - onSubmit(){ + onSubmit() { console.warn(this.BlockDesignForm.value); } /* get total_block_control(){ return this.BlockDesignForm.get('totalBlockControl')} @@ -657,99 +1268,120 @@ export class ExperimentalDesignPageComponent implements OnInit, OnDestroy, After get total_column_per_block_control(){ return this.BlockDesignForm.get('totalColumnPerBlockControl')} get total_row_per_plot_control(){ return this.BlockDesignForm.get('totalRowPerPlotControl')} */ - - get get_biological_material_loaded(){ return this.biologicalMaterialLoaded } - get get_observation_unit_loaded(){ return this.observationUnitLoaded } - get totalBlockControl(){ return this.BlockDesignForm.get('totalBlockControl');} - get totalBlockPerRowControl(){ return this.BlockDesignForm.get('totalBlockPerRowControl')} - get totalRowPerBlockControl(){ return this.BlockDesignForm.get('totalRowPerBlockControl');} - get totalColumnPerBlockControl(){ return this.BlockDesignForm.get('totalColumnPerBlockControl');} - get totalRowPerPlotControl(){ return this.BlockDesignForm.get('totalRowPerPlotControl'); } - get get_BlockDesignForm(){ return this.BlockDesignForm } - get get_displayedColumns(){ return this.displayedColumns } - get get_dataSource(){ return this.dataSource } - get get_design():ExperimentalDesign{ return this.design} - get get_design_type(){ return this.block_design_type} - get get_design_subtype(){ return this.block_design_subtype} - get get_parent_id(){ return this.parent_id } - get get_mode(){ return this.mode } - get get_model_id(){ return this.model_id } - get get_model_key(){ return this.model_key } - get get_role(){ return this.role } - get get_group_key(){ return this.group_key } - - get_associated_material_source(_pd:PlotDesign){ - if (_pd['Associate_material_source'].value!==null){ - return _pd['Plot number'].value +": " +_pd['Associate_material_source'].value + + get get_biological_material_loaded() { return this.biologicalMaterialLoaded } + get get_observation_unit_loaded() { return this.observationUnitLoaded } + get get_sample_loaded() { return this.sampleLoaded } + get totalBlockControl() { return this.BlockDesignForm.get('totalBlockControl'); } + get totalBlockPerRowControl() { return this.BlockDesignForm.get('totalBlockPerRowControl') } + get totalRowPerBlockControl() { return this.BlockDesignForm.get('totalRowPerBlockControl'); } + get totalColumnPerBlockControl() { return this.BlockDesignForm.get('totalColumnPerBlockControl'); } + get totalRowPerPlotControl() { return this.BlockDesignForm.get('totalRowPerPlotControl'); } + get get_BlockDesignForm() { return this.BlockDesignForm } + get get_displayedColumns() { return this.displayedColumns } + get get_dataSource() { return this.dataSource } + get get_design(): ExperimentalDesign { return this.design } + get get_design_type() { return this.block_design_type } + get get_design_subtype() { return this.block_design_subtype } + get get_parent_id() { return this.parent_id } + get get_mode() { return this.mode } + get get_model_id() { return this.model_id } + get get_model_key() { return this.model_key } + get get_role() { return this.role } + get get_group_key() { return this.group_key } + get get_grand_parent_id() { + return this.grand_parent_id + } + + get_associated_material_source(_pd: PlotDesign) { + if (_pd['Associate_material_source'].value !== null) { + return _pd['Plot number'].value + ": " + _pd['Associate_material_source'].value } - else{ - return _pd['Plot number'].value +": No material defined" + else { + return _pd['Plot number'].value + ": No material defined" } } - get_observation_units(_expd:ExperimentalDesign):number|string{ - // console.log(_expd) - if (_expd['Associated observation units'].value!==null){ + get_observation_units(_expd: ExperimentalDesign): number | string { + // console.log(_expd) + if (_expd['Associated observation units'].value !== null) { return _expd['Associated observation units'].value } - else{ + else { return "No observation unit defined" } - } - get_bm(){ + get_bm() { this.get_observation_units(this.design) } - get_samples(_expd:ExperimentalDesign){ - if (_expd['Associated sample'].value!==null){ - return _expd['Associated sample'].value + get_observations(_expd: ExperimentalDesign, block_num: number) { + let tmp_block: BlockDesign = _expd.Blocking.value.filter(block => block['Block number'].value === block_num)[0] + let observations = [] + tmp_block['Plot design'].value.forEach(plot => { + //console.log(plot) + observations = observations.concat(plot['Associated plot observations'].value) + }) + if (observations.length > 0) { + return observations.length } - else{ + else { + return "No observations defined" + } + } + + get_samples(_expd: ExperimentalDesign, block_num: number) { + let tmp_block: BlockDesign = _expd.Blocking.value.filter(block => block['Block number'].value === block_num)[0] + let samples = [] + tmp_block['Plot design'].value.forEach(plot => { + samples = samples.concat(plot['Associated samples'].value) + }) + if (samples.length > 0) { + return samples.length + } + else { return "No samples defined" - } + } } - get_associated_biological_material(_pd:PlotDesign){ + get_associated_biological_material(_pd: PlotDesign) { return _pd['Associated_biological_material'].value.length } - get_associated_sample(_pd:PlotDesign){ - return _pd['Associated samples'].value.length + get_associated_sample(_pd: PlotDesign, date:Date) { + return _pd['Associated samples'].value.filter(sample=>sample['Collection date']===date).length + } + get_associated_observation(_pd: PlotDesign, date:Date) { + return _pd['Associated plot observations'].value.filter(observation=>observation['Observation date']===date).length } - get_replicate_number(_pd:PlotDesign):number|string{ - if (_pd['Replicate number'].value!==null){ + get_replicate_number(_pd: PlotDesign): number | string { + if (_pd['Replicate number'].value !== null) { return _pd['Replicate number'].value } - else{ + else { return "No material defined" } } - get_observation_uuid(_pd:PlotDesign):number|string{ - if (_pd['Observation uuid'].value===null || _pd['Observation uuid'].value===""){ + get_observation_uuid(_pd: PlotDesign): number | string { + if (_pd['Observation unit uuid'].value === null || _pd['Observation unit uuid'].value === "") { return "No observations defined" } - else{ - return _pd['Observation uuid'].value - + else { + return _pd['Observation unit uuid'].value + } } - changeTab(tab:string){ - this.activeTab=tab - console.log(this.activeTab) - } - showBlockInfo(i,value){ - console.log(value) - this.hideme[i] = !this.hideme[i]; - this.Index = i; + get_output_from_child(val: any) { + if (val === 'cancel the form') { + console.log("Cancel form") + } + else { + console.log("Cancel form") + } } - showPlotInfo(j:number,value){ - console.log(value) - this.secondhideme[j] = !this.secondhideme[j]; - this.SecondIndex = j; - } - close(){ - this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "studydesign", role: this.role, group_key: this.group_key } }); - - //this.notify.emit("close_study") - //this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_id: this.parent_id, model_key: this.parent_id.split("/")[1], model_type:'investigation', activeTab: 'assStud', mode: "edit" , role: this.get_role, group_key: this.group_key} }); - // Same as delete project and all childs + + close() { + this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "studydesign", role: this.role, group_key: this.group_key } }); + + //this.notify.emit("close_study") + //this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_id: this.parent_id, model_key: this.parent_id.split("/")[1], model_type:'investigation', activeTab: 'assStud', mode: "edit" , role: this.get_role, group_key: this.group_key} }); + // Same as delete project and all childs } } \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/experimental-designs-page.component.html b/src/app/modules/application/projects/pages/experimental-designs-page.component.html index 73754411..d2586b32 100644 --- a/src/app/modules/application/projects/pages/experimental-designs-page.component.html +++ b/src/app/modules/application/projects/pages/experimental-designs-page.component.html @@ -1,8 +1,7 @@ - +
    -

    Define Experimental design

    - +
    @@ -24,11 +23,11 @@

    Define Experimental design

    [style.top]="contextMenuPosition.y" [matMenuTriggerFor]="contextMenu">
    - + - - + + @@ -245,4 +244,3 @@

    Experiment design table by block

    --> - \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/experimental-designs-page.component.ts b/src/app/modules/application/projects/pages/experimental-designs-page.component.ts index 1d9c84dd..e192faff 100644 --- a/src/app/modules/application/projects/pages/experimental-designs-page.component.ts +++ b/src/app/modules/application/projects/pages/experimental-designs-page.component.ts @@ -240,23 +240,49 @@ export class ExperimentalDesignsPageComponent implements OnInit, OnDestroy, Afte onRemove(element:ExperimentalDesignInterface) { console.log(element) const dialogRef = this.dialog.open(ConfirmationComponent, { disableClose: true,width: '500px', data: { validated: false, only_childs: false, mode: 'remove', model_type: this.model_type } }); - dialogRef.afterClosed().subscribe((result) => { + dialogRef.afterClosed().subscribe(async (result) => { if (result) { if (result.event == 'Confirmed') { - this.globalService.remove(element._id).pipe(first()).toPromise().then( - data => { - ////console.log(data) - if (data["success"]) { - console.log(data["message"]) - var message = element._id + " has been removed from your history !!" - - this.alertService.success(message) - this.reloadComponent() - } - else { - this.alertService.error("this form contains errors! " + data["message"]); + if (element['Associated observation units'].value!==null){ + const remove_res= await this.globalService.remove_observation_unit(element['Associated observation units'].value).toPromise() + if (remove_res["success"]) { + this.globalService.remove(element._id).pipe(first()).toPromise().then( + data => { + ////console.log(data) + if (data["success"]) { + console.log(data["message"]) + var message = element._id + " has been removed from your history !!" + + this.alertService.success(message) + this.reloadComponent() + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + } + } + ); + } + else{ + this.alertService.error("a error is occured when suppressing experimental associated component") + } + } + else{ + this.globalService.remove(element._id).pipe(first()).toPromise().then( + data => { + ////console.log(data) + if (data["success"]) { + console.log(data["message"]) + var message = element._id + " has been removed from your history !!" + + this.alertService.success(message) + this.reloadComponent() + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + } } - }); + ); + } } } //this.reloadComponent(['/projects']) @@ -264,6 +290,14 @@ export class ExperimentalDesignsPageComponent implements OnInit, OnDestroy, Afte } onAdd(){ + console.warn(this.level) + console.warn(this.model_type) + console.warn(this.model_key) + console.warn(this.mode) + console.warn(this.parent_id) + console.warn(this.group_key) + console.warn(this.role) + console.warn(this.grand_parent_id) this.router.navigate(['/experimental_design_page'], { queryParams: { level: "1", grand_parent_id:this.grand_parent_id, @@ -279,6 +313,15 @@ export class ExperimentalDesignsPageComponent implements OnInit, OnDestroy, Afte } onEdit(element:ExperimentalDesignInterface){ + console.warn(this.level) + console.warn(this.model_type) + console.warn(this.model_key) + console.warn(this.mode) + console.warn(this.parent_id) + console.warn(this.group_key) + console.warn(this.role) + console.warn(this.grand_parent_id) + console.log(element['_id']) this.router.navigate(['/experimental_design_page'], { queryParams: { level: "1", grand_parent_id:this.grand_parent_id, @@ -302,9 +345,7 @@ export class ExperimentalDesignsPageComponent implements OnInit, OnDestroy, Afte display_block(_block:BlockDesignInterface){ console.log(_block['Block number'].value) console.log(this.experimental_design_blocks) - console.log(this.experimental_design_blocks.filter(block => - block['Block number'].value===_block['Block number'].value - )) + console.log(this.experimental_design_blocks.filter(block => block['Block number'].value===_block['Block number'].value)) } reloadComponent() { diff --git a/src/app/modules/application/projects/pages/experimental-factors-page.component.html b/src/app/modules/application/projects/pages/experimental-factors-page.component.html index f7455ffa..dd35134a 100644 --- a/src/app/modules/application/projects/pages/experimental-factors-page.component.html +++ b/src/app/modules/application/projects/pages/experimental-factors-page.component.html @@ -1,6 +1,6 @@
    - +
    @@ -22,11 +22,11 @@ [style.top]="contextMenuPosition.y" [matMenuTriggerFor]="contextMenu">
    - + - + @@ -57,7 +57,9 @@
    - -
    + + +
    \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/experimental-factors-page.component.ts b/src/app/modules/application/projects/pages/experimental-factors-page.component.ts index 309e41d4..2fb86cbb 100644 --- a/src/app/modules/application/projects/pages/experimental-factors-page.component.ts +++ b/src/app/modules/application/projects/pages/experimental-factors-page.component.ts @@ -11,6 +11,7 @@ import { ExperimentalFactor } from 'src/app/models/linda/experimental_factor'; import { first } from 'rxjs/operators'; import { FormGenericComponent } from 'src/app/modules/application/dialogs/form-generic.component' import { MatDialog } from '@angular/material/dialog'; +import { TemplateSelectionComponent } from '../../dialogs/template-selection.component'; @Component({ selector: 'app-experimental-factors-page', @@ -118,7 +119,7 @@ export class ExperimentalFactorsPageComponent implements OnInit,AfterViewInit { this.router.routeReuseStrategy.shouldReuseRoute = () => false; this.router.onSameUrlNavigation = 'reload'; this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "expfac", role: this.role, group_key: this.group_key } }); -} + } onRemove(element:ExperimentalFactorInterface) { this.globalService.remove(element._id).pipe(first()).toPromise().then( data => { @@ -134,7 +135,7 @@ export class ExperimentalFactorsPageComponent implements OnInit,AfterViewInit { } }); } - add(){ + add(template:boolean=false){ let user = JSON.parse(localStorage.getItem('currentUser')); let new_step = 0 if (!this.currentUser.tutoriel_done) { @@ -150,23 +151,40 @@ export class ExperimentalFactorsPageComponent implements OnInit,AfterViewInit { //let exp_factor: ExperimentalFactor = new ExperimentalFactor() console.log(this.model_type) console.log(this.parent_id) - const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); - formDialogRef.afterClosed().subscribe((result) => { - if (result) { - if (result.event == 'Confirmed') { - console.log(result) - let exp_factor: ExperimentalFactor= result["formData"]["form"] + if (template){ + const dialogRef = this.dialog.open(TemplateSelectionComponent, {disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'experimental_factor', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + result = Object.keys(result).filter(key => !key.startsWith("_")).reduce((obj, key) => {obj[key] = result[key];return obj;}, {}); + let exp_factor: ExperimentalFactor= result this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( - data => { - if (data["success"]) { - console.log(data) - //this.ngOnInit() - this.reloadComponent() + data => { + if (data["success"]) { this.reloadComponent() } } - });; + ); } - } - }); + }); + } + else{ + const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess"} }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let exp_factor: ExperimentalFactor= result["formData"]["form"] + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + //this.ngOnInit() + this.reloadComponent() + } + } + ); + } + } + }); + } } diff --git a/src/app/modules/application/projects/pages/observation-unit-page.component.html b/src/app/modules/application/projects/pages/observation-unit-page.component.html index 2b61b530..f7947ce3 100644 --- a/src/app/modules/application/projects/pages/observation-unit-page.component.html +++ b/src/app/modules/application/projects/pages/observation-unit-page.component.html @@ -1,4 +1,7 @@ - + +

    Define Observations units

    +

    Here you can easily create Observations units that will hold all of your biological materials, samples and + allows user to easily extract sampless and observations at any level define in Study form

    @@ -59,5 +62,5 @@
    -
    + diff --git a/src/app/modules/application/projects/pages/observation-unit-page.component.ts b/src/app/modules/application/projects/pages/observation-unit-page.component.ts index f0efac76..e9e603c5 100644 --- a/src/app/modules/application/projects/pages/observation-unit-page.component.ts +++ b/src/app/modules/application/projects/pages/observation-unit-page.component.ts @@ -26,6 +26,7 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { @Input('level') level: number; @Input('parent_id') parent_id:string; @Input('model_key') model_key: string; + @Input('design_id') design_id: string; @Input('model_type') model_type: string; @Input('mode') mode: string; @Input('role') role: string; @@ -35,7 +36,7 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { @Output() notify: EventEmitter<{}> = new EventEmitter<{}>(); private dataSource: MatTableDataSource; //private displayedColumns: string[] = ['Observation unit ID','Observation unit type', 'edit']; - private displayedColumns: string[] = ['Total Observations','Observation units type', 'edit']; + private displayedColumns: string[] = ['Total Observation units','Observation units type', 'edit']; loaded: boolean = false contextMenuPosition = { x: '0px', y: '0px' }; userMenuPosition = { x: '0px', y: '0px' }; @@ -55,6 +56,7 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { this.level = params['level']; this.model_type = params['model_type']; this.model_key = params['model_key']; + this.design_id=params['design_id']; this.mode = params['mode']; this.parent_id = params['parent_id'] this.group_key = params['group_key'] @@ -84,7 +86,7 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { data => { console.log(data) data.forEach(obs_unit=>{ - obs_unit['Total Observations']=obs_unit['Observation unit ID'].length + obs_unit['Total Observation units']=obs_unit['Observation unit ID'].length obs_unit['Observation units type']=Array.from(new Set(obs_unit['Observation unit type']))[0] }) @@ -135,7 +137,9 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { let currentUrl = this.router.url; this.router.routeReuseStrategy.shouldReuseRoute = () => false; this.router.onSameUrlNavigation = 'reload'; - this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "obs", role: this.role, group_key: this.group_key } }); + //this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "obs", role: this.role, group_key: this.group_key } }); + this.router.navigate(['/experimental_design_page'], { queryParams: { level: "1", parent_id:this.parent_id, grand_parent_id: this.grand_parent_id, model_key: this.model_key, model_id: this.design_id, model_type: 'experimental_design', mode: "edit", activeTab: "exp_design_info", role: this.role, group_key: this.group_key } }); + } onRemove(element: ObservationUnitInterface) { this.globalService.remove(element._id).pipe(first()).toPromise().then( @@ -153,10 +157,10 @@ export class ObservationUnitPageComponent implements OnInit,AfterViewInit { }); } add(template:boolean=false) { - this.router.navigate(['/Observationunitform'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: "", model_type: this.model_type, mode: "create" , role:'owner', group_key:this.group_key, grand_parent_id:this.grand_parent_id} }); + this.router.navigate(['/Observationunitform'], { queryParams: { level: "1", parent_id: this.parent_id, design_id:this.design_id, model_key: "", model_type: this.model_type, mode: "create" , role:'owner', group_key:this.group_key, grand_parent_id:this.grand_parent_id} }); } onEdit(element: ObservationUnitInterface) { - this.router.navigate(['/Observationunitform'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: element._key, model_type: this.model_type, mode: "edit", role:this.role, group_key:this.group_key, grand_parent_id:this.grand_parent_id } }); + this.router.navigate(['/Observationunitform'], { queryParams: { level: "1", parent_id: this.parent_id, design_id:this.design_id, model_key: element._key, model_type: this.model_type, mode: "edit", role:this.role, group_key:this.group_key, grand_parent_id:this.grand_parent_id } }); } } diff --git a/src/app/modules/application/projects/pages/observations-page.component.html b/src/app/modules/application/projects/pages/observations-page.component.html index 0aa06659..10a727f5 100644 --- a/src/app/modules/application/projects/pages/observations-page.component.html +++ b/src/app/modules/application/projects/pages/observations-page.component.html @@ -1,4 +1,4 @@ - +> -->
    - +
    @@ -26,7 +26,7 @@ - + @@ -56,8 +56,10 @@
    - + +
    diff --git a/src/app/modules/application/projects/pages/observed-variables-page.component.ts b/src/app/modules/application/projects/pages/observed-variables-page.component.ts index 843dbcf4..5383096e 100644 --- a/src/app/modules/application/projects/pages/observed-variables-page.component.ts +++ b/src/app/modules/application/projects/pages/observed-variables-page.component.ts @@ -5,12 +5,13 @@ import { MatSort } from '@angular/material/sort' import { GlobalService, AlertService, OntologiesService } from '../../../../services'; import { Router, ActivatedRoute } from '@angular/router'; import { MatTableDataSource } from '@angular/material/table'; -import { ObservedVariableInterface, ObservedVariable} from 'src/app/models/linda/observed-variable'; +import { ObservedVariableInterface, ObservedVariable } from 'src/app/models/linda/observed-variable'; import { UserInterface } from 'src/app/models/linda/person'; import { first } from 'rxjs/operators'; import { FormGenericComponent } from 'src/app/modules/application/dialogs/form-generic.component' import { MatDialog } from '@angular/material/dialog'; import { Observable } from 'rxjs'; +import { TemplateSelectionComponent } from '../../dialogs/template-selection.component'; @Component({ selector: 'app-observed-variables-page', @@ -19,7 +20,7 @@ import { Observable } from 'rxjs'; }) export class ObservedVariablesPageComponent implements OnInit, AfterViewInit { @Input('level') level: number; - @Input('parent_id') parent_id:string; + @Input('parent_id') parent_id: string; @Input('model_key') model_key: string; @Input('model_type') model_type: string; @Input('mode') mode: string; @@ -68,7 +69,7 @@ export class ObservedVariablesPageComponent implements OnInit, AfterViewInit { this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; this._cdr.detectChanges() -} + } async ngOnInit() { this.dataSource = new MatTableDataSource([]); @@ -80,7 +81,7 @@ export class ObservedVariablesPageComponent implements OnInit, AfterViewInit { } - async get_all_observed_variables(){ + async get_all_observed_variables() { await this.globalService.get_all_observed_variables(this.parent_id.split('/')[1]).toPromise().then( data => { this.dataSource = new MatTableDataSource(data); @@ -88,8 +89,8 @@ export class ObservedVariablesPageComponent implements OnInit, AfterViewInit { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; }); - - + + } public handlePageBottom(event: PageEvent) { this.paginator.pageSize = event.pageSize; @@ -114,57 +115,120 @@ export class ObservedVariablesPageComponent implements OnInit, AfterViewInit { onRemove(element: ObservedVariableInterface) { this.globalService.remove(element._id).pipe(first()).toPromise().then( data => { - ////console.log(data) - if (data["success"]) { - console.log(data["message"]) - var message = element._id + " has been removed from your history !!" - this.alertService.success(message) - this.ngOnInit() - } - else { - this.alertService.error("this form contains errors! " + data["message"]); - } + ////console.log(data) + if (data["success"]) { + console.log(data["message"]) + var message = element._id + " has been removed from your history !!" + this.alertService.success(message) + this.ngOnInit() + } + else { + this.alertService.error("this form contains errors! " + data["message"]); + } }); } - add() { + reloadComponent() { + let currentUrl = this.router.url; + this.router.routeReuseStrategy.shouldReuseRoute = () => false; + this.router.onSameUrlNavigation = 'reload'; + this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.grand_parent_id, model_key: this.parent_id.split('/')[1], model_id: this.parent_id, model_type: 'study', mode: "edit", activeTab: "obsvar", role: this.role, group_key: this.group_key } }); + } + add(template: boolean = false) { let user = JSON.parse(localStorage.getItem('currentUser')); let new_step = 0 if (!this.currentUser.tutoriel_done) { - if (this.currentUser.tutoriel_step === "0") { - new_step = 1 - this.currentUser.tutoriel_step = new_step.toString() - localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); - } - else { - this.alertService.error("You are not in the right form as requested by the tutorial") - } + if (this.currentUser.tutoriel_step === "0") { + new_step = 1 + this.currentUser.tutoriel_step = new_step.toString() + localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); + } + else { + this.alertService.error("You are not in the right form as requested by the tutorial") + } } //let exp_factor: ExperimentalFactor = new ExperimentalFactor() console.log(this.model_type) console.log(this.parent_id) - const formDialogRef = this.dialog.open(FormGenericComponent, {disableClose: true, width: '1200px', data: { model_type: this.model_type, parent_id:this.parent_id, formData: {} , mode: "preprocess" } }); - formDialogRef.afterClosed().subscribe((result) => { - if (result) { - if (result.event == 'Confirmed') { + if (template) { + const dialogRef = this.dialog.open(TemplateSelectionComponent, { disableClose: true, width: '90%', data: { search_type: "Template", model_id: "", user_key: user._key, model_type: 'observed_variable', values: {}, parent_id: this.parent_id } }); + dialogRef.afterClosed().subscribe(result => { + if (result) { console.log(result) - let obs_variable: ObservedVariable= result["formData"]["form"] - this.globalService.add(obs_variable, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( - data => { - if (data["success"]) { - console.log(data) - this.ngOnInit() + /* var keys = Object.keys(result); + for (var i = 0; i < keys.length; i++) { + if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { + keys.splice(i, 1); + //var k=this.keys[i] + i--; } - });; + } + var new_values = {} + keys.forEach(attr => { new_values[attr] = result[attr] }) + ////////console.log(new_values) + */ + result = Object.keys(result).filter(key => !key.startsWith("_")).reduce((obj, key) => {obj[key] = result[key];return obj;}, {}); + let exp_factor: ObservedVariable= result + this.globalService.add(exp_factor, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + + this.reloadComponent() + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + } + else { this.alertService.error("this form contains errors! " + data["message"]);} + } + ); + + + /* this.globalService.add(result, this.model_type, this.parent_id, false).pipe(first()).toPromise().then( + data => { + if (data["success"]) { + //////////console.log(data["message"]) + //this.model_id=data["_id"]; + this.ngOnInit(); + //this.router.navigate(['/homespace'],{ queryParams: { key: this.parent_id.split('/')[1]} }); + var message = "A new " + this.model_type[0].toUpperCase() + this.model_type.slice(1).replace("_", " ") + " based on " + result['_id'] + " has been successfully integrated in your history !!" + this.alertService.success(message) + return true; + } + else { + //////////console.log(data["message"]) + this.alertService.error("this form contains errors! " + data["message"]); + + return false; + //this.router.navigate(['/studies']); + } + } + ); */ } - } - }); + }); + } + else { + const formDialogRef = this.dialog.open(FormGenericComponent, { disableClose: true, width: '1400px', data: { model_type: this.model_type, parent_id: this.parent_id, formData: {}, mode: "preprocess" } }); + formDialogRef.afterClosed().subscribe((result) => { + if (result) { + if (result.event == 'Confirmed') { + console.log(result) + let obs_variable: ObservedVariable = result["formData"]["form"] + this.globalService.add(obs_variable, this.model_type, this.parent_id, false, "").pipe(first()).toPromise().then( + data => { + if (data["success"]) { + console.log(data) + this.ngOnInit() + } + });; + } + } + }); + } } onEdit(element: ObservedVariableInterface) { console.warn("a study has been selected") console.warn(element) //this.notify.emit(elem) //let role = this.roles.filter(inv => inv.study_id == elem._id)[0]['role'] - this.router.navigate(['/observed_variable_page'], { queryParams: { level: "1", grand_parent_id:this.grand_parent_id, parent_id: this.parent_id, model_key: element['_key'], model_id: element['_id'], model_type: this.model_type, mode: "edit", activeTab: "obs_var_info", role: this.role, group_key: this.group_key } }); + this.router.navigate(['/observed_variable_page'], { queryParams: { level: "1", grand_parent_id: this.grand_parent_id, parent_id: this.parent_id, model_key: element['_key'], model_id: element['_id'], model_type: this.model_type, mode: "edit", activeTab: "obs_var_info", role: this.role, group_key: this.group_key } }); } diff --git a/src/app/modules/application/projects/pages/persons-page.component.html b/src/app/modules/application/projects/pages/persons-page.component.html index 4084310d..6b2cb137 100644 --- a/src/app/modules/application/projects/pages/persons-page.component.html +++ b/src/app/modules/application/projects/pages/persons-page.component.html @@ -1,93 +1,46 @@
    - - - - -
    - - - - - - - - -

    Persons involved in this project

    - - -
    - -
    -
    - - - - - - - - - - Filter - - - - - - - - - - - - - - + +
    {{column}} {{element[column]}} {{column}} - +

    Persons involved in this project

    + + +
    + +
    +
    + + + + + + + + + Filter + + + + + + + + + + + - - - - - - -
    {{column}} {{element[column]}} {{column}} + - -
    - -
    -
    + --> + + +
    + +
    +
    - - -
    - -
    +
    +
    \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/persons-page.component.ts b/src/app/modules/application/projects/pages/persons-page.component.ts index bf9446f0..3483c8f7 100644 --- a/src/app/modules/application/projects/pages/persons-page.component.ts +++ b/src/app/modules/application/projects/pages/persons-page.component.ts @@ -139,7 +139,7 @@ export class PersonsPageComponent implements OnInit { this._cdr.detectChanges() } onRoleChanged(event){ - event.target.value + console.log(event) } async get_all_persons() { diff --git a/src/app/modules/application/projects/pages/project-page.component.html b/src/app/modules/application/projects/pages/project-page.component.html index ff72e7d2..143983bb 100644 --- a/src/app/modules/application/projects/pages/project-page.component.html +++ b/src/app/modules/application/projects/pages/project-page.component.html @@ -1,18 +1,7 @@
    - - - -
    @@ -85,46 +58,6 @@

    Project associated studies

    -

    Data files

    @@ -133,6 +66,7 @@

    Data files

    access

    + Explore

    -

    Gantt

    @@ -203,8 +124,6 @@

    Project members

    access

    - - Project members

    -
    - - \ No newline at end of file diff --git a/src/app/modules/application/projects/pages/project-page.component.ts b/src/app/modules/application/projects/pages/project-page.component.ts index 3a722fd8..db6ca01a 100644 --- a/src/app/modules/application/projects/pages/project-page.component.ts +++ b/src/app/modules/application/projects/pages/project-page.component.ts @@ -96,7 +96,6 @@ export class ProjectPageComponent implements OnInit { async get_vertices() { let user = JSON.parse(localStorage.getItem('currentUser')); - //////console.log(user) this.globalService.start() return this.globalService.get_all_vertices(user._key).toPromise().then( //return this.globalService.get_all_vertices(user._key).subscribe( @@ -108,30 +107,6 @@ export class ProjectPageComponent implements OnInit { ) } - get get_parent_id(){ - return this.parent_id - } - get get_model_type(){ - return this.model_type - } - get get_mode(){ - return this.mode - } - get get_model_id(){ - return this.model_id - } - get get_model_key(){ - return this.model_key - } - get get_role(){ - return this.role - } - get get_group_key(){ - return this.group_key - } - get get_collection(){ - return this.collection - } get_output_from_child(val:any){ if (val === 'cancel the form'){ console.log("Cancel form") @@ -139,13 +114,18 @@ export class ProjectPageComponent implements OnInit { else{ console.log(val) this.alertService.success("Changes have been successfully saved") - - } } + get get_parent_id(){ return this.parent_id } + get get_model_type(){ return this.model_type } + get get_mode(){ return this.mode } + get get_model_id(){ return this.model_id } + get get_model_key(){ return this.model_key } + get get_role(){ return this.role } + get get_group_key(){ return this.group_key } + get get_collection(){ return this.collection } submit(){ //Go back to project pages - } cancel(){ //this.notify.emit("close_study") diff --git a/src/app/modules/application/projects/pages/projects-page.component.html b/src/app/modules/application/projects/pages/projects-page.component.html index 9d421df3..5c9940b4 100644 --- a/src/app/modules/application/projects/pages/projects-page.component.html +++ b/src/app/modules/application/projects/pages/projects-page.component.html @@ -68,8 +68,29 @@

    My current projects

    +

    Below is the Investigation table. This table summarizes all your projects in LINDA database. + Click on add investigation button it to expand Project Menu and select add new project. +

    + + + + + Details Options + + + + + + + + + +

    {{get_help_message}}

    +

    + +
    - +
    @@ -93,15 +114,16 @@

    My current projects

    - + - - + Filter @@ -152,8 +174,29 @@

    BFP projects

    -
    - +

    Below is the Investigation table. This table summarizes all your projects in LINDA database. + Click on add investigation button it to expand Project Menu and select add new project. +

    + + + + + Details Options + + + + + + + + + +

    {{get_help_message}}

    +

    + +
    +
    +
    @@ -212,8 +255,10 @@

    BFP projects

    - -
    + + +

    You do not have access to this group. Please contact site administrator or group member to request login credentials

    @@ -222,8 +267,6 @@

    BFP projects

    - -
    - +
    diff --git a/src/app/modules/application/projects/pages/projects-page.component.ts b/src/app/modules/application/projects/pages/projects-page.component.ts index 8bf9d14a..2ab3f872 100644 --- a/src/app/modules/application/projects/pages/projects-page.component.ts +++ b/src/app/modules/application/projects/pages/projects-page.component.ts @@ -80,9 +80,10 @@ export class ProjectsPageComponent implements OnInit, AfterViewInit { //private dataSource: MatTableDataSource; private user_groups = [] private model_type: string = 'investigation' - private displayedColumns: string[] = ['Project Name', 'Investigation description', 'edit']; + private displayedColumns: string[] = ['Project Name', 'Investigation unique ID','Investigation description', 'edit']; private dataSource: MatTableDataSource private projects: InvestigationInterface[] = [] + help_message: string; constructor( private globalService: GlobalService, @@ -157,6 +158,33 @@ export class ProjectsPageComponent implements OnInit, AfterViewInit { this.dataSource.paginator = this.paginator; this._cdr.detectChanges() } + help(button_type:string){ + if(button_type==='edit'){ + this.help_message="Edit project page" + } + else if(button_type==='edit'){ + this.help_message="Edit project details" + } + else if (button_type==='remove'){ + this.help_message="Remove project and all components associated " + } + + else if(button_type==='explore'){ + this.help_message="Explore project - Combine differents variables with experimental factor(s) in differents of levels of observations" + } + else if(button_type==='exportisatab'){ + this.help_message="Export project in ISA tab format - ISA tab format details (https://isa-specs.readthedocs.io/en/latest/isatab.html)" + } + else if (button_type==='exporttab'){ + this.help_message="Export project in popular format (tsv, csv, json)" + } + else{ + this.help_message="Share your study with other Linda users (admin only) " + } + } + get get_help_message(){ + return this.help_message + } async get_projects() { /* // get person linda db id @@ -369,6 +397,31 @@ export class ProjectsPageComponent implements OnInit, AfterViewInit { onExperimental_design() { this.router.navigate(['/design']) } + onAdd() { + let user = JSON.parse(localStorage.getItem('currentUser')); + let new_step = 0 + if (!this.currentUser.tutoriel_done) { + if (this.currentUser.tutoriel_step === "0") { + new_step = 1 + this.currentUser.tutoriel_step = new_step.toString() + localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); + } + else { + this.alertService.error("You are not in the right form as requested by the tutorial") + } + } + let new_investigation: Investigation = new Investigation() + //console.log(new_investigation) + this.globalService.add(new_investigation, this.model_type, this.parent_id, false, this.group_key).pipe(first()).toPromise().then( + data => { + if (data["success"]) { + //console.log(data) + this.router.navigate(['/project_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: data['_id'].split("/")[1], model_type: 'investigation', model_id: data['_id'], mode: "edit", activeTab: 'identifiers', role: "owner", group_key:this.group_key } }); + //this.router.navigate(['/project_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: "", model_type: this.model_type, mode: "create" } }); + + } + });; + } async onRemove(element: InvestigationInterface) { const dialogRef = this.dialog.open(ConfirmationComponent, {disableClose: true, width: '500px', data: { validated: false, only_childs: false, all_childs: true, mode: 'remove_brief', model_type: this.model_type } }); dialogRef.afterClosed().subscribe(async (result) => { @@ -395,31 +448,7 @@ export class ProjectsPageComponent implements OnInit, AfterViewInit { }); } - onAdd() { - let user = JSON.parse(localStorage.getItem('currentUser')); - let new_step = 0 - if (!this.currentUser.tutoriel_done) { - if (this.currentUser.tutoriel_step === "0") { - new_step = 1 - this.currentUser.tutoriel_step = new_step.toString() - localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); - } - else { - this.alertService.error("You are not in the right form as requested by the tutorial") - } - } - let new_investigation: Investigation = new Investigation() - //console.log(new_investigation) - this.globalService.add(new_investigation, this.model_type, this.parent_id, false, this.group_key).pipe(first()).toPromise().then( - data => { - if (data["success"]) { - //console.log(data) - this.router.navigate(['/project_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: data['_id'].split("/")[1], model_type: 'investigation', model_id: data['_id'], mode: "edit", activeTab: 'identifiers', role: "owner", group_key:this.group_key } }); - //this.router.navigate(['/project_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: "", model_type: this.model_type, mode: "create" } }); - - } - });; - } + invitePerson(group_key) { //console.log(group_key) } diff --git a/src/app/modules/application/projects/pages/projects-page.module.ts b/src/app/modules/application/projects/pages/projects-page.module.ts index ae5aa884..7caebb9b 100644 --- a/src/app/modules/application/projects/pages/projects-page.module.ts +++ b/src/app/modules/application/projects/pages/projects-page.module.ts @@ -17,7 +17,7 @@ import { MatSortModule} from '@angular/material/sort'; import { MatRadioModule } from '@angular/material/radio'; import { MatFormFieldModule} from '@angular/material/form-field' import { MatInputModule } from '@angular/material/input'; - +import { MatExpansionModule } from '@angular/material/expansion'; import { MatDividerModule} from '@angular/material/divider'; import { MatGridListModule } from '@angular/material/grid-list'; import { MatSelectModule } from '@angular/material/select'; @@ -62,6 +62,8 @@ import { TableModule} from 'primeng/table'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatIconModule } from '@angular/material/icon'; import { TextFieldModule } from '@angular/cdk/text-field'; +import { DialogModule } from '../../dialogs/dialog.module'; +//import { ChipListComponent } from 'src/app/components/chip-list/chip-list.component'; @@ -86,7 +88,9 @@ import { TextFieldModule } from '@angular/cdk/text-field'; ObservedVariablesPageComponent, EnvironmentVariablesPageComponent, EnvironmentVariablePageComponent, - DataFilePageComponent], + DataFilePageComponent, + //ChipListComponent, + ], imports: [ CommonModule, ProjectsPageRoutingModule, @@ -108,6 +112,7 @@ import { TextFieldModule } from '@angular/cdk/text-field'; MatRadioModule, MatSelectModule, MatProgressSpinnerModule, + MatExpansionModule, AlertModule, ExplorationModule, GanttModule, @@ -120,7 +125,8 @@ import { TextFieldModule } from '@angular/cdk/text-field'; MatCheckboxModule, TextFieldModule, // Primeng modules - TableModule + TableModule, + DialogModule ], exports: [ ProjectsPageComponent, diff --git a/src/app/modules/application/projects/pages/studies-page.component.html b/src/app/modules/application/projects/pages/studies-page.component.html index 92d436e8..45ab8b17 100644 --- a/src/app/modules/application/projects/pages/studies-page.component.html +++ b/src/app/modules/application/projects/pages/studies-page.component.html @@ -41,8 +41,25 @@

    +

    Below is the studies table. This table summarizes all studies in your ccurret project. + Click on add study button it to expand Study Menu and select add new study. +

    + + + + + Details Options + + + + + + +

    {{get_help_message}}

    +

    +
    - +
    @@ -53,7 +70,7 @@

    - +

    My Studies

    diff --git a/src/app/modules/application/projects/pages/studies-page.component.ts b/src/app/modules/application/projects/pages/studies-page.component.ts index 473f483a..290d4491 100644 --- a/src/app/modules/application/projects/pages/studies-page.component.ts +++ b/src/app/modules/application/projects/pages/studies-page.component.ts @@ -75,6 +75,7 @@ export class StudiesPageComponent implements OnInit,AfterViewInit { private model_type: string = 'study' private dataSource: MatTableDataSource; private displayedColumns: string[] = ['Study Name', 'Study description', 'edit']; + help_message: string; constructor( @@ -93,7 +94,7 @@ export class StudiesPageComponent implements OnInit,AfterViewInit { params => { this.parent_id = params['parent_id']; this.group_key = params['group_key']; - this.role == params['role']; + this.role = params['role']; } ); this.currentUser = JSON.parse(localStorage.getItem('currentUser')); @@ -130,6 +131,20 @@ export class StudiesPageComponent implements OnInit,AfterViewInit { //console.log(this.parent_id) //this.wizardService.onClickTour(this.vertices, this.currentUser) } + help(button_type:string){ + if(button_type==='edit'){ + this.help_message="Edit Study details" + } + else if (button_type==='remove'){ + this.help_message="Remove study and all components associated " + } + else{ + this.help_message="Share your study with other Linda users (admin only) " + } + } + get get_help_message(){ + return this.help_message + } ngAfterViewInit() { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; @@ -191,7 +206,7 @@ export class StudiesPageComponent implements OnInit,AfterViewInit { console.warn(elem) //this.notify.emit(elem) let role = this.roles.filter(inv => inv.study_id == elem._id)[0]['role'] - this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: elem['_key'], model_id: elem['_id'], model_type: this.model_type, mode: "edit", activeTab: "studyinfo", role: role, group_key: this.group_key } }); + this.router.navigate(['/study_page'], { queryParams: { level: "1", parent_id: this.parent_id, model_key: elem['_key'], model_id: elem['_id'], model_type: this.model_type, mode: "edit", activeTab: "studyinfo", role: role, group_key: this.group_key, grand_parent_id:this.parent_id } }); } onNext(node: string) { diff --git a/src/app/modules/application/projects/pages/study-page.component.html b/src/app/modules/application/projects/pages/study-page.component.html index 30980b7d..ea304098 100644 --- a/src/app/modules/application/projects/pages/study-page.component.html +++ b/src/app/modules/application/projects/pages/study-page.component.html @@ -1,4 +1,5 @@
    + + -
    +
    --> - + + +
    - --> +
    -

    Describe experimental factors

    +

    Experimental factors

    -

    The object of a study is to ascertain the impact of one or more factors on the biological material. Thus, a factor is, by definition a condition that varies between observation units, which may be biotic (pest, disease interaction) or abiotic (treatment and cultural practice) in nature. Depending on the level of the data, an experimental factor can be either 'what is the factor applied to the plant' (i.e. Unwatered), or the 'environmental characterisation' (i.e. if no rain on unwatered plant : Drought ; if rain on unwatered plant: Irrigated)

    +

    Definition: The object of a study is to ascertain the impact of one or more factors on the biological material. Thus, a factor is, by definition a condition that varies between observation units, which may be biotic (pest, disease interaction) or abiotic (treatment and cultural practice) in nature. Depending on the level of the data, an experimental factor can be either 'what is the factor applied to the plant' (i.e. Unwatered), or the 'environmental characterisation' (i.e. if no rain on unwatered plant : Drought ; if rain on unwatered plant: Irrigated)

    You do not have access to this part of the project. Please contact project owner to gain full project access

    @@ -249,7 +293,7 @@

    Describe experimental factors

    Describe environmental parameters

    -

    +

    Definition: Environmental parameters that were kept constant throughout the study and did not change between observation units or assays. Environment characteristics that vary over time, i.e. environmental variables, should be recorded as Observed Variables.

    @@ -276,8 +320,14 @@

    Describe environmental parameters

    -

    Describe events

    +

    Events

    +

    + Definition: An event is discrete occurrence at a particular time in the experiment (which can be natural, + such as rain, or unnatural, such as planting, watering, etc). Events may be the realization of Factors or parts of + Factors, or may be confounding to Factors. Can be applied at the whole study level or to only a subset of observation + units. +

    You do not have access to this part of the project. Please contact project owner to gain full project access

    @@ -298,7 +348,7 @@

    Describe events

    -
    + - -
    + + + + +
    +
    -->

    Project members

    diff --git a/src/app/modules/application/projects/pages/study-page.component.ts b/src/app/modules/application/projects/pages/study-page.component.ts index eb8e3b86..31ee812b 100644 --- a/src/app/modules/application/projects/pages/study-page.component.ts +++ b/src/app/modules/application/projects/pages/study-page.component.ts @@ -33,6 +33,8 @@ export class StudyPageComponent implements OnInit { startTime: Date; endTime: Date; timeDiff: number; + panel_disabled: boolean = false + panel_expanded: boolean = false constructor(private globalService: GlobalService, private searchService: SearchService, diff --git a/src/app/modules/application/statistics/exploration.component.html b/src/app/modules/application/statistics/exploration.component.html index aee18b12..3c901147 100644 --- a/src/app/modules/application/statistics/exploration.component.html +++ b/src/app/modules/application/statistics/exploration.component.html @@ -1,4 +1,13 @@
    + +

    Investigation exploration

    + + Still in development, new version upcoming on 31 of July 2022 !!! + + + + +

    Investigation exploration

    You're about to mine your data with Linda. You can visualize easily your observations and correlate them with experimental factors and environmental @@ -112,4 +121,5 @@


    -->

    + \ No newline at end of file diff --git a/src/app/modules/application/statistics/exploration.component.ts b/src/app/modules/application/statistics/exploration.component.ts index 0e38739e..cce7b540 100644 --- a/src/app/modules/application/statistics/exploration.component.ts +++ b/src/app/modules/application/statistics/exploration.component.ts @@ -23,7 +23,7 @@ export class ExplorationComponent implements OnInit { ObservationUnits: {} = {}; BiologicalMaterials: {} = {}; title = 'Angular Charts'; - + maintenance:boolean=true view: any[] = [2500, 800]; view2: any[] = [1500, 800]; @@ -81,7 +81,7 @@ export class ExplorationComponent implements OnInit { data[0].forEach( data_file => { //console.log(data_file) - let stud_ass_header=data_file.associated_headers.filter(associated_header => associated_header["associated_component_field"]==="Study unique ID")[0] + let stud_ass_header=data_file.associated_headers.filter(associated_header => associated_header["associated_component_field"]==="Study Name")[0] stud_ass_header.associated_linda_id.forEach(linda_id=>{ if (!this.filename_used.includes(data_file.filename)) { this.datafile_ids[data_file.filename] = data_file.eto diff --git a/src/app/modules/application/tables/table.component.css b/src/app/modules/application/tables/table.component.css index e69de29b..963345a1 100644 --- a/src/app/modules/application/tables/table.component.css +++ b/src/app/modules/application/tables/table.component.css @@ -0,0 +1,3 @@ +.mat-table { + overflow-x: scroll; + } \ No newline at end of file diff --git a/src/app/modules/application/templates/templates.component.html b/src/app/modules/application/templates/templates.component.html index 50a87075..6e1ca17e 100644 --- a/src/app/modules/application/templates/templates.component.html +++ b/src/app/modules/application/templates/templates.component.html @@ -20,7 +20,7 @@

    Your template forms

    Filter - + diff --git a/src/app/modules/application/templates/templates.component.ts b/src/app/modules/application/templates/templates.component.ts index 4f2e26fe..481aeb03 100644 --- a/src/app/modules/application/templates/templates.component.ts +++ b/src/app/modules/application/templates/templates.component.ts @@ -36,6 +36,7 @@ export class TemplatesComponent implements OnInit, AfterViewInit { { this.dataSource = new MatTableDataSource([]); this.currentUser = JSON.parse(localStorage.getItem('currentUser')); + this.get_templates() } @@ -61,6 +62,7 @@ export class TemplatesComponent implements OnInit, AfterViewInit { console.log(this.dataSource); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; + this.selected_model='Experimental factor' this._cdr.detectChanges(); } } diff --git a/src/app/modules/application/user/person.component.html b/src/app/modules/application/user/person.component.html index 42a28d69..999bc35c 100644 --- a/src/app/modules/application/user/person.component.html +++ b/src/app/modules/application/user/person.component.html @@ -15,9 +15,8 @@ -->

    Member since {{account_creation_date}}

    - +
    -
    diff --git a/src/app/modules/application/user/person.component.ts b/src/app/modules/application/user/person.component.ts index 3863d332..fa27454d 100644 --- a/src/app/modules/application/user/person.component.ts +++ b/src/app/modules/application/user/person.component.ts @@ -82,23 +82,32 @@ export class PersonComponent implements OnInit { console.log(this.currentPerson) } + isGuestProfile():boolean{ + return this.currentPerson['Person name'].includes('Guest') + } onModify(field: string) { - //open modify field dialog with only one field and one button - const dialogRef = this.editdialog.open(EditFormComponent, { width: '1000px', data: { person: this.currentPerson, field_to_edit: field } }); - dialogRef.afterClosed().subscribe(data => { - if (data !== undefined) { - if (data['event']==='Confirmed'){ - console.log(data) - if (field.includes('Person')){ - this.ngOnInit() - } - else{ - this.authenticationService.logout() - this.router.navigate(['/login']) + if (this.currentPerson['Person name'].includes('Guest')){ + this.alertService.error("You cannot modify the guest profile") + } + else{ + //open modify field dialog with only one field and one button + const dialogRef = this.editdialog.open(EditFormComponent, { width: '1000px', data: { person: this.currentPerson, field_to_edit: field } }); + dialogRef.afterClosed().subscribe(data => { + if (data !== undefined) { + if (data['event']==='Confirmed'){ + console.log(data) + if (field.includes('Person')){ + this.ngOnInit() + } + else{ + this.authenticationService.logout() + this.router.navigate(['/login']) + } } - } - }; - }); + }; + }); + } + } get getregisterForm() { diff --git a/src/app/modules/application/user/profile.component.html b/src/app/modules/application/user/profile.component.html index fe93f948..2670a233 100644 --- a/src/app/modules/application/user/profile.component.html +++ b/src/app/modules/application/user/profile.component.html @@ -6,12 +6,12 @@ - -
    + +
    + + + + + + How to create an environment parameters with data loader ? + + + + + + + +
    + + + + How to create observed variables with data loader ? + + + + + + + +
    + + + + How to create experimental factors with data loader ? + + + + + + + +
    + + + + How to create experimental design with data loader ? + + + + + + + +
    + + + + How to assign biological materials to experimental design ? + + + + + + + +
    + + + + How to assign samples to experimental design ? + + + + + + + +
    + + + + How to assign observation unit to experimental design ? + + + + + + + +
    + + + + How to create samples with data loader ? + + + + + + + +
    + + + + How to create an observation units with data loader ? + + + + + + + +
    +
    \ No newline at end of file diff --git a/src/app/modules/general/home/home-new.component.css b/src/app/modules/general/home/home-new.component.css index b70bd46c..19eda523 100644 --- a/src/app/modules/general/home/home-new.component.css +++ b/src/app/modules/general/home/home-new.component.css @@ -1,15 +1,17 @@ .nga-gradient { - padding: 3rem 0; + padding: 0.5rem 0; background: linear-gradient(225deg, #10857f, #4ECDC4); + margin-right: auto; +margin-left: auto; } .nga-btn-home { font-family: inherit; color: inherit; display: inline-block; - line-height: 32px; - line-height: 3.2rem; - padding: 0 16px; + line-height: 12px; + line-height: 2.2rem; + padding: 0 12px; font-size: 14px; font-size: 1.4rem; font-weight: 400; @@ -17,18 +19,18 @@ text-decoration: none; overflow: hidden; border: none; - color: white; + color: #4ECDC4; } .nga-btn-home { - background-color: black; - padding: 2px 34px 0; - font-size: 16px; + background-color:#2f323a; + padding: 2px 24px 0; + font-size: 12px; font-size: 1.6rem; font-weight: 600; line-height: 30px; - line-height: 3rem; - border-radius: 48px; + line-height: 2.2rem; + border-radius: 28px; box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .26); box-sizing: border-box; cursor: pointer diff --git a/src/app/modules/general/home/home-new.component.html b/src/app/modules/general/home/home-new.component.html index fdf2c14f..a1833c62 100644 --- a/src/app/modules/general/home/home-new.component.html +++ b/src/app/modules/general/home/home-new.component.html @@ -1,197 +1,205 @@ -
    -
    -
    -
    -
    -
    - -

    LINDA Web Application

    -
    -

    {{ 'Plant Experimental metadata' }}

    -

    {{ 'MIAPPE' }}

    -

    {{ 'FAIR' }}

    -
    -
    - Get Started +
    +
    +
    +
    +
    +
    +
    + +

    LINDA Web Application

    +
    +
    +
    + +
    + + +
    -
    -
    - + - - + Getting started with Angular +
    --> + + +
    -
    -
    -
    -
    -
    + + +
    +
    +
    + + First slide + Second slide
    -
    -
    -
    - - - Previous - - - - Next - + + +
    +
    - -
    - - -
    -
    -
    -

    Features

    -
    -
    -
    -
    - -

    Preserve and store environmental metadata

    -
      -
    • Insert metadata respecting the MIAPPE model (https://www.miappe.org/)
    • -
    • Use the associated ontologies (Plantontology, XEO, ENVo, etc.)
    • -
    • Data from sensors files can be import as tabular and json files
    • -
    -
    - Image - - +
    +
    +

    Features

    +
    + - - -
    - - - -
    - -
    - - - -
    -
    - - +
    +
    \ No newline at end of file diff --git a/src/app/modules/general/login/login.component.html b/src/app/modules/general/login/login.component.html index 9fba56ca..53093317 100644 --- a/src/app/modules/general/login/login.component.html +++ b/src/app/modules/general/login/login.component.html @@ -1,5 +1,5 @@
    -

    Sign In With Username/Email

    +

    Sign In with account details

    @@ -24,5 +24,11 @@

    Sign In With Username/Email

    +

    Sign In with guest account

    +
    +
    You can directly use linda without any account. Keep in mind that your data will not be saved in LINDA database until you do not have created an account
    +
    + +
    diff --git a/src/app/modules/general/login/login.component.ts b/src/app/modules/general/login/login.component.ts index 133180ea..40b1e3ff 100644 --- a/src/app/modules/general/login/login.component.ts +++ b/src/app/modules/general/login/login.component.ts @@ -2,9 +2,9 @@ import { Component, OnInit } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { first } from 'rxjs/operators'; -import { AlertService, AuthenticationService } from '../../../services'; +import { AlertService, UserService, AuthenticationService } from '../../../services'; import { Md5} from 'ts-md5/dist/md5'; - +import * as uuid from 'uuid'; @Component({templateUrl: 'login.component.html'}) @@ -18,6 +18,7 @@ export class LoginComponent implements OnInit { constructor( private formBuilder: FormBuilder, private route: ActivatedRoute, + private userService:UserService, private router: Router, private authenticationService: AuthenticationService, private alertService: AlertService @@ -34,7 +35,6 @@ export class LoginComponent implements OnInit { username: ['', Validators.required], password: ['', Validators.required] }); - // reset login status /* this.authenticationService.logout(); console.log(localStorage); @@ -44,12 +44,55 @@ export class LoginComponent implements OnInit { // get return url from route parameters or default to '/' this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; console.log(this.returnUrl); - } // convenience getter for easy access to form fields get f() { return this.loginForm.controls; } + create_guest_profile(){ + + let date_created=new Date() + let guest_tmp_uuid=uuid.v4() + let person_id=Md5.hashStr(guest_tmp_uuid) + let username="Guest_"+guest_tmp_uuid + let email="guests@guest_"+guest_tmp_uuid+".com" + let pwd=Md5.hashStr('guest-anonymous') + let guest_user:any={ + 'dateCreated':date_created.toUTCString(), + 'Person name': "Guest", + 'username': username, + 'Person affiliation': "Guest-user", + 'Person role': ["beta-tester"], + 'Person ID': person_id, + 'Person email': email , + 'password':pwd, + 'confirmpassword':pwd, + } + this.userService.register_person(guest_user, "groups/Guests") + .pipe(first()) + .subscribe( + data => { + this.alertService.success('Registration successful', true); + //this.router.navigate(['/login']); + this.authenticationService.login(username,pwd).pipe(first()) + .subscribe(( data2 )=> { + this.router.navigate([this.returnUrl]); + }, + error2 => { + this.error = error2 + this.alertService.error(error2); + this.authenticationService.logout() + this.loading = false; + } + ); + }, + error => { + this.alertService.error(error); + this.loading = false; + } + ); + + } onSubmit() { this.submitted = true; this.alertService.clear(); diff --git a/src/app/modules/general/request-reset/request-reset.component.ts b/src/app/modules/general/request-reset/request-reset.component.ts index 46a7b77e..1eb7925c 100644 --- a/src/app/modules/general/request-reset/request-reset.component.ts +++ b/src/app/modules/general/request-reset/request-reset.component.ts @@ -19,7 +19,7 @@ export class RequestResetComponent implements OnInit { constructor( private authService: AuthenticationService, private router: Router, - ) { + ) { } @@ -30,31 +30,32 @@ export class RequestResetComponent implements OnInit { } - RequestResetUser(form) { + async RequestResetUser(form) { console.log(form) if (form.valid) { this.IsvalidForm = true; console.log(this.RequestResetForm.value) - this.authService.requestReset(this.RequestResetForm.value).toPromise().then( - data => { - if (data['success']){ - console.log(data) - console.log("need to write routine service") + const data = await this.authService.requestReset(this.RequestResetForm.value).toPromise()//.then( + if (data['success']) { + console.log(data) + //get token and run auth service sendmail + //var token=data['token'] + //this.RequestResetForm.value['token']=token + console.log(this.RequestResetForm.value['email']) + this.authService.sendmail(this.RequestResetForm.value['email'], data['token']).toPromise().then( + data2 => { + console.log(data2) } - /* this.RequestResetForm.reset(); - this.successMessage = "Reset password link send to email sucessfully."; - setTimeout(() => { - this.successMessage = null; - this.router.navigate(['login']); - }, 3000); */ - } - /* , - err => { - if (err.error.message) { - this.errorMessage = err.error.message; - } - } */ - ); + ) + console.log("need to write routine service") + } + /* this.RequestResetForm.reset(); + this.successMessage = "Reset password link send to email sucessfully."; + setTimeout(() => { + this.successMessage = null; + this.router.navigate(['login']); + }, 3000); */ + } else { this.IsvalidForm = false; } diff --git a/src/app/modules/general/response-reset/response-reset-routing.module.ts b/src/app/modules/general/response-reset/response-reset-routing.module.ts index 4199d593..0058b5ee 100644 --- a/src/app/modules/general/response-reset/response-reset-routing.module.ts +++ b/src/app/modules/general/response-reset/response-reset-routing.module.ts @@ -3,7 +3,7 @@ import { Routes, RouterModule } from '@angular/router'; import { ResponseResetComponent } from './response-reset.component'; const routes: Routes = [ - { path: '', component: ResponseResetComponent }, + //{ path: '', component: ResponseResetComponent }, { path: ':token', component: ResponseResetComponent } ]; diff --git a/src/app/services/authentication.service.ts b/src/app/services/authentication.service.ts index bf5d13b9..1bfe3b77 100644 --- a/src/app/services/authentication.service.ts +++ b/src/app/services/authentication.service.ts @@ -18,20 +18,20 @@ export interface AuthResponse { export class AuthenticationService { private APIUrl: string; - private nodemailerUrl: string; + private apimailUrl: string; private currentUserSubject: BehaviorSubject; public currentUser: Observable; public user: UserInterface; public person: UserInterface - constructor(private http: HttpClient, private router: Router) { + constructor(private http: HttpClient, private rosuter: Router) { //localStorage.removeItem('currentUser'); //console.log(localStorage) var tmp: any = localStorage.getItem('currentUser') this.currentUserSubject = new BehaviorSubject(JSON.parse(tmp)); this.currentUser = this.currentUserSubject.asObservable(); this.APIUrl = Constants.APIConfig.APIUrl; - this.nodemailerUrl = Constants.APIConfig.nodemailerUrl; + this.apimailUrl = Constants.APIConfig.apimailUrl; } public get currentUserValue(): UserInterface { return this.currentUserSubject.value; @@ -75,7 +75,15 @@ export class AuthenticationService { localStorage.removeItem('currentUser'); this.currentUserSubject.next(null); //this.router.navigate(['/login']); - + } + + sendmail(email, token) { + let obj2send = { + 'email': email, + 'token': token + }; + console.log(obj2send) + return this.http.post(`${this.apimailUrl + "sendmail/"}`, obj2send); } requestReset(email_obj) { let token = uuid.v4() diff --git a/src/app/services/file.service.ts b/src/app/services/file.service.ts index 9f459eeb..469710fb 100644 --- a/src/app/services/file.service.ts +++ b/src/app/services/file.service.ts @@ -1,6 +1,6 @@ import { Injectable, ɵCodegenComponentFactoryResolver } from '@angular/core'; import { HttpClient, HttpEvent, HttpErrorResponse, HttpEventType } from '@angular/common/http'; -import { map } from 'rxjs/operators'; +import { catchError, map } from 'rxjs/operators'; import { throwError, Observable } from 'rxjs'; import { Constants } from "../constants"; import { saveAs } from 'file-saver'; @@ -8,6 +8,10 @@ import * as JSZip from 'jszip'; import * as fs from 'fs'; import { element } from 'protractor'; import * as XLSX from 'xlsx'; +import { AssociatedHeadersInterface } from '../models/linda/data_files'; +import { PersonInterface } from '../models/linda/person'; +import { UserService } from './user.service'; +import { GlobalService } from './global.service'; @Injectable({ @@ -16,18 +20,21 @@ import * as XLSX from 'xlsx'; export class FileService { private APIUrl: string; fileUploaded: File; - - - constructor(private httpClient: HttpClient) { + constructor( + private httpClient: HttpClient, + private userService: UserService, + private globalService: GlobalService) { this.APIUrl = Constants.APIConfig.APIUrl; } - private extractData(res: Response) { - + let body = res; return body || {}; } - public upload4(data:{}, parent_id: string): Observable { + private get_csv(csvData: any) { + return csvData.split(/\r|\n|\r/); + } + public upload4(data: {}, parent_id: string): Observable { let user = JSON.parse(localStorage.getItem('currentUser')); let obj2send = { 'username': user.username, @@ -35,7 +42,7 @@ export class FileService { 'parent_id': parent_id, 'values': data }; - //console.log(obj2send) + console.log(obj2send) return this.httpClient.post(`${this.APIUrl + "upload_data"}`, obj2send).pipe(map(this.extractData)); } public upload3(filename: string, data, headers, associated_headers, parent_id: string): Observable { @@ -52,7 +59,7 @@ export class FileService { } }; - console.log(obj2send) + //console.log(obj2send) return this.httpClient.post(`${this.APIUrl + "upload_data"}`, obj2send).pipe(map(this.extractData)); } public upload2(filename: string, data, headers, associated_headers, parent_id: string): Observable { @@ -69,7 +76,7 @@ export class FileService { } }; - //console.log(obj2send) + ////console.log(obj2send) return this.httpClient.post(`${this.APIUrl + "upload"}`, obj2send).pipe(map(this.extractData)); } public upload(filename: string, data, headers, associated_headers, parent_id: string): Observable { @@ -90,11 +97,11 @@ export class FileService { switch (event.type) { case HttpEventType.UploadProgress: const progress = Math.round(100 * event.loaded / event.total); - //console.log(progress); + ////console.log(progress); return { status: 'progress', message: progress }; case HttpEventType.Response: - //console.log(event); + ////console.log(event); return event.body; default: @@ -103,19 +110,19 @@ export class FileService { }) ); } - read_csv(fileUploaded:File) { + public read_csv(fileUploaded: File) { let fileReader = new FileReader(); - var csv:string|ArrayBuffer="" + var csv: string | ArrayBuffer = "" fileReader.onload = (e) => { csv = fileReader.result; } fileReader.readAsText(fileUploaded); - return this.get_csv(csv) + return this.get_csv(csv) } - readExcel(fileUploaded:File) { + public readExcel(fileUploaded: File) { let fileReader = new FileReader(); fileReader.onload = (e) => { - var storeData:any = fileReader.result; + var storeData: any = fileReader.result; var data = new Uint8Array(storeData); var arr = new Array(); for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]); @@ -124,42 +131,39 @@ export class FileService { var first_sheet_name = book.SheetNames[0]; var worksheet = book.Sheets[first_sheet_name]; var csv = XLSX.utils.sheet_to_csv(worksheet); - return this.get_csv(csv); + return this.get_csv(csv); } fileReader.readAsArrayBuffer(fileUploaded); - - } - get_csv(csvData: any) { - return csvData.split(/\r|\n|\r/); + } - public build_path(root_id, models, selected_format) { - console.log(models) - var paths = { 'filepath': [], 'data': [], 'parent_id': [] } + public async build_path(root_id, models, selected_format) { + //console.log(models) + var _paths = { 'filepath': [], 'data': [], 'parent_id': [] } models['models_data'].forEach( - result => { - var _from: string = result["e"]["_from"] - var _to: string = result["e"]["_to"] + model => { + var _from: string = model["e"]["_from"] + var _to: string = model["e"]["_to"] let formats = Object.keys(selected_format); let path = '' if (_from == root_id) { models['models_data'].forEach( - result_bis => { - var _from_bis: string = result_bis["e"]["_from"] - var _to_bis: string = result_bis["e"]["_to"] + model_bis => { + var _from_bis: string = model_bis["e"]["_from"] + var _to_bis: string = model_bis["e"]["_to"] // ???????? if ((_to == _from_bis) && (_to == _to_bis)) { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _to.replace('/', '_') + '/' + _to_bis.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } //if (path.split('/').length == 2) else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -169,15 +173,15 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _to.replace('/', '_') + '/' + _to.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } //if (path.split('/').length == 2) else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -190,17 +194,17 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _to.replace('/', '_') + '/' + _to.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } else if (path.split('/').length == 2) { - paths['parent_id'].push(path.split('/')[0]) + _paths['parent_id'].push(path.split('/')[0]) } else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -216,17 +220,17 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _from.replace('/', '_') + '/' + _to.replace('/', '_') + '/' + _to_bis.replace('/', '_') + '/' + _to_bis.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } else if (path.split('/').length == 2) { - paths['parent_id'].push(path.split('/')[0]) + _paths['parent_id'].push(path.split('/')[0]) } else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -236,17 +240,17 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _from_bis.replace('/', '_') + '/' + _from.replace('/', '_') + '/' + _to.replace('/', '_') + '/' + _to.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } else if (path.split('/').length == 2) { - paths['parent_id'].push(path.split('/')[0]) + _paths['parent_id'].push(path.split('/')[0]) } else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -256,17 +260,17 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { path = _from.replace('/', '_') + '/' + _to.replace('/', '_') + '/' + _to.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } else if (path.split('/').length == 2) { - paths['parent_id'].push(path.split('/')[0]) + _paths['parent_id'].push(path.split('/')[0]) } else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -279,17 +283,17 @@ export class FileService { for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected'] && formats[i] != "isa_tab (.txt)") { let path = _from.replace('/', '_') + '/' + _to.replace('/', '_') + '/' + _to.replace('/', '_') + formats[i] - if (!paths['filepath'].includes(path)) { - paths['filepath'].push(path) - paths['data'].push(result["v"]) + if (!_paths['filepath'].includes(path)) { + _paths['filepath'].push(path) + _paths['data'].push(model["v"]) if (path.split('/').length > 2) { - paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) + _paths['parent_id'].push(path.split('/')[path.split('/').length - 3]) } else if (path.split('/').length == 2) { - paths['parent_id'].push(path.split('/')[0]) + _paths['parent_id'].push(path.split('/')[0]) } else { - paths['parent_id'].push(root_id) + _paths['parent_id'].push(root_id) } } } @@ -298,16 +302,17 @@ export class FileService { } } ); - return paths + + return _paths } public build_zip(paths, zipFile: JSZip) { //let zipFile: JSZip = new JSZip(); //save a config file to reload - console.log(paths) + //console.log(paths) var dict = { 'filepath': [], 'model_type': [], 'parent_id': [] } for (var i = 0; i < paths['filepath'].length; i++) { let model_type = paths['data'][i]["_id"].split('/')[0] - if (model_type == "metadata_files") { + if (model_type == "metadata_files" || model_type == "data_files") { if (paths['filepath'][i].includes(".csv")) { let csvData = this.ConvertMetadataJsonTo(paths['data'][i], ","); @@ -387,7 +392,7 @@ export class FileService { zipFile.file('hierarchy.json', blob_json); return zipFile } - open_zip(fileUploaded:File){ + open_zip(fileUploaded: File) { let zipFile: JSZip = new JSZip(); return zipFile.loadAsync(fileUploaded) } @@ -400,131 +405,235 @@ export class FileService { // }); // }); // } + public get_studies_person(submodels) { + var test = [] + submodels['models_data'].filter(submodel => submodel["v"]["_id"].split('/')[0] === "studies").forEach(async element => { + let persons_in_study = await this.userService.get_persons(element["v"]['_key'], 'studies').toPromise() + + test.push(persons_in_study) + }); + return test + } + public build_study_contacts(_persons: any, _isa_model, study_id: string) { + _isa_model['STUDY CONTACTS']["Comment[Person ID]"] = [] + _persons.forEach(person => { + if (study_id === person['model_id']) { + _isa_model['STUDY CONTACTS']["Comment[Person ID]"].push(person.vertice['Person ID']) + _isa_model['STUDY CONTACTS']["Study Person First Name"].push(person.vertice['Person name'].split(" ")[0]) + if (person.vertice['Person name'].split(" ")[1]) { + _isa_model['STUDY CONTACTS']["Study Person Last Name"].push(person.vertice['Person name'].split(" ")[1]) + } + _isa_model['STUDY CONTACTS']["Study Person Mid Name"] = [] + _isa_model['STUDY CONTACTS']["Study Person Email"].push(person.vertice['Person email']) + _isa_model['STUDY CONTACTS']["Study Person Roles"].push(person.vertice['Person role']) + _isa_model['STUDY CONTACTS']["Study Person Affiliation"].push(person.vertice['Person affiliation']) + _isa_model['STUDY CONTACTS']["Study Person Address"].push(person.vertice['Person affiliation']) + } - public saveISA(model_data, submodels, model_type: string, collection_name = 'data', model_id = "", isa_model, model) { - //console.log(submodels) + }) + return _isa_model + } + public build_investigation_contacts(_persons_in_investigation, _isa_model) { + console.log(_isa_model) + _isa_model['INVESTIGATION CONTACTS']["Comment[Person ID]"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Email"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Roles"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Mid Name"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Affiliation"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Address"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person First Name"] = [] + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"] = [] + _persons_in_investigation.forEach(person => { + _isa_model['INVESTIGATION CONTACTS']["Comment[Person ID]"].push(person['Person ID']) + + console.log(person['Person name'].split(" ")[1]) + //improve the management of Person name + // test lenght + if (person['Person name'].split(" ").lenght === 3) { + _isa_model['INVESTIGATION CONTACTS']["Investigation Person First Name"].push(person['Person name'].split(" ")[0]) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Mid Name"].push(person['Person name'].split(" ")[1]) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"].push(person['Person name'].split(" ")[2]) + } + else if (person['Person name'].split(" ").lenght === 2) { + _isa_model['INVESTIGATION CONTACTS']["Investigation Person First Name"].push(person['Person name'].split(" ")[0]) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Mid Name"].push("") + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"].push(person['Person name'].split(" ")[1]) + + } + else { + _isa_model['INVESTIGATION CONTACTS']["Investigation Person First Name"].push(person['Person name'].split(" ")[0]) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Mid Name"].push("") + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"].push("") + + } + /* if (person['Person name'].split(" ")[1]!==undefined){ + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"].push(person['Person name'].split(" ")[1]) + } + else{ + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"].push("") + } */ + console.log(_isa_model['INVESTIGATION CONTACTS']["Investigation Person Last Name"]) + + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Email"].push(person['Person email']) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Roles"].push(person['Person role']) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Affiliation"].push(person['Person affiliation']) + _isa_model['INVESTIGATION CONTACTS']["Investigation Person Address"].push(person['Person affiliation']) + }) + return _isa_model + } + public async saveISA(model_data, submodels, model_type: string, collection_name = 'data', model_id = "", isa_model, model) { + ////console.log(submodels) var model_key = model_id.split("/")[1]; var paths = { 'filepath': [], 'data': [], 'parent_id': [] } //var root_id = collection_name + '/' + model_key //paths = this.build_path(root_id, submodels, selected_format) let zipFile: JSZip = new JSZip(); //build isa model root - //console.log("entering isa conversion") - var return_data = { "Investigation": {}, "Study": [], "Trait Definition File": [], "Event": {}, "Assay": [] } + ////console.log("entering isa conversion") + var return_data = { "Investigation": {}, "Study": [], "Trait Definition File": [], "Event": [], "Assay": [] } //Always an investigation - var filename = "i_investigation_" + model_key + ".txt" + var filename = "i_" + model_key + ".txt" var parent_id = "" var parent_data = {} var study_data = {} var study_id = "" var study_unique_id = "" - + var persons_in_investigation = [] //console.log(model_data) - //console.log(model) - //console.log(isa_model) - return_data = this.build_isa_model2(model_data, model, isa_model, return_data, model_type, filename, parent_id, parent_data) - //console.log(submodels) + persons_in_investigation = await this.userService.get_persons(model_data['_key'], 'investigations').toPromise() + console.warn(persons_in_investigation) + isa_model = this.build_investigation_contacts(persons_in_investigation, isa_model) + var persons_in_study = await this.globalService.get_studies_and_persons(model_data['_key']).toPromise() + let persons = persons_in_study.filter(element => element.e['_from'].includes("studies")).filter(element2 => element2.v['_id'].includes('persons')).map(res => { + var rObj = {}; + rObj['model_id'] = res.e['_from']; + rObj['vertice'] = res.v; + return rObj; + }) + console.warn(persons) + + return_data = this.build_isa_model2(model_data, model, isa_model, return_data, model_type, filename, parent_id, parent_data, {}) + ////console.log(submodels) + //let persons_in_study= this.get_studies_person(submodels) + submodels['models_data'].forEach( submodel => { - //console.log(submodel) + //console.warn(submodel) + console.warn("parent id: ", submodel["e"]["_from"]) + console.warn("model id: ", submodel["v"]["_id"]) var filename = "" parent_id = submodel["e"]["_from"] if (submodel["v"]["_id"].split('/')[0] === "studies") { - //console.log(submodel["v"]["_id"]) + //submodel["isa_model"]=this.build_study_contacts(persons ,submodel["isa_model"], submodel["v"]["_id"]) + + ////console.log(submodel["v"]["_id"]) + console.log(submodel["isa_model"]) model_type = "study" filename = filename parent_data = model_data study_data = submodel study_id = submodel["v"]["_id"] study_unique_id = submodel["v"]["Study unique ID"] - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data) + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, { persons: persons, edge: {} }) } else if (submodel["v"]["_id"].split('/')[0] === "observation_units") { - ////console.log(submodel["v"]["_id"]) + //////console.log(submodel["v"]["_id"]) //model_type=submodel["v"]["_id"].split('/')[0].slice(0, -1) //filename="s_study_"+submodel["v"]["_id"].split('/')[1]+".txt" parent_data = submodel // return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id) } else if (submodel["v"]["_id"].split('/')[0] === "biological_materials") { - //console.log(submodel["v"]["_id"]) + ////console.log(submodel["v"]["_id"]) model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) - filename = "s_study_" + study_id.split('/')[1] + ".txt" + filename = "s_" + study_id.split('/')[1] + ".txt" if (parent_id.includes("observation_units")) { - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, submodel["e"]) + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, { edge: submodel["e"], persons: [] }) // Here write the environment variable ???? } } - else if (submodel["v"]["_id"].split('/')[0]==="experimental_factors"){ - model_type=submodel["v"]["_id"].split('/')[0].slice(0, -1) - filename="s_study_"+study_id.split('/')[1]+".txt" + else if (submodel["v"]["_id"].split('/')[0] === "experimental_factors") { + model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) + filename = "s_" + study_id.split('/')[1] + ".txt" - if (!parent_id.includes("observation_units")){ - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, study_unique_id, study_data) + if (!parent_id.includes("observation_units")) { + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, study_unique_id, study_data, {}) } } - else if (submodel["v"]["_id"].split('/')[0]==="samples"){ - model_type=submodel["v"]["_id"].split('/')[0].slice(0, -1) - filename="a_assay_"+study_id.split('/')[1]+".txt" - if (parent_id.includes("observation_units")){ - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, submodel["e"]) + else if (submodel["v"]["_id"].split('/')[0] === "samples") { + model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) + filename = "a_" + study_id.split('/')[1] + "_phenotyping.txt" + if (parent_id.includes("observation_units")) { + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, { edge: submodel["e"], persons: [] }) } } else if (submodel["v"]["_id"].split('/')[0] === "observed_variables") { - ////console.log(submodel["v"]["_id"]) + //////console.log(submodel["v"]["_id"]) model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) filename = "tdf_" + study_id.split('/')[1] + ".txt" - + if (!parent_id.includes("observation_units")) { parent_data = submodel - //console.log(submodel) - //console.log(return_data) - //console.log(parent_id) - //console.log(parent_data) - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data) + ////console.log(submodel) + ////console.log(return_data) + ////console.log(parent_id) + ////console.log(parent_data) + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, {}) + } + else{ + console.log(model_data) } // else { // parent_data = model_data - // //console.log(submodel) - // //console.log(return_data) - // //console.log(parent_id) - // //console.log(parent_data) + // ////console.log(submodel) + // ////console.log(return_data) + // ////console.log(parent_id) + // ////console.log(parent_data) // return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data) // } } else { - ////console.log(submodel["v"]["_id"]) + //////console.log(submodel["v"]["_id"]) } } ) submodels['models_data'].forEach( submodel => { parent_id = submodel["e"]["_from"] - ////console.log(parent_id) + //////console.log(parent_id) if (submodel["v"]["_id"].split('/')[0] === "studies") { study_data = submodel study_id = submodel["v"]["_id"] study_unique_id = submodel["v"]["Study unique ID"] - //console.log(study_id) + ////console.log(study_id) } else if (submodel["v"]["_id"].split('/')[0] === "environments") { - //console.log(study_id) + ////console.log(study_id) + model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) + filename = "s_" + study_id.split('/')[1] + ".txt" + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, study_unique_id, study_data, {}) + + } + else if (submodel["v"]["_id"].split('/')[0] === "events") { + ////console.log(study_id) model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) - filename = "s_study_" + study_id.split('/')[1] + ".txt" - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, study_unique_id, study_data) + filename = "events.tsv" + + //filename = "e_" + study_id.split('/')[1] + ".txt" + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, study_unique_id, study_data, {}) } else if (submodel["v"]["_id"].split('/')[0] === "observation_units") { parent_data = submodel } - else if (submodel["v"]["_id"].split('/')[0]==="experimental_factors"){ - model_type=submodel["v"]["_id"].split('/')[0].slice(0, -1) - filename="s_study_"+study_id.split('/')[1]+".txt" - if (parent_id.includes("observation_units")){ - return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data) + else if (submodel["v"]["_id"].split('/')[0] === "experimental_factors") { + model_type = submodel["v"]["_id"].split('/')[0].slice(0, -1) + filename = "s_" + study_id.split('/')[1] + ".txt" + if (parent_id.includes("observation_units")) { + return_data = this.build_isa_model2(submodel["v"], submodel["model"], submodel["isa_model"], return_data, model_type, filename, parent_id, parent_data, {}) } } @@ -548,17 +657,17 @@ export class FileService { // } else { - ////console.log(submodel["v"]["_id"]) + //////console.log(submodel["v"]["_id"]) } } ) - //console.log(return_data) + console.log(return_data) var elements = Object.keys(return_data); for (var j = 0; j < elements.length; j++) { if (elements[j] == 'Investigation') { let tsvData = this.ConvertInvestigationModelTo(return_data[elements[j]], "\t"); let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); - let path = 'ISA/' + "i_" + model_id.replace('/', '_') + '.txt' + let path = 'ISA/' + "i_" + model_id.split('/')[1] + '.txt' zipFile.file(path, blob_tsv); } else if (elements[j] == 'Study') { @@ -589,7 +698,13 @@ export class FileService { } } else { - + console.log(return_data[elements[j]]) + for (var elem in return_data[elements[j]]) { + let tsvData = this.ConvertEventModelTo(return_data[elements[j]][elem]["event_data"], "\t"); + let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); + let path = 'ISA/' + return_data[elements[j]][elem]["filename"] + zipFile.file(path, blob_tsv); + } } } @@ -598,41 +713,67 @@ export class FileService { zipFile = this.build_zip(paths, zipFile) zipFile.generateAsync({ type: "blob" }).then(function (blob) { saveAs(blob, dir_root_id + ".zip"); }); } - public add_multiple_model(fileReader: FileReader, parent_id:string) { + public add_multiple_model(fileReader: FileReader, parent_id: string) { fileReader.onload = function (e) { var archive = new JSZip().loadAsync(e.target['result']).then(function (zip) { var files = zip['files']; Object.keys(zip.files).forEach(function (filename) { - ////console.log(zip.files) - ////console.log(zip.files[filename]['dir']) + //////console.log(zip.files) + //////console.log(zip.files[filename]['dir']) if (!zip.files[filename]['dir']) { zip.files[filename].async('string').then(function (fileData) { - ////console.log(filename) - ////console.log(fileData) // These are your file contents + //////console.log(filename) + //////console.log(fileData) // These are your file contents }) } }) zip.forEach(function (relativePath, zipEntry) { - ////console.log(zipEntry.name) - ////console.log(zipEntry.dir) - //////console.log(zipEntry[relativePath]['dir']) - ////console.log(relativePath) + //////console.log(zipEntry.name) + //////console.log(zipEntry.dir) + ////////console.log(zipEntry[relativePath]['dir']) + //////console.log(relativePath) //for each filepath build the corresponding hierarchy in user tree }); }); } } - public build_isa_model2(data, model, isa_model, return_data, model_type, filename, parent_id, parent_data, edge={}) { + private handleError(error: HttpErrorResponse) { + if (error.status === 0) { + // A client-side or network error occurred. Handle it accordingly. + console.error('An error occurred:', error.error); + } else { + // The backend returned an unsuccessful response code. + // The response body may contain clues as to what went wrong. + console.error( + `Backend returned code ${error.status}, body was: `, error.error); + } + // Return an observable with a user-facing error message. + + return throwError(() => new Error('Something bad happened; please try again later.')) + + } + public async get_persons(investigation_key) { + let persons: PersonInterface[] = await this.httpClient.get(this.APIUrl + "get_persons/" + investigation_key).pipe(catchError(this.handleError)).toPromise() + console.log(persons) + return persons + } + public build_isa_model2(data, model, isa_model, return_data, model_type, filename, parent_id, parent_data, { edge = {}, persons = [] }: { edge?: {}; persons?: {}[] }) { var environment_obj = {} + var event_obj = {} var keys = Object.keys(data); + console.log(model_type) + console.log(data['_id']) + console.log(isa_model) if (model_type === "investigation") { var isa_file = "Investigation" //add the model if (Object.keys(return_data[isa_file]).length === 0) { return_data[isa_file] = isa_model } - //console.log("-----------building isa ", model_type) + // Build investigation contact section + // need to get person related to this investigation data['_id'] + ////console.log("-----------building isa ", model_type) for (var i = 0; i < keys.length; i++) { if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); @@ -667,26 +808,75 @@ export class FileService { } else if (model_type === "study") { var isa_file = "Investigation" - //console.log("-----------building isa ", model_type) + var study_contact_section = 'STUDY CONTACTS' + ////console.log("-----------building isa ", model_type) //add the model - + //console.log(return_data[isa_file]) + //console.log(parent_id) var investigation_isa_sections = Object.keys(return_data[isa_file]) for (var i = 0; i < investigation_isa_sections.length; i++) { + if (investigation_isa_sections[i].includes("STUDY CONTACTS")) { + //console.log(return_data[isa_file][investigation_isa_sections[i]]) + //console.log(persons) + if (persons.length > 0) { + let current_person = persons.filter(person => person['model_id'] === data['_id'])[0]['vertice'] + //return_data[isa_file][investigation_isa_sections[i]]["Study Person First Name"].push(current_person['Person name'].split(" ")[0]) + if (!return_data[isa_file][investigation_isa_sections[i]]["Comment[Person ID]"]){ + return_data[isa_file][investigation_isa_sections[i]]["Comment[Person ID]"]=[] + } + return_data[isa_file][investigation_isa_sections[i]]["Comment[Person ID]"].push([current_person['Person ID']]) + if (current_person['Person name'].split(" ").lenght === 3) { + return_data[isa_file][investigation_isa_sections[i]]["Study Person First Name"].push([current_person['Person name'].split(" ")[0]]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Mid Initials"].push([current_person['Person name'].split(" ")[1]]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Last Name"].push([current_person['Person name'].split(" ")[2]]) + } + else if (current_person['Person name'].split(" ").lenght === 2) { + return_data[isa_file][investigation_isa_sections[i]]["Study Person First Name"].push([current_person['Person name'].split(" ")[0]]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Mid Initials"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Last Name"].push([current_person['Person name'].split(" ")[1]]) - if (investigation_isa_sections[i].includes("STUDY")) { - ////console.log(return_data[isa_file][investigation_isa_sections[i]]) + } + else { + return_data[isa_file][investigation_isa_sections[i]]["Study Person First Name"].push([current_person['Person name'].split(" ")[0]]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Mid Initials"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Last Name"].push([""]) + + } + /* if (current_person['Person name'].split(" ")[1]!==undefined){ + return_data[isa_file][investigation_isa_sections[i]]["Study Person Last Name"].push(current_person['Person name'].split(" ")[1]) + + } + else{ + return_data[isa_file][investigation_isa_sections[i]]["Study Person Last Name"].push("") + + } */ + + return_data[isa_file][investigation_isa_sections[i]]["Study Person Email"].push([current_person['Person email']]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Roles"].push([current_person['Person role']]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Affiliation"].push([current_person['Person affiliation']]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Address"].push([current_person['Person affiliation']]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Phone"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Roles"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Fax"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Roles Term Accession Number"].push([""]) + return_data[isa_file][investigation_isa_sections[i]]["Study Person Roles Term Source REF"].push([""]) + } + } + if (investigation_isa_sections[i].includes("STUDY") && !investigation_isa_sections[i].includes("STUDY CONTACTS")) { + //////console.log(return_data[isa_file][investigation_isa_sections[i]]) var study_isa_keys = Object.keys(return_data[isa_file][investigation_isa_sections[i]]) for (var j = 0; j < study_isa_keys.length; j++) { return_data[isa_file][investigation_isa_sections[i]][study_isa_keys[j]].push([]) - ////console.log(return_data[isa_file][investigation_isa_sections[i]]) + + } } } - ////console.log(return_data[isa_file]) + //console.log(return_data[isa_file]) //return_data[isa_file]["STUDY"]["Study File Name"].push("") - + for (var i = 0; i < keys.length; i++) { if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); @@ -697,15 +887,15 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - ////console.log(isa_field) + //////console.log(isa_field) - //console.log("----------------------write field ", isa_field, " in section ", isa_section, " for ", isa_file) + ////console.log("----------------------write field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][isa_section][isa_field]) { - ////console.log("write field ", isa_field, " in section ", isa_section, " for ", isa_file) + //////console.log("write field ", isa_field, " in section ", isa_section, " for ", isa_file) var study_index = return_data[isa_file][isa_section][isa_field].length - 1 if ((isa_field.includes("Type")) && (!isa_field.includes("Comment"))) { data[keys[i]].split("/").forEach(element => { - ////console.log("studies index",study_index) + //////console.log("studies index",study_index) return_data[isa_file][isa_section][isa_field][study_index].push(element) let tmp_isa_field: string = isa_field + ' Term Accession Number' return_data[isa_file][isa_section][tmp_isa_field][study_index].push(element) @@ -714,14 +904,14 @@ export class FileService { }); } else { - ////console.log("study index",study_index) - ////console.log("study index",return_data[isa_file][isa_section][isa_field]) + //////console.log("study index",study_index) + //////console.log("study index",return_data[isa_file][isa_section][isa_field]) return_data[isa_file][isa_section][isa_field][study_index].push(data[keys[i]]) - ////console.log("study index",return_data[isa_file][isa_section][isa_field]) + //////console.log("study index",return_data[isa_file][isa_section][isa_field]) } } else { - ////console.log("studys index",study_index) + //////console.log("studys index",study_index) return_data[isa_file][isa_section][isa_field] = [] return_data[isa_file][isa_section][isa_field].push([data[keys[i]]]) //return_data[isa_file][isa_section][isa_field][study_index] = [data[keys[i]]] @@ -731,16 +921,16 @@ export class FileService { } else if (model_type === "biological_material") { var factor_obj = {} - //console.log("#############################################################model type", model_type) - - //console.log("----data", data) - //console.log("----parent id", parent_id) - //console.log("----return data", return_data) - //console.log("----parent data", parent_data) - //console.log("----edge data", edge) - //console.log("-----------building isa ", model_type) + ////console.log("#############################################################model type", model_type) + + ////console.log("----data", data) + ////console.log("----parent id", parent_id) + ////console.log("----return data", return_data) + ////console.log("----parent data", parent_data) + ////console.log("----edge data", edge) + ////console.log("-----------building isa ", model_type) var isa_file = "Study" - + var parent_model = parent_data["model"]; var index = 0 @@ -769,31 +959,31 @@ export class FileService { } } if (!already_exist) { - ////console.log('----------------not exist') + //////console.log('----------------not exist') //Add in investigation file if (!return_data['Investigation']['STUDY']['Study File Name'][index].includes(filename)) { return_data['Investigation']['STUDY']['Study File Name'][index].push(filename) } - // //console.log(parent_data['v']["obsUUID"]) - ////console.log(data["obsUUID"]) + // ////console.log(parent_data['v']["obsUUID"]) + //////console.log(data["obsUUID"]) //var parent_index = parent_data['v']["obsUUID"].indexOf(data["obsUUID"]) - // //console.log(data) - // //console.log(parent_data) - // //console.log(parent_index) - // //console.log(keys) - var bm_data=[] - bm_data=edge['biological_materials'] + // ////console.log(data) + // ////console.log(parent_data) + // ////console.log(parent_index) + // ////console.log(keys) + var bm_data = [] + bm_data = edge['biological_materials'] for (var bm_index = 0; bm_index < bm_data.length; bm_index++) { var data_index = data["Material source ID (Holding institute/stock centre, accession)"].indexOf(bm_data[bm_index]["materialId"]) - var bm_data_index=data["Biological material ID"][data_index].indexOf(bm_data[bm_index]["biologicalMaterialId"]) + var bm_data_index = data["Biological material ID"][data_index].indexOf(bm_data[bm_index]["biologicalMaterialId"]) var parent_index = parent_data['v']["obsUUID"].indexOf(bm_data[bm_index]["obsUUID"]) - // //console.log(bm_data[bm_index]) - // //console.log(data_index) - // //console.log(bm_data_index) - // //console.log(data["Material source ID (Holding institute/stock centre, accession)"][data_index]) - // //console.log(parent_index) - // //console.log(parent_data['v']["obsUUID"][parent_index]) - // //console.log(data["Biological material ID"][data_index][bm_data_index]) + // ////console.log(bm_data[bm_index]) + // ////console.log(data_index) + // ////console.log(bm_data_index) + // ////console.log(data["Material source ID (Holding institute/stock centre, accession)"][data_index]) + // ////console.log(parent_index) + // ////console.log(parent_data['v']["obsUUID"][parent_index]) + // ////console.log(data["Biological material ID"][data_index][bm_data_index]) for (var i = 0; i < keys.length; i++) { if (keys[i].startsWith("_") || keys[i].startsWith("Definition") || keys[i].includes("UUID") || keys[i].startsWith("replication")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); @@ -804,25 +994,25 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - //console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) - //console.log(return_data[isa_file][index]["study_data"]) + ////console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) + ////console.log(return_data[isa_file][index]["study_data"]) if (return_data[isa_file][index]["study_data"][isa_field]) { if (return_data[isa_file][index]["study_data"][isa_field]["data"]) { var data2; - if (keys[i].includes("Material") || keys[i].includes("Infraspecific") ){ - data2=data[keys[i]][data_index] - + if (keys[i].includes("Material") || keys[i].includes("Infraspecific")) { + data2 = data[keys[i]][data_index] + } - else if (keys[i].includes("Biological")){ - data2=data[keys[i]][data_index][bm_data_index] + else if (keys[i].includes("Biological")) { + data2 = data[keys[i]][data_index][bm_data_index] } - else{ - data2=data[keys[i]] + else { + data2 = data[keys[i]] } if (isa_field.includes("Characteristics")) { - // //console.log(keys[i]) - // //console.log(data2) + // ////console.log(keys[i]) + // ////console.log(data2) var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { @@ -830,12 +1020,12 @@ export class FileService { term_accession_number = data2 } let tmp_array = [data2, { "Term Source REF": term_source_ref }, { "Term Accession Number": term_accession_number }] - // //console.log(tmp_array) + // ////console.log(tmp_array) return_data[isa_file][index]["study_data"][isa_field]["data"].push(tmp_array) } else if (isa_field === "Factor Value[ ]") { environment_obj["value"] = data2 - // //console.log(environment_obj) + // ////console.log(environment_obj) let tmp_array = [environment_obj, { "Term Source REF": "" }, { "Term Accession Number": "" }] // return_data[isa_file][index]["study_data"][isa_field]["data"].push(tmp_array) } @@ -851,25 +1041,25 @@ export class FileService { } } var parent_keys = Object.keys(parent_data["v"]); - ////console.log(parent_keys) + //////console.log(parent_keys) for (var i = 0; i < parent_keys.length; i++) { if (parent_keys[i].startsWith("_") || parent_keys[i].startsWith("Definition") || parent_keys[i].includes("UUID")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { parent_keys.splice(i, 1); i--; } else { - // //console.log(parent_index) - // //console.log(parent_keys[i]) - // //console.log(parent_data["v"][parent_keys[i]][parent_index]) - // //console.log(parent_data["v"]) - // var is_ontology_key = this.is_ontology_key(parent_model, parent_keys[i][parent_index]) + // ////console.log(parent_index) + // ////console.log(parent_keys[i]) + // ////console.log(parent_data["v"][parent_keys[i]][parent_index]) + // ////console.log(parent_data["v"]) + // var is_ontology_key = this.is_ontology_key(parent_model, parent_keys[i][parent_index]) mapping_data = this.get_mapping_data_by_key(parent_model, parent_keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - //console.log("write observation unit field ", isa_field, " in section ", isa_section, " for ", isa_file) + ////console.log("write observation unit field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][index]["study_data"][isa_field]) { if (return_data[isa_file][index]["study_data"][isa_field]["data"]) { - + if (isa_field.includes("Characteristics")) { var term_source_ref = "" var term_accession_number = "" @@ -882,7 +1072,7 @@ export class FileService { } else if (isa_field === "Factor Value[ ]") { //environment_obj["value"]=parent_data["v"][parent_keys[i]] - ////console.log(environment_obj) + //////console.log(environment_obj) //let tmp_array = [environment_obj, { "Term Source REF":""}, { "Term Accession Number": "" }] // factor_obj["factor"]="" // factor_obj["value"]= "" @@ -897,31 +1087,41 @@ export class FileService { else { return_data[isa_file][index]["study_data"][isa_field] = { "data": [parent_data["v"][parent_keys[i]][parent_index]] } } - + } } } - //console.log(return_data) + ////console.log(return_data) + - } } else if (model_type === "sample") { + var isa_file = "Investigation" + //console.log(parent_id) + //add SAmples in study protocol + for (var i = 0; i < return_data[isa_file]["STUDY"]["Study Identifier"].length; i++) { + if (return_data[isa_file]["STUDY"]["Study Identifier"][i][0] === parent_id) { + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Name"][i].push('Sampling') + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Type"][i].push('Sampling') + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i].push(data["Collection date"][0]+";"+data['Sample description'][0]) + } + } var isa_file = "Assay" - //console.log("#############################################################model type", model_type) - - console.log("----data", data) - - //console.log("----parent id", parent_id) - //console.log("----return data", return_data) - //console.log("----parent data", parent_data) - //console.log("----edge data", edge) - //console.log("-----------building isa ", model_type) - - + ////console.log("#############################################################model type", model_type) + + //console.log("----data", data) + + ////console.log("----parent id", parent_id) + ////console.log("----return data", return_data) + ////console.log("----parent data", parent_data) + ////console.log("----edge data", edge) + ////console.log("-----------building isa ", model_type) + + var parent_keys = Object.keys(parent_data["v"]); var parent_model = parent_data["model"]; var index = 0 @@ -944,27 +1144,29 @@ export class FileService { } } var already_exist = false - for (var i = 0; i < return_data['Assay'][index]["assay_data"]['Sample Name']["data"].length; i++) { - if ((return_data['Assay'][index]["assay_data"]['Sample Name']["data"][i] === parent_data['v']['Observation unit ID']) && (return_data['Assay'][index]["assay_data"]['Extract Name']["data"][i] === data['Sample ID'])) { + for (var i = 0; i < return_data[isa_file][index]["assay_data"]['Sample Name']["data"].length; i++) { + if ((return_data[isa_file][index]["assay_data"]['Sample Name']["data"][i] === parent_data['v']['Observation unit ID']) && (return_data['Assay'][index]["assay_data"]['Extract Name']["data"][i] === data['Sample ID'])) { already_exist = true } } - console.warn('##################ALREADY EXIST : ', already_exist) + //console.warn('##################ALREADY EXIST : ', already_exist) if (!already_exist) { if (!return_data['Investigation']['STUDY ASSAYS']['Study Assay File Name'][index].includes(filename)) { return_data['Investigation']['STUDY ASSAYS']['Study Assay File Name'][index].push(filename) + return_data['Investigation']['STUDY ASSAYS']['Study Assay Measurement Type'][index].push("phenotyping") + return_data['Investigation']['STUDY ASSAYS']['Study Assay Technology Type'][index].push(parent_data['v']['Observation unit type'][0] + " level analysis") } - var sample_data=edge['samples'] - /// NEW CODE TO TEST - for (var sample_index = 0; sample_index < sample_data.length; sample_index++) { + var sample_data = edge['samples'] + /// NEW CODE TO TESTs + for (var sample_index = 0; sample_index < sample_data.length; sample_index++) { var parent_index = parent_data['v']["obsUUID"].indexOf(sample_data[sample_index]["obsUUID"]) //get index of sample obsUUID in parent_data['v'] i.e observation unit data - console.log(parent_index) + //console.log(parent_index) return_data['Assay'][index]["assay_data"]['Sample Name']["data"].push(parent_data['v']['Observation unit ID'][parent_index]) - - console.log(sample_data[sample_index]) + + //console.log(sample_data[sample_index]) for (var i = 0; i < keys.length; i++) { if (keys[i].startsWith("_") || keys[i].startsWith("Definition") || keys[i].includes("UUID")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); @@ -975,27 +1177,27 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) + //console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][index]["assay_data"][isa_field]) { - console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) + //console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) if (return_data[isa_file][index]["assay_data"][isa_field]["data"]) { - console.log("----------------------first if ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ,"and key ", keys[i]) + //console.log("----------------------first if ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ,"and key ", keys[i]) if (isa_field.includes("Characteristics")) { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } let tmp_array = [data[keys[i]][sample_index], { "Term Source REF": term_source_ref }, { "Term Accession Number": term_accession_number }] return_data[isa_file][index]["assay_data"][isa_field]["data"].push(tmp_array) } - + else { - /* console.log(data[sample_index]) - console.log(data[keys[i]][sample_index]) */ + /* //console.log(data[sample_index]) + //console.log(data[keys[i]][sample_index]) */ return_data[isa_file][index]["assay_data"][isa_field]["data"].push(data[keys[i]][sample_index]) } } @@ -1004,14 +1206,14 @@ export class FileService { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } let tmp_array = [data[keys[i]][sample_index], { "Term Source REF": term_source_ref }, { "Term Accession Number": term_accession_number }] return_data[isa_file][index]["assay_data"][isa_field]["data"] = [tmp_array] } - else{ + else { return_data[isa_file][index]["assay_data"][isa_field]["data"] = [data[keys[i]][sample_index]] } } @@ -1021,20 +1223,20 @@ export class FileService { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } let tmp_array = [data[keys[i]][sample_index], { "Term Source REF": term_source_ref }, { "Term Accession Number": term_accession_number }] return_data[isa_file][index]["assay_data"][isa_field] = { "data": [tmp_array] } } - else{ + else { return_data[isa_file][index]["assay_data"][isa_field] = { "data": [data[keys[i]][sample_index]] } } } } - + } } /* for (var sample_index = 0; sample_index < sample_data.length; sample_index++) { @@ -1048,17 +1250,17 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) + //console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][index]["assay_data"][isa_field]) { - console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) + //console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) if (return_data[isa_file][index]["assay_data"][isa_field]["data"]) { - console.log("----------------------first if ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) + //console.log("----------------------first if ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) if (isa_field.includes("Characteristics")) { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } @@ -1076,7 +1278,7 @@ export class FileService { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } @@ -1093,7 +1295,7 @@ export class FileService { var term_source_ref = "" var term_accession_number = "" if (is_ontology_key) { - console.log(data[keys[i]][sample_index]) + //console.log(data[keys[i]][sample_index]) term_source_ref = data[keys[i]][sample_index].split(":")[0] term_accession_number = data[keys[i]][sample_index] } @@ -1108,9 +1310,9 @@ export class FileService { } } } */ - - /// OLD CODE TO TEST - /* console.log(edge['samples']) + + /// OLD CODE TO TEST + /* //console.log(edge['samples']) for (var i = 0; i < keys.length; i++) { if (keys[i].startsWith("_") || keys[i].startsWith("Definition") || keys[i].includes("UUID")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); @@ -1121,9 +1323,9 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - //console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) + ////console.log("----------------------get key ", keys[i], " write field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][index]["assay_data"][isa_field]) { - //console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) + ////console.log("----------------------assay data ", return_data[isa_file][index]["assay_data"][isa_field], "for field ",isa_field ) if (return_data[isa_file][index]["assay_data"][isa_field]["data"]) { if (isa_field.includes("Characteristics")) { @@ -1180,23 +1382,26 @@ export class FileService { } else if (model_type === "experimental_factor") { //Investigation isa file part - //console.log("#############################################################model type", model_type) - //console.log("----data", data) + ////console.log("#############################################################model type", model_type) + ////console.log("----data", data) //in this case it is study id - //console.log("----parent id", parent_id) - //console.log("----return data", return_data) + console.log("----parent id", parent_id) + ////console.log("----return data", return_data) //in this case it is observation unit data - //console.log("----parent data", parent_data) - //console.log("----edge data", edge) - //console.log("-----------building isa ", model_type) + ////console.log("----parent data", parent_data) + ////console.log("----edge data", edge) + ////console.log("-----------building isa ", model_type) - if (parent_data['v']['_id'].includes("studies")){ + if (parent_data['v']['_id'].includes("studies")) { + //write investigation file var isa_file = "Investigation" for (var i = 0; i < return_data[isa_file]["STUDY"]["Study Identifier"].length; i++) { - //console.log(return_data[isa_file]["STUDY"]["Study Identifier"]) + ////console.log(return_data[isa_file]["STUDY"]["Study Identifier"]) if (return_data[isa_file]["STUDY"]["Study Identifier"][i][0] === parent_id) { return_data[isa_file]["STUDY FACTORS"]["Study Factor Name"][i].push(data["Experimental Factor type"]) + return_data[isa_file]["STUDY FACTORS"]["Study Factor Type"][i].push(data["Experimental Factor type"]) return_data[isa_file]["STUDY FACTORS"]["Study Factor Type Term Accession Number"][i].push(data["Experimental Factor accession number"]) + return_data[isa_file]["STUDY FACTORS"]["Study Factor Type Term Source REF"][i].push(data["Experimental Factor accession number"].split(':')[0]) if (return_data[isa_file]["STUDY FACTORS"]["Comment[Study Factor Description]"]) { if (return_data[isa_file]["STUDY FACTORS"]["Comment[Study Factor Description]"].length === 0) { for (var j = 0; j < return_data[isa_file]["STUDY"]["Study Identifier"].length; j++) { @@ -1211,8 +1416,6 @@ export class FileService { return_data[isa_file]["STUDY FACTORS"]["Comment[Study Factor Description]"].push([]) } return_data[isa_file]["STUDY FACTORS"]["Comment[Study Factor Description]"][i].push(data["Experimental Factor description"]) - - } if (return_data[isa_file]["STUDY FACTORS"]["Comment[Study Factor Values]"]) { @@ -1233,10 +1436,9 @@ export class FileService { } } } - else{ + else { //Write Study isa part isa_file = "Study" - var parent_keys = Object.keys(parent_data["v"]); var parent_model = parent_data["model"]; var index = 0 @@ -1246,47 +1448,39 @@ export class FileService { if (return_data[isa_file][i]["filename"] === filename) { found = true index = i - //console.log('found ', filename) - //console.log(return_data[isa_file][i]["study_data"]) - //console.log(return_data[isa_file][i]["study_data"]["Factor Value[ ]"]["data"]) + console.log('found ', filename) + console.log(return_data[isa_file][i]["study_data"]) + console.log(return_data[isa_file][i]["study_data"]["Factor Value[ ]"]["data"]) for (var j = 0; j < return_data[isa_file][i]["study_data"]["Characteristics[Material Source ID]"]['data'].length; j++) { - //console.log(return_data['Study'][i]["study_data"]['Sample Name']["data"][j]) - //console.log(parent_data['v']['Observation unit ID']) - //console.log(parent_data['v']) + ////console.log(return_data['Study'][i]["study_data"]['Sample Name']["data"][j]) + ////console.log(parent_data['v']['Observation unit ID']) + ////console.log(parent_data['v']) var parent_index = parent_data['v']['Observation unit ID'].indexOf(return_data['Study'][i]["study_data"]['Sample Name']["data"][j]) - //console.log(parent_data['v']['Observation unit ID'][parent_index]) + ////console.log(parent_data['v']['Observation unit ID'][parent_index]) if (return_data['Study'][i]["study_data"]['Sample Name']["data"][j] === parent_data['v']['Observation unit ID'][parent_index]) { //console.log(parent_data["v"]["Observation Unit factor value"][parent_index]) - var factor_obj={} + var factor_obj = {} factor_obj["factor"] = data["Experimental Factor type"] factor_obj["value"] = parent_data["v"]["Observation Unit factor value"][parent_index] let tmp_array = [factor_obj, { "Term Source REF": data["Experimental Factor accession number"].split(":")[0] }, { "Term Accession Number": data["Experimental Factor accession number"] }] - return_data[isa_file][i]["study_data"]["Factor Value[ ]"]["data"][j] = tmp_array + return_data[isa_file][i]["study_data"]["Factor Value[ ]"]["data"][j].push(tmp_array) } // else{ // if (!return_data['Study'][i]["study_data"]['Sample Name']["data"][j]){ // factor_obj["factor"]="" // factor_obj["value"]= "" // let tmp_array = [factor_obj, { "Term Source REF":"", { "Term Accession Number": "" }] - // return_data[isa_file][i]["study_data"]["Factor Value[ ]"]["data"].push(tmp_array) // } - - // } - } - } } } } - - - } else if (model_type === "observed_variable") { - //console.log("#############################################################model type", model_type) + ////console.log("#############################################################model type", model_type) var isa_file = "Trait Definition File" var parent_keys = Object.keys(parent_data["v"]); @@ -1329,7 +1523,7 @@ export class FileService { var mapping_data = this.get_mapping_data_by_key(model, keys[i]) var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] var isa_field: string = mapping_data["ISA-Tab Field"] - //console.log("write field ", isa_field, " in section ", isa_section, " for ", isa_file) + ////console.log("write field ", isa_field, " in section ", isa_section, " for ", isa_file) if (return_data[isa_file][index]["tdf_data"][isa_field]) { return_data[isa_file][index]["tdf_data"][isa_field].push(data[keys[i]]) } @@ -1344,22 +1538,44 @@ export class FileService { else if (model_type === "observation_unit") { } else if (model_type === "environment") { + + console.log(data) + console.log(data["Environment parameter"]) + console.log(parent_id) var isa_file = "Investigation" + console.log(return_data[isa_file]["STUDY PROTOCOLS"]) + console.log(return_data[isa_file]["STUDY"]) + console.log(return_data[isa_file]["STUDY"]["Study Identifier"]) + console.log(return_data[isa_file]["STUDY"]["Study Identifier"][0]) for (var i = 0; i < return_data[isa_file]["STUDY"]["Study Identifier"].length; i++) { - if (return_data[isa_file]["STUDY"]["Study Identifier"][i] === parent_id) { - return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i].push(data["Environment parameter"]) + if (return_data[isa_file]["STUDY"]["Study Identifier"][i][0] === parent_id) { + console.log(data["Environment parameter"]) + if (!return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Name"][i].includes('Growth')) { + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Name"][i].push('Growth') + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i].push(data["Environment parameter"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Accession Number"][i].push(data["Environment parameter accession number"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Source REF"][i].push(data["Environment parameter accession number"].split(":")[0]) + } + else { + //get Growth index, usually 0 + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i][0] = return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i][0] + ";" + (data["Environment parameter"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Accession Number"][i][0] = return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Accession Number"][i][0] + ";" + (data["Environment parameter accession number"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Source REF"][i][0] = return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Source REF"][i][0] + ";" + (data["Environment parameter accession number"].split(":")[0]) + } + + } } //var study_index=return_data[isa_file]["STUDY"]["Study Identifier"].length -1 environment_obj["parameter"] = data["Environment parameter"] environment_obj["value"] = data["Environment parameter value"] - let tmp_array = [environment_obj, { "Term Source REF": "" }, { "Term Accession Number": "" }] + let tmp_array = [environment_obj, { "Term Source REF": data["Environment parameter accession number"].split(':')[0] }, { "Term Accession Number": data["Environment parameter accession number"] }] isa_file = "Study" - //console.log(parent_data) + ////console.log(parent_data) var parent_keys = Object.keys(parent_data["v"]); var parent_model = parent_data["model"]; var index = 0 @@ -1369,8 +1585,8 @@ export class FileService { if (return_data[isa_file][i]["filename"] === filename) { found = true index = i - //console.log('found ', filename) - //console.log(return_data[isa_file][i]["study_data"]) + ////console.log('found ', filename) + ////console.log(return_data[isa_file][i]["study_data"]) for (var j = 0; j < return_data[isa_file][i]["study_data"]["Characteristics[Material Source ID]"]['data'].length; j++) { return_data[isa_file][i]["study_data"]["Parameter Value[ ]"]["data"].push(tmp_array) } @@ -1426,21 +1642,100 @@ export class FileService { // } } else if (model_type === "event") { + /* console.log(data) + console.log(data["Event type"]) + console.log(parent_id) */ + var isa_file = "Investigation" + /* console.log(return_data[isa_file]["STUDY PROTOCOLS"]) + console.log(return_data[isa_file]["STUDY"]) + console.log(return_data[isa_file]["STUDY"]["Study Identifier"]) + console.log(return_data[isa_file]["STUDY"]["Study Identifier"][0]) */ + for (var i = 0; i < return_data[isa_file]["STUDY"]["Study Identifier"].length; i++) { + if (return_data[isa_file]["STUDY"]["Study Identifier"][i][0] === parent_id) { + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Name"][i].push('Event') + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name"][i].push(data["Event type"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Accession Number"][i].push(data["Event accession number"]) + return_data[isa_file]["STUDY PROTOCOLS"]["Study Protocol Parameters Name Term Source REF"][i].push(data["Event accession number"].split(":")[0]) + } + } + + var isa_file = "Event" + var parent_keys = Object.keys(parent_data["v"]); + var parent_model = parent_data["model"]; + var index = 0 + if (return_data[isa_file].length === 0) { + //if (Object.keys(return_data[isa_file]).length === 0){ + return_data[isa_file].push({ "filename": filename, "event_data": isa_model }) + return_data[isa_file][0]["event_data"]["Event Type"]["data"].push(data["Event type"]) + return_data[isa_file][0]["event_data"]["Event Description"]["data"].push(data["Event description"]) + return_data[isa_file][0]["event_data"]["Event Date*"]["data"].push(data["Event date"]) + return_data[isa_file][0]["event_data"]["Event Accession Number"]["data"].push(data["Event accession number"]) + return_data[isa_file][0]["event_data"]["Study ID*"]["data"].push(parent_id) + return_data[isa_file][0]["event_data"]["Observation Unit(s)"]["data"].push("NA") + + //return_data[isa_file]=isa_model + } + else { + var found: boolean = false + if (return_data[isa_file].length !== 0) { + for (var i = 0; i < return_data[isa_file].length; i++) { + if (return_data[isa_file][i]["filename"] === filename) { + found = true + index = i + return_data[isa_file][i]["event_data"]["Event Type"]["data"].push(data["Event type"]) + return_data[isa_file][i]["event_data"]["Event Description"]["data"].push(data["Event description"]) + return_data[isa_file][i]["event_data"]["Event Date*"]["data"].push(data["Event date"]) + return_data[isa_file][i]["event_data"]["Event Accession Number"]["data"].push(data["Event accession number"]) + return_data[isa_file][i]["event_data"]["Study ID*"]["data"].push(parent_id) + return_data[isa_file][i]["event_data"]["Observation Unit(s)"]["data"].push("NA") + + + + + + } + } + if (!found) { + return_data[isa_file].push({ "filename": filename, "event_data": isa_model }) + index = return_data[isa_file].length - 1 + return_data[isa_file][i]["event_data"]["Event Type"]["data"].push(data["Event type"]) + return_data[isa_file][i]["event_data"]["Event Description"]["data"].push(data["Event description"]) + return_data[isa_file][i]["event_data"]["Event Date*"]["data"].push(data["Event date"]) + return_data[isa_file][i]["event_data"]["Event Accession Number"]["data"].push(data["Event accession number"]) + return_data[isa_file][i]["event_data"]["Study ID*"]["data"].push(parent_id) + return_data[isa_file][i]["event_data"]["Observation Unit(s)"]["data"].push("NA") + } + } + + } + + //Write in return data in this isa model is not exists + + /* var already_exist = false + for (var i = 0; i < return_data[isa_file][index]["event_data"]['Event Accession Number']["data"].length; i++) { + if ((return_data[isa_file][index]["event_data"]['Sample Name']["data"][i] === parent_data['v']['Observation unit ID']) && (return_data['Assay'][index]["assay_data"]['Extract Name']["data"][i] === data['Sample ID'])) { + already_exist = true + } + + } */ + + //var study_index=return_data[isa_file]["STUDY"]["Study Identifier"].length -1 + /* event_obj["parameter"] = data["Event"] + event_obj["value"] = data["Event value"] + let tmp_array = [event_obj, { "Term Source REF": "" }, { "Term Accession Number": "" }] */ + } - else { - } - //console.log(return_data) + console.log(return_data) return return_data } public build_isa_model(data, model, isa_model, return_data, model_type) { - //console.log(return_data) + ////console.log(return_data) var keys = Object.keys(data); - //console.log("@@@@@@@@@@@@@@@@@@@@@@#=>", isa_model) - //console.log("@@@@@@@@@@@@@@@@@@@@@@#=>", model_type) + ////console.log("@@@@@@@@@@@@@@@@@@@@@@#=>", isa_model) + ////console.log("@@@@@@@@@@@@@@@@@@@@@@#=>", model_type) var environment_obj = {} var already_exist = false - if (model_type === "biological_material") { //vérifier qu'il existe un modéle dans return data pour la study qui contient ce matériel biologique for (var elem in return_data['Study']['Source Name']["data"]) { @@ -1465,32 +1760,32 @@ export class FileService { isa_files = mapping_data["ISA-Tab File"] } for (var j = 0; j < isa_files.length; j++) { - //console.log("write in ", isa_files[j], "ISA file") + ////console.log("write in ", isa_files[j], "ISA file") var isa_file = isa_files[j] var isa_section = mapping_data["ISA-Tab Section (for Investigation file)"] - ////console.log("write in section: ", isa_section) + //////console.log("write in section: ", isa_section) var isa_field: string = mapping_data["ISA-Tab Field"] - ////console.log("write for isa field: ", isa_field) + //////console.log("write for isa field: ", isa_field) var is_ontology_key = this.is_ontology_key(model, keys[i]) - ////console.log("write for miappe model key ", keys[i]) - ////console.log(return_data) - ////console.log(return_data[isa_file]) + //////console.log("write for miappe model key ", keys[i]) + //////console.log(return_data) + //////console.log(return_data[isa_file]) if (Object.keys(return_data[isa_file]).length === 0) { ////console.log ("change isa model for ", isa_file, isa_model) return_data[isa_file] = isa_model } - ////console.log(return_data[isa_file]) + //////console.log(return_data[isa_file]) // specific model to write in investigation if (isa_file == 'Investigation') { - ////console.log("Investigation") + //////console.log("Investigation") if (return_data[isa_file][isa_section][isa_field]) { //environment type if (model_type === "environment") { - ////console.log("model type environments") + //////console.log("model type environments") environment_obj["parameter"] = data[keys[i]] } //observation unit type @@ -1513,8 +1808,8 @@ export class FileService { //investigation and study type else { if ((isa_field.includes("Type")) && (!isa_field.includes("Comment"))) { - ////console.log(isa_field) - ////console.log(data[keys[i]]) + //////console.log(isa_field) + //////console.log(data[keys[i]]) data[keys[i]].split("/").forEach(element => { return_data[isa_file][isa_section][isa_field].push(element) let tmp_isa_field: string = isa_field + ' Term Accession Number' @@ -1537,10 +1832,10 @@ export class FileService { // Environment type if (model_type === "environment") { - ////console.log("environment model used => write in study isa file") + //////console.log("environment model used => write in study isa file") if (return_data[isa_file][isa_field]["data"]) { - ////console.log(return_data[isa_file][isa_field]) - ////console.log("value => ", data[keys[i]]) + //////console.log(return_data[isa_file][isa_field]) + //////console.log("value => ", data[keys[i]]) environment_obj["value"] = data[keys[i]] let tmp_array = [environment_obj, { "Term Source REF": "" }, { "Term Accession Number": "" }] @@ -1563,9 +1858,9 @@ export class FileService { //Observation_unit and Biological material type else { - ////console.log("search for ", isa_field, " in isa model", isa_file) + //////console.log("search for ", isa_field, " in isa model", isa_file) if (return_data[isa_file][isa_field]) { - ////console.log(isa_field, "exists in", return_data[isa_file][isa_field]["data"]) + //////console.log(isa_field, "exists in", return_data[isa_file][isa_field]["data"]) if (return_data[isa_file][isa_field]["data"]) { if (isa_field.includes("Characteristics")) { @@ -1589,7 +1884,7 @@ export class FileService { } } // else { - // ////console.log(return_data[isa_file][isa_field]) + // //////console.log(return_data[isa_file][isa_field]) // return_data[isa_file][isa_field]["data"] = [data[keys[i]]] // } } @@ -1602,7 +1897,7 @@ export class FileService { //sample type else if (isa_file == 'Assay') { if (return_data[isa_file][isa_field]) { - ////console.log(isa_field, "exists in", return_data[isa_file][isa_field]["data"]) + //////console.log(isa_field, "exists in", return_data[isa_file][isa_field]["data"]) if (return_data[isa_file][isa_field]["data"]) { if (isa_field.includes("Characteristics")) { @@ -1621,7 +1916,7 @@ export class FileService { } } else { - ////console.log(return_data[isa_file][isa_field]) + //////console.log(return_data[isa_file][isa_field]) return_data[isa_file][isa_field]["data"] = [data[keys[i]]] } } @@ -1653,15 +1948,16 @@ export class FileService { } } - //console.log(return_data) + ////console.log(return_data) return return_data } - public saveFiles(model_data, submodels, collection_name = 'data', model_id = "", selected_format = { '.csv': { 'selected': false, separator: ',', type: 'text/csv;charset=utf-8;' } }) { - //console.log(submodels) + public async saveFiles(model_data, submodels, collection_name = 'data', model_id = "", selected_format = { '.csv': { 'selected': false, separator: ',', type: 'text/csv;charset=utf-8;' } }) { + ////console.log(submodels) var model_key = model_id.split("/")[1]; - var paths = { 'filepath': [], 'data': [], 'parent_id': [] } + //var paths = { 'filepath': [], 'data': [], 'parent_id': [] } var root_id = collection_name + '/' + model_key - paths = this.build_path(root_id, submodels, selected_format) + var paths: { 'filepath': any[], 'data': any[], 'parent_id': any[] } = await this.build_path(root_id, submodels, selected_format) + //console.log(paths) let zipFile: JSZip = new JSZip(); // write the data for the selected root node var formats = Object.keys(selected_format); @@ -1672,13 +1968,13 @@ export class FileService { paths['filepath'].push(dir_root_path) paths['data'].push(model_data) paths['parent_id'].push('root') - ////console.log(dir_root_path) + //////console.log(dir_root_path) //zipFile = this.build_zip(dir_root_path, zipFile) } } //build zipfilez with differents paths let dir_root_id = collection_name + '_' + model_key - //console.log(paths) + ////console.log(paths) zipFile = this.build_zip(paths, zipFile) zipFile.generateAsync({ type: "blob" }).then(function (blob) { saveAs(blob, dir_root_id + ".zip"); }); } @@ -1687,8 +1983,8 @@ export class FileService { var formats = Object.keys(selected_format); for (var i = 0; i < formats.length; i++) { if (selected_format[formats[i]]['selected']) { - //console.log(model_type) - if (model_type == "metadata_file") { + ////console.log(model_type) + if (model_type == "metadata_file" || model_type == "data_files") { if (formats[i] == ".csv") { let csvData = this.ConvertMetadataJsonTo(data, ","); let blob = new Blob(['\ufeff' + csvData], { type: 'text/csv;charset=utf-8;' }); @@ -1724,28 +2020,28 @@ export class FileService { // return_data[model_type]=isa_model // return_data = this.build_isa_model(data, model, isa_model, return_data, model_type) // //isa_model = this.build_isa_model(data, model, isa_model) - // //console.log(isa_model) + // ////console.log(isa_model) // //write isa model - // ////console.log(trait_dict) + // //////console.log(trait_dict) // if (model_type == 'observed_variable') { // let tsvData = this.ConvertTraitModelTo(return_data[model_type], "\t"); // let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); // let path = model_id.replace('/', '_') + '/' + 'tdf.txt' - // //console.log(path) + // ////console.log(path) // zipFile.file(path, blob_tsv); // } // else if (model_type == 'biological_material') { // let tsvData = this.ConvertStudyModelTo(return_data[model_type], "\t"); // let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); // let path = model_id.replace('/', '_') + '/' + 's_' + model_id.replace('/', '_') + '.txt' - // //console.log(path) + // ////console.log(path) // zipFile.file(path, blob_tsv); // } // else if (model_type == 'sample') { // let tsvData = this.ConvertStudyModelTo(return_data[model_type], "\t"); // let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); // let path = model_id.replace('/', '_') + '/' + 'a_' + model_id.replace('/', '_') + '.txt' - // //console.log(path) + // ////console.log(path) // zipFile.file(path, blob_tsv); // } // else { @@ -1753,7 +2049,7 @@ export class FileService { // let blob_tsv = new Blob(['\ufeff' + tsvData], { type: 'text/tsv;charset=utf-8;' }); // let path = model_id.replace('/', '_') + '/' + "i_" + model_id.replace('/', '_') + '.txt' // zipFile.file(path, blob_tsv); - // //console.log(path) + // ////console.log(path) // } @@ -1793,14 +2089,16 @@ export class FileService { return str; } public ConvertInvestigationModelTo(objArray, sep = '\t') { - ////console.log(objArray) + //////console.log(objArray) + console.log(sep) let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; + console.log(array) let str = ''; var keys = Object.keys(array); var study_number = 0 for (var i = 0; i < keys.length; i++) { if (keys[i].includes("INVESTIGATION")) { - ////console.log(keys[i]) + //////console.log(keys[i]) if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); i--; @@ -1818,7 +2116,7 @@ export class FileService { var subkeys = Object.keys(array[keys[i]]); for (var j = 0; j < subkeys.length; j++) { if (subkeys[j] === 'Study Identifier') { - //console.log(array[keys[i]][subkeys[j]]) + ////console.log(array[keys[i]][subkeys[j]]) study_number = array[keys[i]][subkeys[j]].length } @@ -1831,7 +2129,7 @@ export class FileService { for (var n = 0; n < study_number; n++) { for (var i = 0; i < keys.length; i++) { if (keys[i].includes("STUDY")) { - ////console.log(keys[i]) + //////console.log(keys[i]) if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); i--; @@ -1841,7 +2139,15 @@ export class FileService { str += keys[i] + '\r\n'; var subkeys = Object.keys(array[keys[i]]); for (var j = 0; j < subkeys.length; j++) { - str += subkeys[j] + sep + array[keys[i]][subkeys[j]][n] + '\r\n'; + /* console.log(subkeys[j]) + console.log(array[keys[i]][subkeys[j]][n]) */ + if (array[keys[i]][subkeys[j]][n].length > 1) { + str += subkeys[j] + sep + array[keys[i]][subkeys[j]][n].join('\t') + '\r\n'; + } + else { + str += subkeys[j] + sep + array[keys[i]][subkeys[j]][n] + '\r\n'; + } + } } } @@ -1853,9 +2159,54 @@ export class FileService { } - ////console.log(str) return str; } + + public ConvertEventModelTo(objArray, sep = ',') { + //console.log(objArray) + let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; + console.log(array) + let str = ''; + //Write header in study isa file and count object + var keys = Object.keys(array); + var event_number = 0 + var headers = [] + for (var i = 0; i < keys.length; i++) { + if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { + keys.splice(i, 1); + i--; + } + else { + //console.log(array[keys[i]]) + event_number = array[keys[i]]['data'].length + str += keys[i] + sep; + } + } + //console.log(str) + //remove last separator + str = str.slice(0, -1); + str += '\r\n'; + for (var j = 0; j < event_number; j++) { + for (var i = 0; i < keys.length; i++) { + //console.log(keys[i]) + if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { + keys.splice(i, 1); + i--; + } + else { + //console.log(array[keys[i]]['data']) + //console.log(array[keys[i]]['data'][j]) + str += array[keys[i]]['data'][j] + sep; + } + + } + str = str.slice(0, -1); + str += '\r\n'; + } + //console.log(str) + return str; + + } public ConvertTraitModelTo(objArray, sep = ',') { let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; let str = ''; @@ -1893,12 +2244,13 @@ export class FileService { return str; } public ConvertStudyModelTo(objArray, sep = '\t') { - //console.log(objArray) + ////console.log(objArray) let obj = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; let str = ''; //Write header in study isa file and count object var keys = Object.keys(obj); + console.log(obj) var biological_material_number = 0 var headers = [] for (var i = 0; i < keys.length; i++) { @@ -1909,11 +2261,11 @@ export class FileService { } else { key_data["data"].forEach(element => { - ////console.log(element) + if (element) { if (keys[i] === "Parameter Value[ ]") { - ////console.log(element[0]["parameter"]+ sep) - ////console.log(keys[i], "=>", key_data["data"]) + //////console.log(element[0]["parameter"]+ sep) + //////console.log(keys[i], "=>", key_data["data"]) if (!str.includes("Parameter Value[" + element[0]["parameter"] + "]")) { str += "Parameter Value[" + element[0]["parameter"] + "]" + sep; headers.push("Parameter Value[" + element[0]["parameter"] + "]") @@ -1927,33 +2279,49 @@ export class FileService { } } else if (keys[i] === "Factor Value[ ]") { - ////console.log(element[0]["parameter"]+ sep) - ////console.log(keys[i], "=>", key_data["data"]) + //console.log(element) + //////console.log(element[0]["parameter"]+ sep) + //////console.log(keys[i], "=>", key_data["data"]) if (element.length > 0) { - if (!str.includes("Factor Value[" + element[0]["factor"] + "]")) { + element.forEach(elem=>{ + if (!str.includes("Factor Value[" + elem[0]["factor"] + "]")) { + str += "Factor Value[" + elem[0]["factor"] + "]" + sep; + headers.push("Factor Value[" + elem[0]["factor"] + "]") + for (var j = 1; j < elem.length; j++) { + var extra_keys = Object.keys(elem[j]); + //console.log(extra_keys) + for (var k = 0; k < extra_keys.length; k++) { + str += extra_keys[k] + sep; + headers.push(extra_keys[k]) + } + } + } + }) + /* if (!str.includes("Factor Value[" + element[0]["factor"] + "]")) { str += "Factor Value[" + element[0]["factor"] + "]" + sep; headers.push("Factor Value[" + element[0]["factor"] + "]") for (var j = 1; j < element.length; j++) { var extra_keys = Object.keys(element[j]); + //console.log(extra_keys) for (var k = 0; k < extra_keys.length; k++) { str += extra_keys[k] + sep; headers.push(extra_keys[k]) } } - } + } */ + //console.log(str) } - } else { //Characteristics descriptors - ////console.log(typeof element) + //////console.log(typeof element) if (typeof element != "string") { - ////console.log(keys[i], "=>", key_data["data"]) + //////console.log(keys[i], "=>", key_data["data"]) if (!str.includes(keys[i])) { str += keys[i] + sep; headers.push(keys[i]) for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { str += extra_keys[k] + sep; @@ -1961,11 +2329,10 @@ export class FileService { } } } - } //Source name or sample name else { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) if (!str.includes(keys[i])) { str += keys[i] + sep; headers.push(keys[i]) @@ -1988,8 +2355,8 @@ export class FileService { } } - ////console.log(headers) - ////console.log(biological_material_number) + console.log(headers) + //////console.log(biological_material_number) str = str.slice(0, -1); str += '\r\n'; //write data @@ -1998,49 +2365,49 @@ export class FileService { // if (h.includes) // } - - + + for (var n = 0; n < biological_material_number; n++) { - // //console.log("#############################=> write a new line") + // ////console.log("#############################=> write a new line") var row = ''; for (var h = 0; h < headers.length; h++) { var header_found: boolean = false - ////console.log("searching for header: ", headers[h]) - + //////console.log("searching for header: ", headers[h]) + for (var i = 0; i < keys.length; i++) { - ////console.log(obj[keys[i]]) - + //////console.log(obj[keys[i]]) + if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); i--; } else { - ////console.log(keys[i]) + //////console.log(keys[i]) var key_data = obj[keys[i]] var element = key_data["data"][n] // key_data["data"].forEach(element => { - ////console.log(key_data["data"]) - ////console.log(element) - - ////console.log(keys[i], obj[keys[i]]) + //////console.log(key_data["data"]) + //////console.log(element) + + //////console.log(keys[i], obj[keys[i]]) if (element) { if (keys[i] === "Parameter Value[ ]") { - ////console.log("searching for key: ", keys[i]) - ////console.log(keys[i], "=>", key_data) + //////console.log("searching for key: ", keys[i]) + //////console.log(keys[i], "=>", key_data) if (headers[h] === "Parameter Value[" + element[0]["parameter"] + "]") { - ////console.log("header found: ", headers[h]) + //////console.log("header found: ", headers[h]) header_found = true str += element[0]['value'] + sep; row += element[0]['value'] + "_"; for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) + //////console.log(element[j][extra_keys[k]]) str += element[j][extra_keys[k]] + sep; row += element[j][extra_keys[k]] + "_"; } @@ -2052,27 +2419,35 @@ export class FileService { } else if (keys[i] === "Factor Value[ ]") { - ////console.log(keys[i], "=>", key_data) + + //////console.log(keys[i], "=>", key_data) if (element.length > 0) { //for (elem in element){ - if (headers[h] === "Factor Value[" + element[0]["factor"] + "]") { - ////console.log("header found: ", headers[h]) - header_found = true - str += element[0]['value'] + sep; - row += element[0]['value'] + "_"; - for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) - var extra_keys = Object.keys(element[j]); - for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) - str += element[j][extra_keys[k]] + sep; - row += element[j][extra_keys[k]] + "_"; + for (let index = 0; index < element.length; index++) { + const elem = element[index]; + if (headers[h] === "Factor Value[" + elem[0]["factor"] + "]") { + //console.log("header found: ", headers[h]) + //console.warn(element) + header_found = true + var factor_obj=elem[0]['value'].filter(el=>el[elem[0]["factor"]]!==undefined)[0] + str += factor_obj[elem[0]["factor"]] + sep; + row += factor_obj[elem[0]["factor"]] + "_"; + + /* str += element[0]['value'][element[0]["factor"]] + sep; + row += element[0]['value'][element[0]["factor"]] + "_"; */ + for (var j = 1; j < elem.length; j++) { + //////console.log(element[j]) + var extra_keys = Object.keys(elem[j]); + for (var k = 0; k < extra_keys.length; k++) { + //////console.log(element[j][extra_keys[k]]) + str += elem[j][extra_keys[k]] + sep; + row += elem[j][extra_keys[k]] + "_"; + } } + h += 2 + break; } - h += 2 - break; } - //} } // else { @@ -2083,22 +2458,22 @@ export class FileService { // } } else { - ////console.log(typeof element) + //////console.log(typeof element) //Characteristics descriptors if (typeof element != "string") { //element is an array - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) //add first value (string value) if (headers[h] === keys[i]) { - ////console.log("header found: ", headers[h]) + //////console.log("header found: ", headers[h]) header_found = true str += element[0] + sep; row += element[0] + "_"; for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) + //////console.log(element[j][extra_keys[k]]) str += element[j][extra_keys[k]] + sep; row += element[j][extra_keys[k]] + "_"; } @@ -2110,9 +2485,9 @@ export class FileService { } //source name, protocol ref, else { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) if (headers[h] === keys[i]) { - ////console.log("header found: ", headers[h]) + //////console.log("header found: ", headers[h]) header_found = true str += element + sep; row += element + "_"; @@ -2125,10 +2500,10 @@ export class FileService { //}); } - ////console.log("row after add a new value in line for header :" ,row) + //////console.log("row after add a new value in line for header :" ,row) } - ////console.log(header_found) + //////console.log(header_found) if (!header_found) { if (headers[h].includes("Parameter Value")) { @@ -2152,7 +2527,7 @@ export class FileService { } } - ////console.log("row after add a new value in line for header :" ,row) + //////console.log("row after add a new value in line for header :" ,row) @@ -2163,17 +2538,17 @@ export class FileService { } - //console.log(str) ////console.log(str) + //////console.log(str) // str = str.slice(0, -1); // str += '\r\n'; return str; } public ConvertAssayModelTo(objArray, sep = '\t') { - //console.log(objArray) + ////console.log(objArray) let obj = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; - console.log(obj) + //console.log(obj) let str = ''; //Write header in assay isa file and count object var keys = Object.keys(obj); @@ -2181,19 +2556,19 @@ export class FileService { var headers = [] for (var i = 0; i < keys.length; i++) { var key_data = obj[keys[i]] - console.log(key_data) - console.log(keys[i]) + //console.log(key_data) + //console.log(keys[i]) if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); i--; } else { key_data["data"].forEach(element => { - console.log(element) + //console.log(element) if (element) { if (keys[i] === "Parameter Value[ ]") { - ////console.log(element[0]["parameter"]+ sep) - ////console.log(keys[i], "=>", key_data["data"]) + //////console.log(element[0]["parameter"]+ sep) + //////console.log(keys[i], "=>", key_data["data"]) if (!str.includes("Parameter Value[" + element[0]["parameter"] + "]")) { str += "Parameter Value[" + element[0]["parameter"] + "]" + sep; headers.push(str) @@ -2207,8 +2582,8 @@ export class FileService { } } else if (keys[i] === "Factor Value[ ]") { - ////console.log(element[0]["parameter"]+ sep) - ////console.log(keys[i], "=>", key_data["data"]) + //////console.log(element[0]["parameter"]+ sep) + //////console.log(keys[i], "=>", key_data["data"]) if (!str.includes("Factor Value[" + element[0]["parameter"] + "]")) { str += "Factor Value[" + element[0]["parameter"] + "]" + sep; headers.push(str) @@ -2223,14 +2598,14 @@ export class FileService { } else { //Characteristics descriptors - ////console.log(typeof element) + //////console.log(typeof element) if (typeof element != "string") { - ////console.log(keys[i], "=>", key_data["data"]) + //////console.log(keys[i], "=>", key_data["data"]) if (!str.includes(keys[i])) { str += keys[i] + sep; headers.push(str) for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { str += extra_keys[k] + sep; @@ -2242,7 +2617,7 @@ export class FileService { } //Source name or sample name else { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) if (!str.includes(keys[i])) { str += keys[i] + sep; headers.push(str) @@ -2264,10 +2639,10 @@ export class FileService { } } - console.log(headers) + //console.log(headers) - console.log(str) - ////console.log(biological_material_number) + //console.log(str) + //////console.log(biological_material_number) str = str.slice(0, -1); str += '\r\n'; //write data @@ -2280,8 +2655,8 @@ export class FileService { var row = ''; for (var i = 0; i < keys.length; i++) { - ////console.log(obj[keys[i]]) - ////console.log(keys[i]) + //////console.log(obj[keys[i]]) + //////console.log(keys[i]) if (keys[i].startsWith("_") || keys[i].startsWith("Definition")) {// || this.model[this.keys[i]].Level ==undefined || this.model[this.keys[i]].Level !=this.level) { keys.splice(i, 1); i--; @@ -2290,53 +2665,53 @@ export class FileService { var key_data = obj[keys[i]] var element = key_data["data"][n] // key_data["data"].forEach(element => { - ////console.log(element) - ////console.log(keys[i], obj[keys[i]]) + //////console.log(element) + //////console.log(keys[i], obj[keys[i]]) if (element) { if (keys[i] === "Parameter Value[ ]") { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) str += element[0]['value'] + sep; for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) + //////console.log(element[j][extra_keys[k]]) str += element[j][extra_keys[k]] + sep; } } } else if (keys[i] === "Factor Value[ ]") { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) str += element[0]['value'] + sep; for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) + //////console.log(element[j][extra_keys[k]]) str += element[j][extra_keys[k]] + sep; } } } else { - ////console.log(typeof element) + //////console.log(typeof element) //Characteristics descriptors if (typeof element != "string") { //element is an array - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) //add first value (string value) str += element[0] + sep; for (var j = 1; j < element.length; j++) { - ////console.log(element[j]) + //////console.log(element[j]) var extra_keys = Object.keys(element[j]); for (var k = 0; k < extra_keys.length; k++) { - ////console.log(element[j][extra_keys[k]]) + //////console.log(element[j][extra_keys[k]]) str += element[j][extra_keys[k]] + sep; } } } //source name, protocol ref, else { - ////console.log(keys[i], "=>", key_data) + //////console.log(keys[i], "=>", key_data) str += element + sep; } } @@ -2348,17 +2723,17 @@ export class FileService { str = str.slice(0, -1); str += '\r\n'; } - console.log(str) + //console.log(str) // str = str.slice(0, -1); // str += '\r\n'; return str; } public ConvertMetadataJsonTo(objArray, sep = ',') { let data = typeof objArray != 'object' ? JSON.parse(objArray) : objArray; - + //console.log(data) var headers = data["headers"]; - var associated_headers = data["associated_headers"]; - var lines = data["data"] + var associated_headers: AssociatedHeadersInterface[] = data["associated_headers"]; + var lines = data["Data"] let row = ''; let str = ''; @@ -2367,33 +2742,37 @@ export class FileService { } row = row.slice(0, -1); str += row + '\r\n'; + //console.log(str) - row = ''; + /* row = ''; + //console.log(associated_headers) for (let index in headers) { - row += associated_headers[headers[index]]['associated_term_id'] + sep; + //console.log(associated_headers.filter(associated_header=>associated_header.header===headers[index])[0]) + row += associated_headers.filter(associated_header=>associated_header.header===headers[index])[0]['associated_parent_id'] + sep; } row = row.slice(0, -1); - str += row + '\r\n'; + str += row + '\r\n'; */ row = ''; for (let index_data in lines) { //console.log(lines[index_data]) row = ''; - for (let i = 0; i < lines[index_data].length; i++) { - row += lines[index_data][i] + sep; + var keys = Object.keys(lines[index_data]) + for (let i = 0; i < keys.length; i++) { + row += lines[index_data][keys[i]] + sep; } row = row.slice(0, -1); str += row + '\r\n'; } - + //console.log(str) return str; } public get_mapping_data_by_key(model: {}, key: string) { - // //console.log(key) - // //console.log(model) - // //console.log(model[key]) + // ////console.log(key) + // ////console.log(model) + // ////console.log(model[key]) var mapping_data = {} - if (Object.keys(model).includes(key)){ + if (Object.keys(model).includes(key)) { if (model[key]["Mapping"]) { mapping_data = model[key]["Mapping"] } @@ -2401,7 +2780,7 @@ export class FileService { return mapping_data } public is_ontology_key(model: {}, key: string) { - if (Object.keys(model).includes(key)){ + if (Object.keys(model).includes(key)) { if (model[key]["Associated ontologies"]) { return true } @@ -2409,7 +2788,7 @@ export class FileService { return false } } - else{ + else { return false } diff --git a/src/app/services/global.service.ts b/src/app/services/global.service.ts index 49c17b07..eded5189 100644 --- a/src/app/services/global.service.ts +++ b/src/app/services/global.service.ts @@ -141,6 +141,12 @@ export class GlobalService { get_ncbi_taxon_data():Observable{ return this.http.get(this.APIUrl + "get_ncbi_taxon_data/"); } + get_ncbi_taxon_data_by_species_regex(regex:string):Observable{ + return this.http.get(this.APIUrl + "get_ncbi_taxon_data_by_species_regex/"+ regex); + } + get_ncbi_taxon_data_by_taxon_regex(regex:string):Observable{ + return this.http.get(this.APIUrl + "get_ncbi_taxon_data_by_taxon_regex/"+ regex); + } get_germplasm_taxon_group_accession_numbers(taxon_group:string):Observable{ return this.http.get(this.APIUrl + "get_germplasm_taxon_group_accession_numbers/" + taxon_group); } @@ -185,8 +191,8 @@ export class GlobalService { return this.http.post(`${this.APIUrl + "update_associated_headers_linda_id"}`, obj2send); } - get_lindaID_by_studyID(study_unique_id:string, parent_key:string):Observable{ - return this.http.get(this.APIUrl + "get_lindaID_by_studyID/" + study_unique_id+ "/" + parent_key).pipe(catchError(this.handleError)); + get_lindaID_by_studyName(study_name:string, parent_key:string):Observable{ + return this.http.get(this.APIUrl + "get_lindaID_by_studyName/" + study_name+ "/" + parent_key).pipe(catchError(this.handleError)); } get_all_vertices(user_key: string) { @@ -220,8 +226,8 @@ export class GlobalService { get_studies(investigation_key: string, person_key: string) : Observable{ return this.http.get(this.APIUrl + "get_studies/" + investigation_key + "/" + person_key).pipe(catchError(this.handleError)); } - get_studies_and_persons(investigation_key: string): Observable<{"e":{},"s":{}}[]>{ - return this.http.get<{"e":{},"s":{}}[]>(this.APIUrl + "get_studies_and_persons/" + investigation_key).pipe(catchError(this.handleError)); + get_studies_and_persons(investigation_key: string): Observable<{"e":{},"v":{}}[]>{ + return this.http.get<{"e":{},"v":{}}[]>(this.APIUrl + "get_studies_and_persons/" + investigation_key).pipe(catchError(this.handleError)); } get_all_project_persons(investigation_key: string) : Observable{ return this.http.get(this.APIUrl + "get_project_persons/" + investigation_key).pipe(catchError(this.handleError)); @@ -359,7 +365,7 @@ export class GlobalService { console.log(obj2send) return this.http.post(`${this.APIUrl + "update_field"}`, obj2send); } - update_multiple_field(values: string[], parent_id:string, _keys: string[], field: string, model_type: string, datafile_key:string="" ,datafile_header:string="" ,model_field:string="") { + update_multiple_field(values: string[], parent_id:string, _keys: string[], field: string, model_type: string, datafile_key:string="" ,datafile_header:string="" , model_field:string="") { let user = this.get_user(); let obj2send = { 'username': user.username, @@ -648,7 +654,7 @@ export class GlobalService { console.log(obj2send) return this.http.post(`${this.APIUrl + "remove_childs_by_type_and_id"}`, obj2send); } - remove_observation_unit(id) { + remove_observation_unit(id:string) { let user = this.get_user(); let obj2send = { 'username': user.username, @@ -786,7 +792,30 @@ export class GlobalService { }; return this.http.post(`${this.APIUrl + "add_multi"}`, obj2send); } - + add_observation_units_factor_value(experimental_factor_values:string[],obs_unit_id:string, factor_type:string){ + let user = this.get_user(); + let obj2send = { + 'username': user.username, + 'password': user.password, + 'experimental_factor_values': experimental_factor_values, + 'obs_unit_id': obs_unit_id, + 'factor_type':factor_type + }; + console.log(obj2send) + return this.http.post(`${this.APIUrl + "add_observation_units_factor_value"}`, obj2send); + } + add_observation_units_observed_variables(values: {}, parent_id: string, obs_var_id:string) { + let user = this.get_user(); + let obj2send = { + 'username': user.username, + 'password': user.password, + 'parent_id': parent_id, + 'values': values, + 'observed_variable_id':obs_var_id + }; + console.log(obj2send) + return this.http.post(`${this.APIUrl + "add_observation_units_observed_variables"}`, obj2send); + } add_observation_units_samples(values: {}, parent_id: string) { let user = this.get_user(); let obj2send = { @@ -811,6 +840,19 @@ export class GlobalService { console.log(obj2send) return this.http.post(`${this.APIUrl + "add_observation_units"}`, obj2send); } + + add_observation_unit_factor(experimental_factor: {}, observation_unit_id: string) { + let user = this.get_user(); + let obj2send = { + 'username': user.username, + 'password': user.password, + 'observation_unit_id': observation_unit_id, + 'experimental_factor': experimental_factor + }; + console.log(obj2send) + return this.http.post(`${this.APIUrl + "add_observation_unit_factor"}`, obj2send); + } + add_observation_units2(values: {}, model_type: string, parent_id: string) { let user = this.get_user(); let obj2send = { diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts index be3f4225..b35bc8e6 100644 --- a/src/app/services/user.service.ts +++ b/src/app/services/user.service.ts @@ -39,7 +39,7 @@ export class UserService { return throwError(() => new Error('Something bad happened; please try again later.')) - } + } getAll() : Observable { //return this.http.get(`${this.APIUrl}users`); return this.http.get(this.APIUrl + "persons/").pipe(catchError(this.handleError)); @@ -77,6 +77,11 @@ export class UserService { //return null return this.http.post(`${this.APIUrl}/update_person_infos`, person); } + get_persons(model_key:string, collection_type:string): Observable{ + return this.http.get(this.APIUrl + "get_persons/" + model_key+ "/"+collection_type).pipe(catchError(this.handleError)) + } + + get_person_id(user_key:string): Observable{ return this.http.get(this.APIUrl + "get_person_id/" + user_key).pipe(catchError(this.handleError)); } diff --git a/src/assets/css/style.css b/src/assets/css/style.css index f8f46c09..11bebf51 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -512,6 +512,7 @@ ul.sidebar-menu li a.active i { padding-bottom: 15px; padding-top: 15px; width: 100%; + min-height: 600px; } a.logo { diff --git a/src/assets/images/LindaLogo.png b/src/assets/images/LindaLogo.png new file mode 100644 index 00000000..3d51108a Binary files /dev/null and b/src/assets/images/LindaLogo.png differ diff --git a/src/assets/images/bio_mat.png b/src/assets/images/bio_mat.png new file mode 100644 index 00000000..61335621 Binary files /dev/null and b/src/assets/images/bio_mat.png differ diff --git a/src/assets/images/biomat_select.png b/src/assets/images/biomat_select.png new file mode 100644 index 00000000..0adcee9d Binary files /dev/null and b/src/assets/images/biomat_select.png differ diff --git a/src/assets/images/block_selection.png b/src/assets/images/block_selection.png new file mode 100644 index 00000000..c5c810f9 Binary files /dev/null and b/src/assets/images/block_selection.png differ diff --git a/src/assets/images/blocks.png b/src/assets/images/blocks.png new file mode 100644 index 00000000..2e7e3f43 Binary files /dev/null and b/src/assets/images/blocks.png differ diff --git a/src/assets/images/bm_description.png b/src/assets/images/bm_description.png new file mode 100644 index 00000000..31a6950a Binary files /dev/null and b/src/assets/images/bm_description.png differ diff --git a/src/assets/images/bm_identifiers.png b/src/assets/images/bm_identifiers.png new file mode 100644 index 00000000..a56443da Binary files /dev/null and b/src/assets/images/bm_identifiers.png differ diff --git a/src/assets/images/datafiles.png b/src/assets/images/datafiles.png new file mode 100644 index 00000000..53f7ca13 Binary files /dev/null and b/src/assets/images/datafiles.png differ diff --git a/src/assets/images/design_table.png b/src/assets/images/design_table.png new file mode 100644 index 00000000..dd77c7bf Binary files /dev/null and b/src/assets/images/design_table.png differ diff --git a/src/assets/images/empty_projects_page.png b/src/assets/images/empty_projects_page.png new file mode 100644 index 00000000..963875ab Binary files /dev/null and b/src/assets/images/empty_projects_page.png differ diff --git a/src/assets/images/env_param.png b/src/assets/images/env_param.png new file mode 100644 index 00000000..ccffd319 Binary files /dev/null and b/src/assets/images/env_param.png differ diff --git a/src/assets/images/events.png b/src/assets/images/events.png new file mode 100644 index 00000000..74f49882 Binary files /dev/null and b/src/assets/images/events.png differ diff --git a/src/assets/images/exp_design.png b/src/assets/images/exp_design.png new file mode 100644 index 00000000..25e781e5 Binary files /dev/null and b/src/assets/images/exp_design.png differ diff --git a/src/assets/images/exp_factors.png b/src/assets/images/exp_factors.png new file mode 100644 index 00000000..8dfb5461 Binary files /dev/null and b/src/assets/images/exp_factors.png differ diff --git a/src/assets/images/exp_site.png b/src/assets/images/exp_site.png new file mode 100644 index 00000000..97835797 Binary files /dev/null and b/src/assets/images/exp_site.png differ diff --git a/src/assets/images/gant.png b/src/assets/images/gant.png new file mode 100644 index 00000000..39046254 Binary files /dev/null and b/src/assets/images/gant.png differ diff --git a/src/assets/images/help2.png b/src/assets/images/help2.png new file mode 100644 index 00000000..e9df4e05 Binary files /dev/null and b/src/assets/images/help2.png differ diff --git a/src/assets/images/help3.png b/src/assets/images/help3.png new file mode 100644 index 00000000..44919bc8 Binary files /dev/null and b/src/assets/images/help3.png differ diff --git a/src/assets/images/help4.png b/src/assets/images/help4.png new file mode 100644 index 00000000..eac481d9 Binary files /dev/null and b/src/assets/images/help4.png differ diff --git a/src/assets/images/help5.png b/src/assets/images/help5.png new file mode 100644 index 00000000..3137911b Binary files /dev/null and b/src/assets/images/help5.png differ diff --git a/src/assets/images/help6.png b/src/assets/images/help6.png new file mode 100644 index 00000000..13c60b2b Binary files /dev/null and b/src/assets/images/help6.png differ diff --git a/src/assets/images/jobim.png b/src/assets/images/jobim.png new file mode 100644 index 00000000..7a4cbb9e Binary files /dev/null and b/src/assets/images/jobim.png differ diff --git a/src/assets/images/linda_favicon.png b/src/assets/images/linda_favicon.png new file mode 100644 index 00000000..d14d9522 Binary files /dev/null and b/src/assets/images/linda_favicon.png differ diff --git a/src/assets/images/linda_favicon2.png b/src/assets/images/linda_favicon2.png new file mode 100644 index 00000000..bb26bdf9 Binary files /dev/null and b/src/assets/images/linda_favicon2.png differ diff --git a/src/assets/images/linda_features.png b/src/assets/images/linda_features.png new file mode 100644 index 00000000..0f8000e0 Binary files /dev/null and b/src/assets/images/linda_features.png differ diff --git a/src/assets/images/obs-var.png b/src/assets/images/obs-var.png new file mode 100644 index 00000000..f1a3c1c8 Binary files /dev/null and b/src/assets/images/obs-var.png differ diff --git a/src/assets/images/observations.png b/src/assets/images/observations.png new file mode 100644 index 00000000..031bc928 Binary files /dev/null and b/src/assets/images/observations.png differ diff --git a/src/assets/images/plots.png b/src/assets/images/plots.png new file mode 100644 index 00000000..35ab0fd4 Binary files /dev/null and b/src/assets/images/plots.png differ diff --git a/src/assets/images/project_members.png b/src/assets/images/project_members.png new file mode 100644 index 00000000..3e94d1e6 Binary files /dev/null and b/src/assets/images/project_members.png differ diff --git a/src/assets/images/project_page.png b/src/assets/images/project_page.png new file mode 100644 index 00000000..6b636963 Binary files /dev/null and b/src/assets/images/project_page.png differ diff --git a/src/assets/images/samples.png b/src/assets/images/samples.png new file mode 100644 index 00000000..828f9346 Binary files /dev/null and b/src/assets/images/samples.png differ diff --git a/src/assets/images/studies_page.png b/src/assets/images/studies_page.png new file mode 100644 index 00000000..252580ce Binary files /dev/null and b/src/assets/images/studies_page.png differ diff --git a/src/assets/images/study_members.png b/src/assets/images/study_members.png new file mode 100644 index 00000000..65132148 Binary files /dev/null and b/src/assets/images/study_members.png differ diff --git a/src/assets/images/study_page.png b/src/assets/images/study_page.png new file mode 100644 index 00000000..aa4f76f2 Binary files /dev/null and b/src/assets/images/study_page.png differ diff --git a/src/assets/images/use_selected_bm.png b/src/assets/images/use_selected_bm.png new file mode 100644 index 00000000..fb41fd3e Binary files /dev/null and b/src/assets/images/use_selected_bm.png differ diff --git a/src/index.html b/src/index.html index 6001f7e0..28141555 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,8 @@ LINDA Plant Experimental Metadata - + + diff --git a/src/styles.css b/src/styles.css index 54b4ea95..1f72fe89 100644 --- a/src/styles.css +++ b/src/styles.css @@ -148,7 +148,7 @@ text-align: center; } -html, body { height: 100%; } +/* html, body { height: 100%; } */ /*body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; @@ -173,9 +173,9 @@ mat-progress-bar .mat-progress-bar-buffer { .mat-card{ border: 1px solid rgba(0, 0, 0, 0.5); - padding-left: 20px; - padding-right: 20px; - margin: 20px + padding-left: 10px; + padding-right: 10px; + margin: 10px } @@ -263,7 +263,7 @@ a[data-toggle="collapse"] { display: block; } #sidebar ul li a:hover { - color: #7386D5; + color: #4ECDC4; background: #fff; }