Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
de8425a
wc: include new activeItem property in vertical-menu component #TASK-…
jmjuanes Sep 26, 2025
27a8380
wc: dispatch a changeActiveItem event in vertical-menu when active it…
jmjuanes Sep 26, 2025
cc0465e
wc: add utility to extract current application and tool from hash fra…
jmjuanes Sep 26, 2025
731b1fe
wc: refactor methods to generate links to IVA in webutils #TASK-7762
jmjuanes Sep 26, 2025
15c3372
wc: add method to redirect to the provided app and tool #TASK-7762
jmjuanes Sep 26, 2025
a34c490
wc: fix usage of getIVALink in variant browser grid #TASK-7762
jmjuanes Sep 26, 2025
9275338
wc: fix usage of getIVALink in new filters toolbar #TASK-7762
jmjuanes Sep 26, 2025
10b6634
wc: fix usage of getIVALink in old filters toolbar #TASK-7762
jmjuanes Sep 26, 2025
35dc1e9
wc: fix analysis tools to listen for active item change in vertical m…
jmjuanes Sep 26, 2025
7861cb7
wc: fix organization-admin to listen for active item change in vertic…
jmjuanes Sep 26, 2025
ab5749f
wc: rename active item listener in analysis-tools #TASK-7762
jmjuanes Sep 26, 2025
1c69d55
wc: fix study-admin-iva to listen for active item change in vertical …
jmjuanes Sep 26, 2025
3027bbf
wc: fix study-admin to listen for active item change in vertical menu…
jmjuanes Sep 26, 2025
89d394a
wc: fix operations-admin to listen for active item change in vertical…
jmjuanes Sep 26, 2025
7cae0fe
iva: add tool property in some components #TASK-7762
jmjuanes Sep 26, 2025
a517ba6
Merge branch 'develop' into TASK-7762
jmjuanes Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/sites/iva/iva-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,7 @@ class IvaApp extends LitElement {
content = html`
<organization-admin
.opencgaSession="${this.opencgaSession}"
.tool="${this.queries[this.tool]?.tool}"
@studyUpdateRequest="${this.onStudyUpdateRequest}"
@sessionUpdateRequest="${this.onSessionUpdateRequest}">
</organization-admin>
Expand All @@ -1291,6 +1292,7 @@ class IvaApp extends LitElement {
content = html`
<study-admin
.opencgaSession="${this.opencgaSession}"
.tool="${this.queries[this.tool]?.tool}"
@studyUpdateRequest="${this.onStudyUpdateRequest}">
</study-admin>
`;
Expand All @@ -1299,6 +1301,7 @@ class IvaApp extends LitElement {
content = html`
<study-admin-iva
.opencgaSession="${this.opencgaSession}"
.tool="${this.queries[this.tool]?.tool}"
.settings="${this.settings}"
@studyUpdateRequest="${this.onStudyUpdateRequest}">
</study-admin-iva>
Expand All @@ -1308,6 +1311,7 @@ class IvaApp extends LitElement {
content = html`
<operations-admin
.opencgaSession="${this.opencgaSession}"
.tool="${this.queries[this.tool]?.tool}"
@studyUpdateRequest="${this.onStudyUpdateRequest}">
</operations-admin>
`;
Expand Down Expand Up @@ -1344,7 +1348,8 @@ class IvaApp extends LitElement {
case "analysis-tools":
content = html`
<analysis-tools
.opencgaSession="${this.opencgaSession}">
.opencgaSession="${this.opencgaSession}"
.tool="${this.queries[this.tool]?.tool}">
</analysis-tools>
`;
break;
Expand Down
17 changes: 15 additions & 2 deletions src/webcomponents/commons/analysis/analysis-tools.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {LitElement, html, nothing, render} from "lit";
import {LitElement, html} from "lit";
import WebUtils from "../utils/web-utils.js";
import "../tool-header.js";
import "../view/vertical-menu.js";
import "../../clinical/analysis/mutational-signature-analysis.js";
Expand Down Expand Up @@ -42,19 +43,31 @@ export default class AnalysisTools extends LitElement {
opencgaSession: {
type: Object,
},
tool: {
type: String,
},
};
}

#init() {
this._config = this.getDefaultConfig();
}

onChangeActiveItem(event) {
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
WebUtils.redirectTo(this.opencgaSession, app, tool, {
tool: event.detail.value,
});
}

render() {
return html`
<tool-header .title="${this._config.title}"></tool-header>
<vertical-menu
.opencgaSession="${this.opencgaSession}"
.config="${this._config || {}}">
.activeItem="${this.tool}"
.config="${this._config || {}}"
@changeActiveItem="${event => this.onChangeActiveItem(event)}">
</vertical-menu>
`;
}
Expand Down
3 changes: 2 additions & 1 deletion src/webcomponents/commons/filters-toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,8 @@ export default class FiltersToolbar extends LitElement {

onCopyLink() {
// 1. Generate the url to the tool with the current query
const link = WebUtils.getIVALink(this.opencgaSession, this.toolId, this.preparedQuery);
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
const link = WebUtils.getIVALink(this.opencgaSession, app, tool, this.preparedQuery);

// 2. Copy this link to the user clipboard
UtilsNew.copyToClipboard(link);
Expand Down
3 changes: 2 additions & 1 deletion src/webcomponents/commons/opencga-active-filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,8 @@ export default class OpencgaActiveFilters extends LitElement {

onCopyLink() {
// 1. Generate the url to the tool with the current query
const link = WebUtils.getIVALink(this.opencgaSession, this.toolId, this.query);
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
const link = WebUtils.getIVALink(this.opencgaSession, app, tool, this.query);
// 2. Copy this link to the user clipboard
UtilsNew.copyToClipboard(link);
// 3. Notify user that the link has been copied to the clipboard
Expand Down
40 changes: 25 additions & 15 deletions src/webcomponents/commons/utils/web-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,27 @@ export default class WebUtils {
return (resource && mapResourcePermissionId[resource] && mode) ? `${mode.toUpperCase()}_${mapResourcePermissionId[resource]}` : "";
}

static getIVALink(opencgaSession, tool, query = {}) {
const baseUrl = (new URL(window.location.pathname, window.location.origin));
let queryStr = "";
// Check if query object has been provided
if (query) {
queryStr = "?" + (new URLSearchParams(query)).toString();
}
return `${baseUrl}#${tool}/${opencgaSession.project.id}/${opencgaSession.study.id}${queryStr}`;
}

static getInterpreterLink(opencgaSession, caseId = "") {
static getLink(opencgaSession, app = "", tool = "", query = null) {
const hashItems = [
// ...window.location.hash.replace("#", "").split("/").slice(0, -3), // '#clinical/portal/project/study' --> ['clinical']
"clinical",
"interpreter",
app,
tool,
opencgaSession?.project?.id || "",
opencgaSession?.study?.id || "",
];

return `#${hashItems.filter(Boolean).join("/")}${!!caseId ? "?id=" + caseId : ""}`;
// build the querystring fragment of the URL if a query object is provided
const queryStr = (query && Object.keys(query || {}).length > 0) ? "?" + (new URLSearchParams(query)).toString() : "";

// build and return the internal link
return `#${hashItems.filter(Boolean).join("/")}${queryStr}`;
}

static getIVALink(opencgaSession, app, tool, query = null) {
return (new URL(window.location.pathname, window.location.origin)) + WebUtils.getLink(opencgaSession, app, tool, query);
}

static getInterpreterLink(opencgaSession, query = null) {
return WebUtils.getLink(opencgaSession, "clinical", "interpreter", query);
}

static getClinicalAnalysisPriorityColour(rank) {
Expand All @@ -100,4 +101,13 @@ export default class WebUtils {
});
}

static getApplicationAndToolFromHash(hash = "") {
// '#clinical/portal/project/study' --> ['clinical', 'portal]
// '#portal/project/study' --> ['portal']
return (hash || window.location.hash).replace("#", "").split("/").slice(0, -2);
}

static redirectTo(opencgaSession, app = "", tool = "", query = {}) {
window.location.hash = WebUtils.getLink(opencgaSession, app, tool, query);
}
}
16 changes: 14 additions & 2 deletions src/webcomponents/commons/view/vertical-menu.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {LitElement, html, nothing} from "lit";
import UtilsNew from "../../../core/utils-new.js";
import LitUtils from "../utils/lit-utils.js";

export default class VerticalMenu extends LitElement {

Expand All @@ -17,6 +18,9 @@ export default class VerticalMenu extends LitElement {
opencgaSession: {
type: Object,
},
activeItem: {
type: String,
},
config: {
type: Object,
},
Expand All @@ -35,8 +39,15 @@ export default class VerticalMenu extends LitElement {
...this.getDefaultConfig(),
...this.config,
};
// initialize the active item
if (!this._activeItem) {
}

if (changedProperties.has("config") || changedProperties.has("activeItem")) {
// check if we have to change the active item
if (this.activeItem && this.activeItem !== this._activeItem) {
this._activeItem = this.activeItem;
}
// initialize the active item if not set
if (!this._activeItem && !this.activeItem) {
this._activeItem = this._config.menu[0].submenu[0].id;
}
}
Expand All @@ -46,6 +57,7 @@ export default class VerticalMenu extends LitElement {

onChangeActiveItem(newActiveItem) {
this._activeItem = newActiveItem;
LitUtils.dispatchCustomEvent(this, "changeActiveItem", this._activeItem);
this.requestUpdate();
}

Expand Down
17 changes: 15 additions & 2 deletions src/webcomponents/organization/admin/organization-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/
import {LitElement, html} from "lit";
import WebUtils from "../../commons/utils/web-utils.js";
import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js";
import "./group-admin-browser.js";
import "./user-admin-browser.js";
Expand All @@ -38,7 +39,10 @@ export default class OrganizationAdmin extends LitElement {
static get properties() {
return {
opencgaSession: {
type: Object
type: Object,
},
tool: {
type: String,
},
};
}
Expand All @@ -47,6 +51,13 @@ export default class OrganizationAdmin extends LitElement {
this._config = this.getDefaultConfig();
}

onChangeActiveItem(event) {
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
WebUtils.redirectTo(this.opencgaSession, app, tool, {
tool: event.detail.value,
});
}

render() {
if (!this.opencgaSession?.organization || !OpencgaCatalogUtils.isOrganizationAdmin(this.opencgaSession?.organization, this.opencgaSession?.user?.id)) {
return html`
Expand All @@ -60,7 +71,9 @@ export default class OrganizationAdmin extends LitElement {
<tool-header title="Organization Admin: ${this.opencgaSession?.organization?.id}"></tool-header>
<vertical-menu
.opencgaSession="${this.opencgaSession}"
.config="${this._config || {}}">
.activeItem="${this.tool}"
.config="${this._config || {}}"
@changeActiveItem="${event => this.onChangeActiveItem(event)}">
</vertical-menu>
`;
}
Expand Down
18 changes: 14 additions & 4 deletions src/webcomponents/study/admin/study-admin-iva.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/

import {LitElement, html} from "lit";
import LitUtils from "../../commons/utils/lit-utils";
import NotificationUtils from "../../commons/utils/notification-utils";
import UtilsNew from "../../../core/utils-new";
import WebUtils from "../../commons/utils/web-utils.js";
import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils";
import "../../commons/view/vertical-menu.js";
import "../../commons/pages/restricted-access-page.js";
Expand All @@ -41,6 +39,9 @@ export default class StudyAdminIva extends LitElement {
opencgaSession: {
type: Object,
},
tool: {
type: String,
},
settings: {
type: Object,
},
Expand Down Expand Up @@ -78,6 +79,13 @@ export default class StudyAdminIva extends LitElement {
return (title === "Clinical Analysis Browser") ? "Clinical Analysis Portal" : title;
}

onChangeActiveItem(event) {
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
WebUtils.redirectTo(this.opencgaSession, app, tool, {
tool: event.detail.value,
});
}

render() {
const isOrganizationAdmin = OpencgaCatalogUtils.isOrganizationAdmin(this.opencgaSession?.organization, this.opencgaSession?.user?.id);
const isAdmin = OpencgaCatalogUtils.isAdmin(this.opencgaSession?.study, this.opencgaSession?.user?.id);
Expand All @@ -94,7 +102,9 @@ export default class StudyAdminIva extends LitElement {
<tool-header title="${this._config.name}"></tool-header>
<vertical-menu
.opencgaSession="${this.opencgaSession}"
.config="${this._config || {}}">
.activeItem="${this.tool}"
.config="${this._config || {}}"
@changeActiveItem="${event => this.onChangeActiveItem(event)}">
</vertical-menu>
`;
}
Expand Down
15 changes: 14 additions & 1 deletion src/webcomponents/study/admin/study-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import {LitElement, html} from "lit";
import WebUtils from "../../commons/utils/web-utils.js";
import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js";
import "./study-admin-users.js";
import "./study-admin-permissions.js";
Expand Down Expand Up @@ -44,13 +45,23 @@ export default class StudyAdmin extends LitElement {
opencgaSession: {
type: Object,
},
tool: {
type: String,
},
};
}

#init() {
this._config = this.getDefaultConfig();
}

onChangeActiveItem(event) {
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
WebUtils.redirectTo(this.opencgaSession, app, tool, {
tool: event.detail.value,
});
}

render() {
const isOrganizationAdmin = OpencgaCatalogUtils.isOrganizationAdmin(this.opencgaSession?.organization, this.opencgaSession?.user?.id);
const isAdmin = OpencgaCatalogUtils.isAdmin(this.opencgaSession?.study, this.opencgaSession?.user?.id);
Expand All @@ -67,7 +78,9 @@ export default class StudyAdmin extends LitElement {
<tool-header title="${this._config.name}"></tool-header>
<vertical-menu
.opencgaSession="${this.opencgaSession}"
.config="${this._config || {}}">
.activeItem="${this.tool}"
.config="${this._config || {}}"
@changeActiveItem="${event => this.onChangeActiveItem(event)}">
</vertical-menu>
`;
}
Expand Down
15 changes: 14 additions & 1 deletion src/webcomponents/study/admin/variant/operations-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import {LitElement, html} from "lit";
import WebUtils from "../../../commons/utils/web-utils.js";
import OpencgaCatalogUtils from "../../../../core/clients/opencga/opencga-catalog-utils";
import "../../../variant/operation/variant-index-operation.js";
import "../../../variant/operation/variant-stats-index-operation.js";
Expand All @@ -40,6 +41,9 @@ export default class OperationsAdmin extends LitElement {
opencgaSession: {
type: Object
},
tool: {
type: String,
},
};
}

Expand All @@ -48,6 +52,13 @@ export default class OperationsAdmin extends LitElement {
this._config = this.getDefaultConfig();
}

onChangeActiveItem(event) {
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
WebUtils.redirectTo(this.opencgaSession, app, tool, {
tool: event.detail.value,
});
}

render() {
const isOrganizationAdmin = OpencgaCatalogUtils.isOrganizationAdmin(this.opencgaSession?.organization, this.opencgaSession?.user?.id);
const isAdmin = OpencgaCatalogUtils.isAdmin(this.opencgaSession?.study, this.opencgaSession?.user?.id);
Expand All @@ -64,7 +75,9 @@ export default class OperationsAdmin extends LitElement {
<tool-header title="${this._config.name}"></tool-header>
<vertical-menu
.opencgaSession="${this.opencgaSession}"
.config="${this._config || {}}">
.activeItem="${this.tool}"
.config="${this._config || {}}"
@changeActiveItem="${event => this.onChangeActiveItem(event)}">
</vertical-menu>
`;
}
Expand Down
3 changes: 2 additions & 1 deletion src/webcomponents/variant/variant-browser-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,8 @@ export default class VariantBrowserGrid extends LitElement {
break;
case "copy-link":
// 1. Generate the URL to this variant
const link = WebUtils.getIVALink(this.opencgaSession, this.toolId, {id: variant.id});
const [app, tool] = WebUtils.getApplicationAndToolFromHash();
const link = WebUtils.getIVALink(this.opencgaSession, app, tool, {id: variant.id});
// 2. Copy this link to the clipboard
UtilsNew.copyToClipboard(link);
// 3. Notify user that link has been copied to the clipboard
Expand Down
Loading