Skip to content

Commit

Permalink
Merge branch 'release-3.x.x' into TASK-5589
Browse files Browse the repository at this point in the history
  • Loading branch information
jmjuanes authored Sep 24, 2024
2 parents 2d7c4fa + 0d42375 commit 7529011
Show file tree
Hide file tree
Showing 15 changed files with 209 additions and 199 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/iva/genome-browser.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ context("GenomeBrowser", () => {

cy.get("@karyotype")
.find(`div[data-cy="gb-karyotype-toggle"]`)
.trigger("click");
.trigger("click", {force: true});

cy.get("@karyotypeContent")
.invoke("css", "display")
Expand Down
32 changes: 32 additions & 0 deletions cypress/e2e/iva/variant-browser-grid.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,38 @@ context("Variant Browser Grid", () => {
});
});

context("clinical info", () => {
context("cosmic column", () => {
const columnIndex = 18;
it("should display an 'x' icon if no cosmic information is available", () => {
cy.get("@variantBrowser")
.find(`tbody > tr[data-uniqueid="14:91649938:A:G"] > td`)
.eq(columnIndex)
.find("i")
.should("have.class", "fa-times");
});

it("should display the number of entries and total trait associations", () => {
cy.get("@variantBrowser")
.find("tbody tr:first > td")
.eq(columnIndex)
.should("contain.text", "1 entry (1)");
});

it("should display a tooltip with a link to cosmic", () => {
cy.get("@variantBrowser")
.find("tbody tr:first > td")
.eq(columnIndex)
.find("a")
.trigger("mouseover");

cy.get(`div[class="qtip-content"]`)
.find(`a[href^="https://cancer.sanger.ac.uk/cosmic/search?q="]`)
.should("exist");
});
});
});

