From a4671ee1ff084e0e5f573b9000526f8b9c8b769f Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 11 Jan 2024 19:01:03 +0100 Subject: [PATCH 01/16] wc - Fixed management of undefined cellbase host and spinner rotating around wrong centre Signed-off-by: gpveronica --- src/core/clients/cellbase/cellbase-client.js | 38 ++++++++++++------- src/sites/iva/iva-app.js | 5 ++- .../commons/layouts/custom-footer.js | 14 +++---- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/core/clients/cellbase/cellbase-client.js b/src/core/clients/cellbase/cellbase-client.js index 84337d9406..7f3b4d78dc 100644 --- a/src/core/clients/cellbase/cellbase-client.js +++ b/src/core/clients/cellbase/cellbase-client.js @@ -61,21 +61,31 @@ export class CellBaseClient { detail: value })); }; - this.getMeta("about") - .then(response => { - const result = response?.response?.[0]?.result[0]; - // Older versions of cellbase are using 'Version: ' as the key instead of 'Version' (Issue #185). - // To keep compatibility, we will check for both keys, but in the future only the newest key will be used. - globalEvent("hostInit", { - host: "cellbase", - value: "v" + (result["Version"] || result["Version: "]), - }); - }) - .catch(e => { - console.error(e); - // globalEvent("signingInError", {value: "Cellbase host not available."}); - globalEvent("hostInit", {host: "cellbase", value: "NOT AVAILABLE"}); + if (!this._config.host) { + globalEvent("hostInit", { + host: "cellbase", + value: "NOT DEFINED" }); + } else { + this.getMeta("about") + .then(response => { + const result = response?.response?.[0]?.result[0]; + // Older versions of cellbase are using 'Version: ' as the key instead of 'Version' (Issue #185). + // To keep compatibility, we will check for both keys, but in the future only the newest key will be used. + globalEvent("hostInit", { + host: "cellbase", + value: "v" + (result["Version"] || result["Version: "]), + }); + }) + .catch(e => { + console.error(e); + // globalEvent("signingInError", {value: "Cellbase host not available."}); + globalEvent("hostInit", { + host: "cellbase", + value: "NOT AVAILABLE" + }); + }); + } } _initCache() { diff --git a/src/sites/iva/iva-app.js b/src/sites/iva/iva-app.js index d29e90d85b..afab4332aa 100644 --- a/src/sites/iva/iva-app.js +++ b/src/sites/iva/iva-app.js @@ -975,9 +975,10 @@ class IvaApp extends LitElement { } else { // Josemi 20220216 NOTE: we keep this old way to be backward compatible with OpenCGA 2.1 // But this should be removed in future releases + this.config.cellbase = null; this.cellbaseClient = new CellBaseClient({ - host: this.config.cellbase.host, - version: this.config.cellbase.version, + host: this.config.cellbase?.host, + version: this.config.cellbase?.version, species: "hsapiens", }); } diff --git a/src/webcomponents/commons/layouts/custom-footer.js b/src/webcomponents/commons/layouts/custom-footer.js index e95575ab0d..adfaacf89b 100644 --- a/src/webcomponents/commons/layouts/custom-footer.js +++ b/src/webcomponents/commons/layouts/custom-footer.js @@ -186,22 +186,20 @@ export default class CustomFooter extends LitElement { ${this.appName || "IVA (JSorolla)"} ${this.version || this.config?.version} + + From 3e8b93cb0e9869714c030fb31c0b3239b93e70f4 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 15 Jan 2024 09:38:44 +0100 Subject: [PATCH 02/16] wc - Added optional chaining to the check condition for NOT DEFINED Signed-off-by: gpveronica --- src/core/clients/cellbase/cellbase-client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/clients/cellbase/cellbase-client.js b/src/core/clients/cellbase/cellbase-client.js index 7f3b4d78dc..f87f49d436 100644 --- a/src/core/clients/cellbase/cellbase-client.js +++ b/src/core/clients/cellbase/cellbase-client.js @@ -61,7 +61,7 @@ export class CellBaseClient { detail: value })); }; - if (!this._config.host) { + if (!this._config?.host) { globalEvent("hostInit", { host: "cellbase", value: "NOT DEFINED" From 15e9617ba3f372b185beeb40fb27cc9a1508640b Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 13:33:00 +0100 Subject: [PATCH 03/16] wc: add samples dropdown for single type in clinical analysis create form #TASK-5094 --- .../clinical/clinical-analysis-create.js | 76 +++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 49033beae1..8bb50f2834 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -21,6 +21,7 @@ import NotificationUtils from "../commons/utils/notification-utils.js"; import WebUtils from "../commons/utils/web-utils.js"; import UtilsNew from "../../core/utils-new.js"; import "../commons/forms/data-form.js"; +import "../commons/forms/select-token-filter.js"; import "../commons/filters/disease-panel-filter.js"; import "../commons/filters/catalog-search-autocomplete.js"; import "../commons/image-viewer.js"; @@ -113,9 +114,27 @@ export default class ClinicalAnalysisCreate extends LitElement { _users: this._users, comments: [], panelLock: false, + samples: [], }; } + initSamples(samples, isSomatic) { + // 1 Check if there is a sample with status READY + const readySample = samples.find(sample => { + return sample.somatic === isSomatic && sample?.internal?.status?.id === "READY"; + }); + if (readySample) { + return [readySample]; + } + // 2. If not, select the first sample in the list instead + const firstSample = samples.find(sample => sample.somatic === isSomatic); + if (firstSample) { + return [firstSample]; + } + // 3. Other case, no samples are available + return []; + } + onFieldChange(e) { this.clinicalAnalysis = {...this.clinicalAnalysis}; @@ -157,12 +176,14 @@ export default class ClinicalAnalysisCreate extends LitElement { // Empty proband and disorder fields when a new individual has been selected or removed from the proband field delete this.clinicalAnalysis["proband"]; delete this.clinicalAnalysis["disorder"]; + delete this.clinicalAnalysis["samples"]; if (e.detail.value) { this.clinicalAnalysis.type = "SINGLE"; this.opencgaSession.opencgaClient.individuals().info(e.detail.value, {study: this.opencgaSession.study.fqn}) .then(response => { this.clinicalAnalysis.proband = response.responses[0].results[0]; + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); if (this.clinicalAnalysis.proband?.disorders?.length === 1) { this.clinicalAnalysis.disorder = { @@ -257,6 +278,16 @@ export default class ClinicalAnalysisCreate extends LitElement { } } + onSampleChange(e) { + this.clinicalAnalysis.samples = (e.detail.value || "") + .split(",") + .map(sampleId => { + return this.clinicalAnalysis.proband?.samples?.find(sample => sample.id === sampleId); + }); + this.clinicalAnalysis = {...this.clinicalAnalysis}; + this.requestUpdate(); + } + notifyClinicalAnalysisWrite() { LitUtils.dispatchCustomEvent(this, "clinicalAnalysisCreate", null, { id: this.clinicalAnalysis.id, @@ -278,15 +309,18 @@ export default class ClinicalAnalysisCreate extends LitElement { // remove private fields delete data._users; + delete data.samples; data = { ...data, proband: { - id: this.clinicalAnalysis?.proband?.id ? this.clinicalAnalysis?.proband?.id : null + id: this.clinicalAnalysis?.proband?.id ? this.clinicalAnalysis?.proband?.id : null, + samples: this.clinicalAnalysis.samples.map(sample => { + return {id: sample.id}; + }), } }; if (data.type === "FAMILY") { - data = { ...data, family: { @@ -325,6 +359,27 @@ export default class ClinicalAnalysisCreate extends LitElement { }); } + renderSamplesSelection(samples = [], isMultiple, disableSomaticSamples) { + const selectedSamples = (this.clinicalAnalysis?.samples || []) + .map(sample => sample.id) + .join(","); + const data = (samples || []).map(sample => { + return { + id: sample.id, + name: `${sample.name || sample.id} (${sample.somatic ? "Somatic" : "Germline"})`, + disabled: sample.somatic && disableSomaticSamples, + }; + }); + return html` + + + `; + } + render() { if (!this.opencgaSession?.study) { return html ` @@ -479,6 +534,17 @@ export default class ClinicalAnalysisCreate extends LitElement { }, }, }, + { + title: "Select Samples", + field: "proband.samples", + type: "custom", + required: true, + display: { + render: samples => { + return this.renderSamplesSelection(samples, false, true); + }, + }, + }, { title: "Select Disorder", field: "disorder.id", @@ -495,12 +561,12 @@ export default class ClinicalAnalysisCreate extends LitElement { } }, { - title: "Samples", - field: "proband.samples", + title: "Selected Samples", + field: "samples", type: "table", display: { // defaultLayout: "vertical", - errorMessage: "No proband selected", + errorMessage: "No samples selected", errorClassName: "", columns: [ { From dcb4e82bf2c240fec83072a03c765cc6b32f0d20 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 13:35:57 +0100 Subject: [PATCH 04/16] wc: minor code style fixes in clinical analysis create #TASK-5094 --- .../clinical/clinical-analysis-create.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 8bb50f2834..631883cabf 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -70,15 +70,8 @@ export default class ClinicalAnalysisCreate extends LitElement { titleAlign: "left", titleWidth: 3, defaultLayout: "horizontal", - }; - - } - - connectedCallback() { - super.connectedCallback(); - - this._config = {...this.getDefaultConfig(), ...this.config}; + this._config = this.getDefaultConfig(); } update(changedProperties) { @@ -88,15 +81,18 @@ export default class ClinicalAnalysisCreate extends LitElement { if (this.opencgaSession?.study) { this._users = OpencgaCatalogUtils.getUsers(this.opencgaSession.study); this.initClinicalAnalysis(); - this._clinicalAnalysis = UtilsNew.objectClone(this.clinicalAnalysis); } this.requestUpdate(); } if (changedProperties.has("config")) { - this._config = {...this.getDefaultConfig(), ...this.config}; + this._config = { + ...this.getDefaultConfig(), + ...this.config, + }; } + super.update(changedProperties); } From d44d960da6a32b5b7830b7f9c5dbf00a11869026 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 13:58:00 +0100 Subject: [PATCH 05/16] wc: add samples dropdown for family type in clinical analysis create form #TASK-5094 --- .../clinical/clinical-analysis-create.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 631883cabf..3673c2d84c 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -172,7 +172,9 @@ export default class ClinicalAnalysisCreate extends LitElement { // Empty proband and disorder fields when a new individual has been selected or removed from the proband field delete this.clinicalAnalysis["proband"]; delete this.clinicalAnalysis["disorder"]; - delete this.clinicalAnalysis["samples"]; + + // Reset samples + this.clinicalAnalysis.samples = []; if (e.detail.value) { this.clinicalAnalysis.type = "SINGLE"; @@ -205,11 +207,15 @@ export default class ClinicalAnalysisCreate extends LitElement { delete this.clinicalAnalysis["disorder"]; delete this.clinicalAnalysis["family"]; + // Reset samples + this.clinicalAnalysis.samples = []; + if (e.detail.value) { this.clinicalAnalysis.type = "FAMILY"; this.opencgaSession.opencgaClient.families().info(e.detail.value, {study: this.opencgaSession.study.fqn}) .then(response => { this.clinicalAnalysis.family = response.responses[0].results[0]; + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); // Select as proband the first son/daughter with a disorder if (this.clinicalAnalysis.family && this.clinicalAnalysis.family.members) { @@ -622,6 +628,17 @@ export default class ClinicalAnalysisCreate extends LitElement { errorMessage: "No family selected", }, }, + { + title: "Select Samples", + field: "proband.samples", + type: "custom", + required: true, + display: { + render: samples => { + return this.renderSamplesSelection(samples, false, true); + }, + }, + }, { title: "Select Disorder", field: "disorder.id", From 6031924a94e0eaaaa8ea4d744593cfb8ba795714 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:01:47 +0100 Subject: [PATCH 06/16] wc: add samples dropdown for cancer type in clinical analysis create form #TASK-5094 --- .../clinical/clinical-analysis-create.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 3673c2d84c..6ed98f64d2 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -250,14 +250,15 @@ export default class ClinicalAnalysisCreate extends LitElement { delete this.clinicalAnalysis["proband"]; delete this.clinicalAnalysis["disorder"]; + // Reset selected samples + this.clinicalAnalysis.samples = []; + if (e.detail.value) { this.clinicalAnalysis.type = "CANCER"; this.opencgaSession.opencgaClient.individuals().info(e.detail.value, {study: this.opencgaSession.study.fqn}) .then(response => { - this.clinicalAnalysis = { - ...this.clinicalAnalysis, - proband: response.responses[0].results[0] - }; + this.clinicalAnalysis.proband = response?.responses?.[0]?.results?.[0] || {}; + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); if (this.clinicalAnalysis?.proband?.disorders?.length === 1) { this.clinicalAnalysis = { @@ -763,6 +764,17 @@ export default class ClinicalAnalysisCreate extends LitElement { `, }, }, + { + title: "Select Samples", + field: "proband.samples", + type: "custom", + required: true, + display: { + render: samples => { + return this.renderSamplesSelection(samples, true, false); + }, + }, + }, { title: "Select Disorder", field: "disorder.id", From abbce584057473a253dbc01ad41d91c8758eec5b Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:07:54 +0100 Subject: [PATCH 07/16] wc: fix selecting initial sample for cancer cases #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 6ed98f64d2..de9c2e673d 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -258,7 +258,7 @@ export default class ClinicalAnalysisCreate extends LitElement { this.opencgaSession.opencgaClient.individuals().info(e.detail.value, {study: this.opencgaSession.study.fqn}) .then(response => { this.clinicalAnalysis.proband = response?.responses?.[0]?.results?.[0] || {}; - this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], true); if (this.clinicalAnalysis?.proband?.disorders?.length === 1) { this.clinicalAnalysis = { From 8793e49c4bd37be8a342a69b96dedab1c9ad9074 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:14:12 +0100 Subject: [PATCH 08/16] wc: display an error message if no samples are available for the selected proband #TASK-5094 --- .../clinical/clinical-analysis-create.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index de9c2e673d..02957d960b 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -362,7 +362,13 @@ export default class ClinicalAnalysisCreate extends LitElement { }); } - renderSamplesSelection(samples = [], isMultiple, disableSomaticSamples) { + renderSamplesSelection(samples = [], isMultiple, somatic = false) { + // Check for no available samples + if (this.clinicalAnalysis?.proband?.id) { + if (samples.length === 0 || !samples.some(sample => sample.somatic === somatic)) { + return `No ${somatic ? "somatic" : "germline"} samples availabe for proband '${this.clinicalAnalysis.proband.id}'.`; + } + } const selectedSamples = (this.clinicalAnalysis?.samples || []) .map(sample => sample.id) .join(","); @@ -370,7 +376,7 @@ export default class ClinicalAnalysisCreate extends LitElement { return { id: sample.id, name: `${sample.name || sample.id} (${sample.somatic ? "Somatic" : "Germline"})`, - disabled: sample.somatic && disableSomaticSamples, + disabled: sample.somatic && !somatic, }; }); return html` @@ -544,7 +550,7 @@ export default class ClinicalAnalysisCreate extends LitElement { required: true, display: { render: samples => { - return this.renderSamplesSelection(samples, false, true); + return this.renderSamplesSelection(samples, false, false); }, }, }, @@ -636,7 +642,7 @@ export default class ClinicalAnalysisCreate extends LitElement { required: true, display: { render: samples => { - return this.renderSamplesSelection(samples, false, true); + return this.renderSamplesSelection(samples, false, false); }, }, }, @@ -771,7 +777,7 @@ export default class ClinicalAnalysisCreate extends LitElement { required: true, display: { render: samples => { - return this.renderSamplesSelection(samples, true, false); + return this.renderSamplesSelection(samples, true, true); }, }, }, From e92c4626d0dc12e3d2327321c27756838c6a5cce Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:18:54 +0100 Subject: [PATCH 09/16] wc: fix setting samples on family type #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 02957d960b..01f1afb567 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -139,6 +139,9 @@ export default class ClinicalAnalysisCreate extends LitElement { delete this.clinicalAnalysis["proband"]; delete this.clinicalAnalysis["disorder"]; delete this.clinicalAnalysis["family"]; + + // We would need also to reset samples + this.clinicalAnalysis.samples = []; } // In FAMILY, changing the proband only sets the 'proband.id' field of the clinicalAnalysis object @@ -150,9 +153,12 @@ export default class ClinicalAnalysisCreate extends LitElement { const proband = this.clinicalAnalysis.family.members.find(member => member.id === this.clinicalAnalysis.proband?.id); this.clinicalAnalysis.proband = UtilsNew.objectClone(proband); this.clinicalAnalysis.proband.disorders = this.clinicalAnalysis.proband.disorders || []; + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); + } else { - // If we have removed the 'proband.id' field, we have to remove also the full proband object + // If we have removed the 'proband.id' field, we have to remove also the full proband object and reset samples delete this.clinicalAnalysis.proband; + this.clinicalAnalysis.samples = []; } } @@ -215,13 +221,13 @@ export default class ClinicalAnalysisCreate extends LitElement { this.opencgaSession.opencgaClient.families().info(e.detail.value, {study: this.opencgaSession.study.fqn}) .then(response => { this.clinicalAnalysis.family = response.responses[0].results[0]; - this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); // Select as proband the first son/daughter with a disorder if (this.clinicalAnalysis.family && this.clinicalAnalysis.family.members) { for (const member of this.clinicalAnalysis.family.members) { if (member.disorders && member.disorders.length > 0 && member.father.id && member.mother.id) { this.clinicalAnalysis.proband = UtilsNew.objectClone(member); + this.clinicalAnalysis.samples = this.initSamples(this.clinicalAnalysis?.proband?.samples || [], false); break; } } From 036d7fbad6a21188a2a62e7aff1665d2c6538d1f Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:25:43 +0100 Subject: [PATCH 10/16] wc: fix displayed samples #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 01f1afb567..29e8303eb2 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -580,8 +580,7 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "samples", type: "table", display: { - // defaultLayout: "vertical", - errorMessage: "No samples selected", + errorMessage: "No proband or sample selected.", errorClassName: "", columns: [ { @@ -804,11 +803,11 @@ export default class ClinicalAnalysisCreate extends LitElement { }, { title: "Samples", - field: "proband.samples", + field: "samples", type: "table", display: { errorClassName: "", - errorMessage: "No proband selected", + errorMessage: "No proband or sample(s) selected.", columns: [ { id: "fileIds", From 84cc884b5fd89ef554356c94f4c2d8e0fbfc787c Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:26:10 +0100 Subject: [PATCH 11/16] wc: fix removing samples #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 29e8303eb2..bdff69d929 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -290,6 +290,7 @@ export default class ClinicalAnalysisCreate extends LitElement { onSampleChange(e) { this.clinicalAnalysis.samples = (e.detail.value || "") .split(",") + .filter(s => !!s) .map(sampleId => { return this.clinicalAnalysis.proband?.samples?.find(sample => sample.id === sampleId); }); From d1610450472a07c2c4af97efdbb513cfaaf34912 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:29:21 +0100 Subject: [PATCH 12/16] wc: fix displayed error message on selected samples table #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index bdff69d929..d4276356ae 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -581,8 +581,7 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "samples", type: "table", display: { - errorMessage: "No proband or sample selected.", - errorClassName: "", + defaultValue: "No proband or sample selected.", columns: [ { id: "id", @@ -807,8 +806,7 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "samples", type: "table", display: { - errorClassName: "", - errorMessage: "No proband or sample(s) selected.", + defaultValue: "No proband or sample(s) selected.", columns: [ { id: "fileIds", From faae1e1e9d4165bacddf91b422d39d9e9316a1c5 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 14:30:37 +0100 Subject: [PATCH 13/16] wc: fix status column in samples table of clinical analysis create #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index d4276356ae..381cb38887 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -600,7 +600,7 @@ export default class ClinicalAnalysisCreate extends LitElement { { id: "Status", title: "Status", - field: "status.name", + field: "internal.status.id", formatter: value => value ?? "-" }, ] @@ -825,7 +825,7 @@ export default class ClinicalAnalysisCreate extends LitElement { }, { title: "Status", - field: "status.name", + field: "internal.status.id", formatter: value => value ?? "-" } ] From ddc499ebd404e9932443d63431824c51b02eb8ce Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 15:52:35 +0100 Subject: [PATCH 14/16] wc: removed unused function in clinical analysis create #TASK-5094 --- src/webcomponents/clinical/clinical-analysis-create.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 381cb38887..ae35939dab 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -165,15 +165,6 @@ export default class ClinicalAnalysisCreate extends LitElement { this.requestUpdate(); } - onCustomFieldChange(field, e) { - this.onFieldChange({ - detail: { - value: e.detail.value, - param: field - } - }); - } - onIndividualChange(e) { // Empty proband and disorder fields when a new individual has been selected or removed from the proband field delete this.clinicalAnalysis["proband"]; @@ -423,7 +414,6 @@ export default class ClinicalAnalysisCreate extends LitElement { title: "Create Case", icon: "fas fa-user-md", requires: "2.0.0", - description: "Sample Variant Stats description", display: this.displayConfig || this.displayConfigDefault, sections: [ { From 2f7405fdb3a0be74f51c4b1a8480fb94a8de0d73 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 16:16:30 +0100 Subject: [PATCH 15/16] wc: add validations to selected samples #TASK-5094 --- .../clinical/clinical-analysis-create.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index ae35939dab..9a108f67b9 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -545,6 +545,12 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "proband.samples", type: "custom", required: true, + validation: { + validate: () => { + return this.clinicalAnalysis?.samples?.length === 1; + }, + message: "A germline sample must be selected.", + }, display: { render: samples => { return this.renderSamplesSelection(samples, false, false); @@ -635,6 +641,12 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "proband.samples", type: "custom", required: true, + validation: { + validate: () => { + return this.clinicalAnalysis?.samples?.length === 1; + }, + message: "A germline sample must be selected.", + }, display: { render: samples => { return this.renderSamplesSelection(samples, false, false); @@ -770,6 +782,24 @@ export default class ClinicalAnalysisCreate extends LitElement { field: "proband.samples", type: "custom", required: true, + validation: { + validate: () => { + // Case :: Only one sample has been selected, check if this sample is somatic + if (this.clinicalAnalysis?.samples?.length === 1) { + return this.clinicalAnalysis.samples[0].somatic; + } + // Case 2: two samples selected: verify that one sample is somatic and the other + // sample is germline + if (this.clinicalAnalysis?.samples?.length === 2) { + const hasSomatic = this.clinicalAnalysis.samples.some(s => s.somatic); + const hasGermline = this.clinicalAnalysis.samples.some(s => !s.somatic); + return hasSomatic && hasGermline; + } + // Case 3: no samples or more than two samples selected. + return false; + }, + message: "At least a somatic sample must be selected. Only one somatic and one germline samples are allowed.", + }, display: { render: samples => { return this.renderSamplesSelection(samples, true, true); From 0d322402b595bce30c8225385eaf17a9a5236b72 Mon Sep 17 00:00:00 2001 From: Josemi Date: Wed, 17 Jan 2024 16:27:55 +0100 Subject: [PATCH 16/16] wc: fix preparing data for creating the new clinical analysis #TASK-5094 --- .../clinical/clinical-analysis-create.js | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/webcomponents/clinical/clinical-analysis-create.js b/src/webcomponents/clinical/clinical-analysis-create.js index 9a108f67b9..13ffc0b0d7 100644 --- a/src/webcomponents/clinical/clinical-analysis-create.js +++ b/src/webcomponents/clinical/clinical-analysis-create.js @@ -77,7 +77,6 @@ export default class ClinicalAnalysisCreate extends LitElement { update(changedProperties) { if (changedProperties.has("opencgaSession")) { // We store the available users from opencgaSession in 'clinicalAnalysis._users' - this.clinicalAnalysis._users = []; if (this.opencgaSession?.study) { this._users = OpencgaCatalogUtils.getUsers(this.opencgaSession.study); this.initClinicalAnalysis(); @@ -107,7 +106,6 @@ export default class ClinicalAnalysisCreate extends LitElement { // analyst: { // id: this.opencgaSession?.user?.id // }, - _users: this._users, comments: [], panelLock: false, samples: [], @@ -306,28 +304,30 @@ export default class ClinicalAnalysisCreate extends LitElement { onSubmit() { // Prepare the data for the REST create - let data = {...this.clinicalAnalysis}; - - // remove private fields - delete data._users; - delete data.samples; - data = { - ...data, + const data = { + ...this.clinicalAnalysis, proband: { id: this.clinicalAnalysis?.proband?.id ? this.clinicalAnalysis?.proband?.id : null, samples: this.clinicalAnalysis.samples.map(sample => { - return {id: sample.id}; + return { + id: sample.id, + }; }), - } + }, }; + // Remove private fields + delete data.samples; + + // For FAMILY case, we need to include the family id and the members if (data.type === "FAMILY") { - data = { - ...data, - family: { - id: this.clinicalAnalysis.family.id, - members: this.clinicalAnalysis.family.members.map(e => ({id: e.id})) - } + data.family = { + id: this.clinicalAnalysis.family.id, + members: this.clinicalAnalysis.family.members.map(member => { + return { + id: member.id, + }; + }), }; } @@ -877,8 +877,6 @@ export default class ClinicalAnalysisCreate extends LitElement { title: "Assigned To", field: "analysts", type: "custom", - // defaultValue: this.opencgaSession?.user?.id, - // allowedValues: "_users", display: { render: (analysts, dataFormFilterChange) => { const handleAnalystsFilterChange = e => {