context("actions", () => {
const variant = "14:91649858:C:T";
beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/genome-browser/genome-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default class GenomeBrowser {
// Generate GB template
const template = UtilsNew.renderHTML(`
<div id="${this.prefix}" data-cy="gb-parent" class="card text-bg-light mb-3">
<div id="${this.prefix}Navigation" data-cy="gb-navigation" class="card-header"></div>
<div id="${this.prefix}Navigation" data-cy="gb-navigation" class="card-header bg-light sticky-top"></div>
<ul class="list-group rounded-0">
<li id="${this.prefix}Karyotype" data-cy="gb-karyotype" class="list-group-item" style="display:none;"></li>
<li id="${this.prefix}Chromosome" data-cy="gb-chromosome" class="list-group-item" style="display:none;"></li>
Expand Down
33 changes: 28 additions & 5 deletions src/genome-browser/renderers/variant-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,21 @@ export default class VariantRenderer extends Renderer {
const lollipopStickHeight = this.config.lollipopHeight - this.config.lollipopFocusWidth - this.config.lollipopMaxWidth / 2;
let lollipopStickStart = this.config.lollipopFocusWidth + this.config.lollipopMaxWidth / 2;
let lollipopPositions = [];
let lollipopIndex = 0;
let topPosition = this.config.lollipopVisible ? this.config.lollipopHeight : this.config.headerHeight;

// We have to filter features and consider only the ones that are in the current region
// this is important because when we request for breakends to OpenCGA it returns both variants of the breakend
const region = options.requestedRegion;
const featuresToDisplay = (features || []).filter(feature => {
return feature.chromosome === region.chromosome && feature.start <= region.end && region.start <= feature.end;
});

if (this.config.lollipopVisible) {
lollipopPositions = LollipopLayout.fromFeaturesList(features || [], options.requestedRegion, lollipopRegionWidth, {
const featuresForLollipops = featuresToDisplay.filter(feature => {
return this.config.lollipopVariantTypes.includes(feature.type);
});
lollipopPositions = LollipopLayout.fromFeaturesList(featuresForLollipops, options.requestedRegion, lollipopRegionWidth, {
minSeparation: this.config.lollipopMaxWidth,
});
}
Expand All @@ -60,7 +71,16 @@ export default class VariantRenderer extends Renderer {
lollipopStickStart = lollipopStickStart + this.config.highlightHeight;
}

(features || []).forEach((feature, featureIndex) => {
featuresToDisplay.forEach((feature, featureIndex) => {
// Check if this variant has been previously rendered
if (options?.renderedFeatures && feature?.id) {
if (options.renderedFeatures.has(feature.id)) {
return;
}
// Prevent rendering this variant in next calls of this renderer
options.renderedFeatures.add(feature.id);
}

const group = SVG.addChild(options.svgCanvasFeatures, "g", {
"data-cy": "gb-variant",
"data-id": feature.id || "-",
Expand All @@ -86,9 +106,9 @@ export default class VariantRenderer extends Renderer {

let variantElement = null;

// Check if lollipops are visible
if (this.config.lollipopVisible) {
const lollipopX = lollipopStartX + lollipopPositions[featureIndex];
// Check if lollipops are visible and the feature type is one of the allowed types for lollipops
if (this.config.lollipopVisible && this.config.lollipopVariantTypes?.includes?.(feature?.type)) {
const lollipopX = lollipopStartX + lollipopPositions[lollipopIndex];
const lollipopWidth = Math.min(1, Math.max(0, this.getValueFromConfig("lollipopWidth", [feature])));
const lollipopPath = [
`M ${lollipopX},${lollipopStickStart}`,
Expand Down Expand Up @@ -130,6 +150,8 @@ export default class VariantRenderer extends Renderer {
variantElement.setAttribute("stroke-width", 0);
});
}
// increment lollipop index
lollipopIndex = lollipopIndex + 1;
} else {
variantElement = SVG.addChild(group, "rect", {
"data-cy": "gb-variant-lollipop-shape",
Expand Down Expand Up @@ -296,6 +318,7 @@ export default class VariantRenderer extends Renderer {
lollipopMaxWidth: 15,
lollipopShape: GenomeBrowserUtils.lollipopShapeFormatter,
lollipopWidth: GenomeBrowserUtils.lollipopWidthFormatter,
lollipopVariantTypes: ["SNV", "INDEL", "BREAKEND"],
// Lollipop focus
lollipopFocusEnabled: true,
lollipopFocusWidth: 2,
Expand Down
8 changes: 4 additions & 4 deletions src/genome-browser/tracks/feature-track.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,17 @@ export default class FeatureTrack {

hideContent() {
this.contentVisible = false;
this.content.classList.add("hidden");
this.resize.classList.add("hidden");
this.content.classList.add("d-none");
this.resize.classList.add("d-none");

this.titleToggleIcon.classList.remove("fa-minus");
this.titleToggleIcon.classList.add("fa-plus");
}

showContent() {
this.contentVisible = true;
this.content.classList.remove("hidden");
this.resize.classList.remove("hidden");
this.content.classList.remove("d-none");
this.resize.classList.remove("d-none");

this.titleToggleIcon.classList.remove("fa-plus");
this.titleToggleIcon.classList.add("fa-minus");
Expand Down
29 changes: 7 additions & 22 deletions src/webcomponents/clinical/clinical-analysis-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import OpencgaCatalogUtils from "../../core/clients/opencga/opencga-catalog-util
import UtilsNew from "../../core/utils-new.js";
import GridCommons from "../commons/grid-commons.js";
import CatalogGridFormatter from "../commons/catalog-grid-formatter.js";
import "../commons/opencb-grid-toolbar.js";
import LitUtils from "../commons/utils/lit-utils.js";
import NotificationUtils from "../commons/utils/notification-utils.js";
import ModalUtils from "../commons/modal/modal-utils.js";
import WebUtils from "../commons/utils/web-utils.js";
import "../commons/opencb-grid-toolbar.js";

export default class ClinicalAnalysisGrid extends LitElement {

Expand Down Expand Up @@ -304,22 +305,6 @@ export default class ClinicalAnalysisGrid extends LitElement {
// TODO remove this code as soon as new OpenCGA configuration is in place
const _priorities = this.opencgaSession?.study?.internal?.configuration?.clinical?.priorities || [];

// Priorities classes
const priorityMap = {
URGENT: "text-bg-danger",
HIGH: "text-bg-warning",
MEDIUM: "text-bg-primary",
LOW: "text-bg-info"
};
const priorityRankToColor = [
"text-bg-danger",
"text-bg-warning",
"text-bg-primary",
"text-bg-info",
"text-bg-success",
"text-bg-light"
];

const hasWriteAccess = OpencgaCatalogUtils.checkPermissions(this.opencgaSession.study, this.opencgaSession.user.id, "WRITE_CLINICAL_ANALYSIS");
const isEditable = !this._config.readOnlyMode && hasWriteAccess && !row.locked; // priority is editable

Expand All @@ -329,12 +314,12 @@ export default class ClinicalAnalysisGrid extends LitElement {

// Current priority
const currentPriorityText = value?.id ?? value ?? "-";
const currentPriorityLabel = priorityRankToColor[value?.rank ?? ""] ?? priorityMap[value ?? ""] ?? "";
const currentPriorityColor = WebUtils.getClinicalAnalysisPriorityColour(value?.rank);

return `
<div class="dropdown">
<button class="${btnClassName}" type="button" data-bs-toggle="dropdown" style="${btnStyle}" ${!isEditable ? "disabled=\"disabled\"" : ""}>
<span class="badge ${currentPriorityLabel} me-auto top-0">
<span class="badge ${currentPriorityColor} me-2 top-0">
${currentPriorityText}
</span>
</button>
Expand All @@ -344,8 +329,8 @@ export default class ClinicalAnalysisGrid extends LitElement {
<li>
<a class="d-flex dropdown-item py-2" data-action="priorityChange" data-priority="${priority.id}" style="cursor:pointer;">
<div class="flex-grow-1">
<div class="">
<span class="badge ${priorityRankToColor[priority?.rank ?? ""] ?? ""}">
<div>
<span class="badge ${WebUtils.getClinicalAnalysisPriorityColour(priority?.rank)}">
${priority.id}
</span>
</div>
Expand All @@ -372,7 +357,7 @@ export default class ClinicalAnalysisGrid extends LitElement {
// const btnClassName = "d-inline-flex align-items-center btn btn-light dropdown-toggle";
const btnClassName = "d-flex justify-content-between align-items-center btn btn-light dropdown-toggle w-100";
// const btnStyle = "display:inline-flex;align-items:center;";
debugger

return `
<div class="dropdown">
<button class="${btnClassName}" type="button" data-bs-toggle="dropdown" ${!isEditable ? "disabled=\"disabled\"" : ""}>
Expand Down
24 changes: 4 additions & 20 deletions src/webcomponents/clinical/clinical-analysis-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
* limitations under the License.
*/

import {LitElement, html, nothing} from "lit";
import {LitElement, html} from "lit";
import UtilsNew from "../../core/utils-new.js";
import LitUtils from "../commons/utils/lit-utils";
import CatalogGridFormatter from "../commons/catalog-grid-formatter.js";
import BioinfoUtils from "../../core/bioinfo/bioinfo-utils.js";
import WebUtils from "../commons/utils/web-utils.js";
import "../commons/forms/data-form.js";
import "../commons/image-viewer.js";
import BioinfoUtils from "../../core/bioinfo/bioinfo-utils";

export default class ClinicalAnalysisView extends LitElement {

Expand Down Expand Up @@ -157,23 +158,6 @@ export default class ClinicalAnalysisView extends LitElement {
}
}

#priorityFormatter(id, data) {
const priorityRankToColor = [
"text-bg-danger",
"text-bg-warning",
"text-bg-primary",
"text-bg-info",
"text-bg-success",
"text-bg-light"
];

if (typeof data?.priority?.rank === "number") {
return priorityRankToColor[data?.priority?.rank - 1] || "";
} else {
return "";
}
}

#setLoading(value) {
this.isLoading = value;
this.requestUpdate();
Expand Down Expand Up @@ -296,7 +280,7 @@ export default class ClinicalAnalysisView extends LitElement {
display: {
template: "${priority.id}",
className: {
"priority.id": (id, data) => `badge ${this.#priorityFormatter(id, data)}`,
"priority.id": (id, data) => `badge ${WebUtils.getClinicalAnalysisPriorityColour(data?.priority?.rank)}`,
},
}
},
Expand Down
18 changes: 10 additions & 8 deletions src/webcomponents/commons/forms/data-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -930,14 +930,16 @@ export default class DataForm extends LitElement {

const content = html`
<div class="form-check">
<input
id="${this._prefix}FilterCheckbox"
type="checkbox"
class="${this._prefix}FilterCheckbox form-check-input"
.checked="${value}"
?disabled="${disabled}"
@click="${e => this.onFilterChange(element, e.currentTarget.checked)}">
<label class="form-check-label" for="${this._prefix}FilterCheckbox">${element.text}</label>
<label class="form-check-label">
<input
id="${this._prefix}${element.field}"
type="checkbox"
class="form-check-input"
.checked="${value}"
?disabled="${disabled}"
@click="${e => this.onFilterChange(element, e.currentTarget.checked)}">
${element.text}
</label>
</div>
`;

Expand Down
13 changes: 13 additions & 0 deletions src/webcomponents/commons/utils/web-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export default class WebUtils {
"JOB": "JOBS",
"FILE": "FILES",
"CLINICAL_ANALYSIS": "CLINICAL_ANALYSIS",
"CLINICAL_VARIANT": "CLINICAL_VARIANT",
"PROJECT": "PROJECTS",
"STUDY": "STUDIES",
"USER": "USERS",
Expand Down Expand Up @@ -96,4 +97,16 @@ export default class WebUtils {
return "-";
}

static getClinicalAnalysisPriorityColour(rank) {
const priorityRankToColor = {
1: "bg-danger", // URGENT
2: "bg-warning", // HIGH
3: "bg-primary", // NORMAL
4: "bg-info", // LOW
5: "bg-light text-dark", // UNKNOWN
};

return priorityRankToColor[rank] ?? "";
}

}
6 changes: 3 additions & 3 deletions src/webcomponents/variant/custom/steiner-report.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ class SteinerReport extends LitElement {

#init() {
this.gridTypes = {
snv: "variantInterpreterCancerSNV",
cnv: "variantInterpreterCancerCNV",
rearrangements: "variantInterpreterRearrangement",
snv: "variant-interpreter-cancer-snv",
cnv: "variant-interpreter-cancer-cnv",
rearrangements: "variant-interpreter-rearrangement",
};

this.callersInfo = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,13 +564,52 @@ class VariantInterpreterBrowserTemplate extends LitElement {
},
{
type: "opencga-variant",
visible: ["SINGLE", "FAMILY"].includes(this.clinicalAnalysis?.type),
config: {
title: "Variants",
query: {
sample: this.clinicalAnalysis.proband.samples.map(s => s.id).join(","),
},
},
},
{
type: "opencga-variant",
visible: this.clinicalAnalysis?.type === "CANCER",
config: {
title: "Small Variants",
query: {
sample: this.clinicalAnalysis.proband.samples.map(s => s.id).join(","),
type: "SNV,INDEL",
},
headerHeight: 0,
},
},
{
type: "opencga-variant",
visible: this.clinicalAnalysis?.type === "CANCER",
config: {
title: "Copy Number Variants",
query: {
sample: this.clinicalAnalysis.proband.samples.map(s => s.id).join(","),
type: "COPY_NUMBER",
},
lollipopVisible: false,
highlightVisible: false,
headerHeight: 0,
},
},
{
type: "opencga-variant",
visible: this.clinicalAnalysis?.type === "CANCER",
config: {
title: "Structural Variants",
query: {
sample: this.clinicalAnalysis.proband.samples.map(s => s.id).join(","),
type: "BREAKEND,INSERTION,DELETION,DUPLICATION",
},
headerHeight: 0,
},
},
...(this.clinicalAnalysis.proband?.samples || []).map(sample => ({
type: "opencga-alignment",
config: {
Expand Down
Loading

0 comments on commit 7529011

Please sign in to comment.