From ecfbf10f06155b4490b58d8b626efaad089e0038 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 20 Mar 2024 13:38:55 +0100 Subject: [PATCH 001/177] core - Fixed minor typo #TASK-5866 Signed-off-by: gpveronica --- src/core/clients/opencga/opencga-client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/clients/opencga/opencga-client.js b/src/core/clients/opencga/opencga-client.js index 9164a1ca1..093072572 100644 --- a/src/core/clients/opencga/opencga-client.js +++ b/src/core/clients/opencga/opencga-client.js @@ -220,7 +220,7 @@ export class OpenCGAClient { if (!this.clients.has("organization")) { this.clients.set("organization", new Organization(this._config)); } - return this.clients.get("organizaton"); + return this.clients.get("organization"); } /* From 42c9cc832dddf7a8bc0b5b60211564d62ca2590d Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 28 Mar 2024 14:14:54 +0100 Subject: [PATCH 002/177] wp - Initial commit organizations Signed-off-by: gpveronica --- src/sites/iva/conf/config.js | 14 +- src/sites/iva/iva-app.js | 13 + .../admin/organization-admin-audit.js | 410 ++++++++++++++++++ .../organization/admin/organization-admin.js | 210 +++++++++ 4 files changed, 644 insertions(+), 3 deletions(-) create mode 100644 src/webcomponents/organization/admin/organization-admin-audit.js create mode 100644 src/webcomponents/organization/admin/organization-admin.js diff --git a/src/sites/iva/conf/config.js b/src/sites/iva/conf/config.js index 8cadce5fe..466035ce6 100644 --- a/src/sites/iva/conf/config.js +++ b/src/sites/iva/conf/config.js @@ -15,7 +15,6 @@ * limitations under the License. */ - const hosts = [ { id: "prod", @@ -32,11 +31,11 @@ const hosts = [ ]; const opencga = { - host: hosts[1].url, + host: hosts[2].url, version: "v2", organizations: [], cookie: { - prefix: "iva-" + hosts[1].id, + prefix: "iva-" + hosts[2].id, secure: true, }, sso: { @@ -752,6 +751,15 @@ const SUITE = {
` }, menu: [ + { + id: "organization-admin", + name: "Organizations Admin", + fa_icon: "fas fa-file-invoice", + icon: "img/tools/icons/variant_browser.svg", + description: "", + visibility: "public", + featured: true, + }, { id: "study-admin", name: "Study admin", diff --git a/src/sites/iva/iva-app.js b/src/sites/iva/iva-app.js index ea9b8e26a..4bd6c13ca 100644 --- a/src/sites/iva/iva-app.js +++ b/src/sites/iva/iva-app.js @@ -81,6 +81,7 @@ import "../../webcomponents/clinical/clinical-analysis-create.js"; import "../../webcomponents/file/file-manager.js"; import "../../webcomponents/job/job-monitor.js"; import "../../webcomponents/loading-spinner.js"; +import "../../webcomponents/organization/admin/organization-admin.js" import "../../webcomponents/project/projects-admin.js"; import "../../webcomponents/study/admin/study-admin.js"; import "../../webcomponents/study/admin/study-admin-iva.js"; @@ -233,6 +234,7 @@ class IvaApp extends LitElement { "diseasePanelUpdate", "clinicalAnalysis", // Admin + "organization-admin", "study-admin", "study-admin-iva", // "catalog-admin", @@ -2016,6 +2018,17 @@ class IvaApp extends LitElement { } + ${this.config.enabledComponents["organization-admin"] ? html` + +
+ + +
+ ` : null} + ${this.config.enabledComponents["projects-admin"] ? html`
diff --git a/src/webcomponents/organization/admin/organization-admin-audit.js b/src/webcomponents/organization/admin/organization-admin-audit.js new file mode 100644 index 000000000..ea55c2621 --- /dev/null +++ b/src/webcomponents/organization/admin/organization-admin-audit.js @@ -0,0 +1,410 @@ +/** + * Copyright 2015-2019 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement, nothing} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import GridCommons from "../../commons/grid-commons.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import {guardPage} from "../../commons/html-utils.js"; + +export default class OrganizationAdminAudit extends LitElement { + + constructor() { + super(); + + // Set status and init private properties + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + opencgaSession: { + type: Object + }, + studyId: { + type: String + }, + study: { + type: Object + }, + query: { + type: Object + }, + config: { + type: Object + } + }; + } + + #init() { + this._prefix = UtilsNew.randomString(8); + + this._filters = []; + this.query = {}; + this.sortedUserIds = []; + this.gridId = this._prefix + "AuditBrowserGrid"; + this.actionValues = ["SEARCH", "LINK", "INFO", "CREATE"]; + this.resourceTypeValues = ["AUDIT", "USER", "PROJECT", "STUDY", "FILE", "SAMPLE", "JOB", "INDIVIDUAL", "COHORT", "DISEASE_PANEL", + "FAMILY", "CLINICAL_ANALYSIS", "INTERPRETATION", "VARIANT", "ALIGNMENT", "CLINICAL", "EXPRESSION", "FUNCTIONAL"]; + this.statusTypeValues = ["SUCCESS", "ERROR"]; + } + + connectedCallback() { + super.connectedCallback(); + + this._config = {...this.getDefaultConfig(), ...this.config}; + this.gridCommons = new GridCommons(this.gridId, this, this._config); + } + + update(changedProperties) { + if (changedProperties.has("studyId")) { + for (const project of this.opencgaSession.projects) { + for (const study of project.studies) { + if (study.id === this.studyId || study.fqn === this.studyId) { + this.study = {...study}; + break; + } + } + } + } + + if (changedProperties.has("study")) { + this.studyObserver(); + } + if (changedProperties.has("query")) { + this.propertyObserver(); + } + super.update(changedProperties); + } + + async studyObserver() { + this.groupsMap = new Map(); + try { + const resp = await this.opencgaSession.opencgaClient.studies() + .groups(this.study.fqn); + const groups = resp.responses[0].results; + if (groups[0].users) { + for (const group of groups) { + this.groupsMap.set(group.id, group.users); + } + } else { + for (const group of response.responses[0].results) { + this.groupsMap.set(group.id, group.userIds.map(u => { + return {id: u, name: u}; + })); + } + } + this.users = this.groupsMap.get("@members"); + this.sortedUserIds = [...this.groupsMap.get("@members").map(user => user.id).sort()]; + // With the requestUpdate, work to get users for the filter + this.requestUpdate(); + } catch (err) { + console.log("An error occurred fetching users: ", err); + } + this.renderRemoteTable(); + } + + propertyObserver() { + this.renderRemoteTable(); + } + + renderRemoteTable() { + if (this.opencgaSession?.opencgaClient && this.study) { + this.table = $("#" + this.gridId); + this.table.bootstrapTable("destroy"); + this.table.bootstrapTable({ + theadClasses: "table-light", + buttonsClass: "light", + columns: this._getDefaultColumns(), + method: "get", + sidePagination: "server", + iconsPrefix: GridCommons.GRID_ICONS_PREFIX, + icons: GridCommons.GRID_ICONS, + uniqueId: "id", + // Table properties + pagination: this._config.pagination, + pageSize: this._config.pageSize, + pageList: this._config.pageList, + // paginationVAlign: "both", + formatShowingRows: this.gridCommons.formatShowingRows, + showExport: this._config.showExport, + detailView: this._config.detailView, + detailFormatter: this.detailFormatter, + gridContext: this, + // formatLoadingMessage: () => "
", + loadingTemplate: () => GridCommons.loadingFormatter(), + ajax: params => { + const query = { + study: this.study.fqn, + limit: params.data.limit, + skip: params.data.offset || 0, + count: !this.table.bootstrapTable("getOptions").pageNumber || this.table.bootstrapTable("getOptions").pageNumber === 1, + ...this.query + }; + // Store the current filters + // this.lastFilters = {..._filters}; + this.opencgaSession.opencgaClient.studies().searchAudit(this.study.fqn, query) + .then(res => { + params.success(res); + }) + .catch(e => { + console.error(e); + params.error(e); + }); + }, + responseHandler: response => { + const result = this.gridCommons.responseHandler(response, $(this.table).bootstrapTable("getOptions")); + return result.response; + }, + onClickRow: (row, selectedElement, field) => this.gridCommons.onClickRow(row.id, row, selectedElement), + onDblClickRow: (row, element, field) => { + // We detail view is active we expand the row automatically. + // FIXME: Note that we use a CSS class way of knowing if the row is expand or collapse, this is not ideal but works. + if (this._config.detailView) { + if (element[0].innerHTML.includes("fa-plus")) { + this.table.bootstrapTable("expandRow", element[0].dataset.index); + } else { + this.table.bootstrapTable("collapseRow", element[0].dataset.index); + } + } + }, + onLoadSuccess: data => { + this.gridCommons.onLoadSuccess(data, 1); + }, + onLoadError: (e, restResponse) => this.gridCommons.onLoadError(e, restResponse), + onPostBody: data => { + // Add tooltips? + } + }); + } + } + + detailFormatter(index, row) { + return ` +
+

Action Params

+
${JSON.stringify(row.params, null, 2)}
+
+ `; + } + + _getDefaultColumns() { + return [ + { + title: "Audit Record ID", + field: "id", + }, + { + title: "User ID", + field: "userId", + }, + { + title: "Study ID", + field: "studyId", + }, + { + title: "Action", + field: "action" + }, + { + title: "Resource Type", + field: "resource" + }, + { + title: "Resource ID", + field: "resourceId", + }, + { + title: "Date", + field: "date", + formatter: value => value ? UtilsNew.dateFormatter(UtilsNew.getDatetime(value)) : "NA" + }, + { + title: "Status", + field: "status.name", + }, + ]; + } + + onFilterChange(key, value) { + if (value && value !== "") { + this.query = {...this.query, ...{[key]: value}}; + } else { + delete this.query[key]; + this.query = {...this.query}; + } + } + + clear(e) { + this.query = {}; + } + + render() { + if (!OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { + return guardPage("No permission to view this page"); + } + + return html` +
+
+ + ${~this._config.filter.sections[0].filters.findIndex(field => field.id === "userId") ? html` + +
+ + +
+ `: nothing} + + ${~this._config.filter.sections[0].filters.findIndex(field => field.id === "action") ? html` + +
+ + +
+ ` : nothing} + + ${~this._config.filter.sections[0].filters.findIndex(field => field.id === "resource") ? html` + +
+ + +
+ ` : nothing} + + ${~this._config.filter.sections[0].filters.findIndex(field => field.id === "status") ? html` + +
+ + +
+ ` : nothing} + +
+ +
+
+
+ +
+
+
+ + + + `; + } + + getDefaultConfig() { + return { + filter: { + sections: [ + { + title: "", + filters: [ + {id: "userId"}, + {id: "resource"}, + {id: "action"}, + {id: "status"}, + ] + } + ], + }, + pagination: true, + pageSize: 10, + pageList: [10, 25, 50], + showExport: false, + detailView: true, + multiSelection: false, + showSelectCheckbox: true, + showToolbar: true, + showActions: true, + }; + } + + +} + +customElements.define("organization-admin-audit", OrganizationAdminAudit); diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js new file mode 100644 index 000000000..89a4f7780 --- /dev/null +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -0,0 +1,210 @@ +/** + * Copyright 2015-2024 OpenCB * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {LitElement, html} from "lit"; +import UtilsNew from "../../../core/utils-new"; +import LitUtils from "../../commons/utils/lit-utils"; +import "./group-admin-browser.js"; +import "./user-admin-browser.js"; + +// FIXME VERY IMPORTANT: +// ******************************************** +// Enable only for organization owner or admin +// ******************************************** + +export default class OrganizationAdmin extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + organizationId: { + type: String, + }, + opencgaSession: { + type: Object + }, + }; + } + + #init() { + this._config = this.getDefaultConfig(); + this._activeMenuItem = ""; + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("organizationId")) { + this.organizationIdObserver(); + } + + super.update(changedProperties); + } + + organizationIdObserver() { + if (this.organizationId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + .info(this.organizationId) + .then(response => { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + // this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); + this.#setLoading(false); + }); + + } + } + + // --- RENDER METHOD --- + render() { + if (this.organization) { + return html` + + + + `; + } + } + + getDefaultConfig() { + const menu = [ + { + id: "dashboard", + name: "Dashboard", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ + // TODO: pending refactor and fix + { + id: "audit", + name: "Audit", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + ], + }, + { + id: "manage", + name: "Manage", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ + { + id: "groups", + name: "Groups", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, organization) => html` + + + `, + }, + { + id: "users", + name: "Users", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, organization) => html` + + + `, + }, + { + id: "settings", + name: "Settings", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + { + id: "studies", + name: "Projects/Studies", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + ], + }, + { + id: "configure", + name: "Configure", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ + { + id: "identity-providers", + name: "Identity Providers", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + { + id: "optimization", + name: "Optimizations", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + ], + }, + ]; + + return { + name: "Organization Admin", + logo: "", + icon: "", + visibility: "", + menu: menu, + }; + } + +} + +customElements.define("organization-admin", OrganizationAdmin); From 3449e3d16c43a18cdde15f53015c47df0a43e527 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 28 Mar 2024 14:17:20 +0100 Subject: [PATCH 003/177] wp - Custom vertical navbar Signed-off-by: gpveronica --- .../commons/layouts/custom-vertical-navbar.js | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/webcomponents/commons/layouts/custom-vertical-navbar.js b/src/webcomponents/commons/layouts/custom-vertical-navbar.js index aa88e9c14..cc837dfc5 100644 --- a/src/webcomponents/commons/layouts/custom-vertical-navbar.js +++ b/src/webcomponents/commons/layouts/custom-vertical-navbar.js @@ -35,6 +35,9 @@ export default class CustomVerticalNavBar extends LitElement { // --- PROPERTIES --- static get properties() { return { + organization: { + type: Object, + }, studyId: { type: String, }, @@ -80,7 +83,7 @@ export default class CustomVerticalNavBar extends LitElement { // --- LIT LIFECYCLE --- update(changedProperties) { - if (changedProperties.has("studyId") || changedProperties.has("opencgaSession")) { + if (changedProperties.has("studyId")) { this.studyIdObserver(); } if (changedProperties.has("activeMenuItem")) { @@ -99,11 +102,13 @@ export default class CustomVerticalNavBar extends LitElement { // --- OBSERVERS --- studyIdObserver() { - for (const project of this.opencgaSession?.projects) { - for (const study of project.studies) { - if (study.id === this.studyId || study.fqn === this.studyId) { - this.study = study; - break; + if (this.studyId && this.opencgaSession) { + for (const project of this.opencgaSession?.projects) { + for (const study of project.studies) { + if (study.id === this.studyId || study.fqn === this.studyId) { + this.study = study; + break; + } } } } @@ -301,7 +306,11 @@ export default class CustomVerticalNavBar extends LitElement {
- ${subItem.render(this.opencgaSession, this.study)} + ${ + (this.organization) ? + subItem.render(this.opencgaSession, this.organization) : + subItem.render(this.opencgaSession, this.study) + }
`) @@ -339,9 +348,7 @@ export default class CustomVerticalNavBar extends LitElement { // --- DEFAULT CONFIG --- getDefaultConfig() {} - } customElements.define("custom-vertical-navbar", CustomVerticalNavBar); - From 6ad8f2ea96c19d9c61fc6f649a76fb42c689c6a0 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 28 Mar 2024 14:17:40 +0100 Subject: [PATCH 004/177] wp - WiP Group components Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 237 +++++++++++++ .../organization/admin/group-admin-create.js | 216 ++++++++++++ .../organization/admin/group-admin-grid.js | 327 ++++++++++++++++++ .../organization/admin/group-admin-update.js | 306 ++++++++++++++++ 4 files changed, 1086 insertions(+) create mode 100644 src/webcomponents/organization/admin/group-admin-browser.js create mode 100644 src/webcomponents/organization/admin/group-admin-create.js create mode 100644 src/webcomponents/organization/admin/group-admin-grid.js create mode 100644 src/webcomponents/organization/admin/group-admin-update.js diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js new file mode 100644 index 000000000..c762cd414 --- /dev/null +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -0,0 +1,237 @@ +/** + * Copyright 2015-2024 OpenCB * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * The group admin browser component has two key responsibilities: + * 1. Retrieving groups per study + * 2. Rendering the graphic filters if enabled and grid. + * Accepted properties are: + * - A single study + * - An organization with multiple projects/studies + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../commons/utils/lit-utils"; +import UtilsNew from "../../../core/utils-new"; +import "./group-admin-grid.js"; + +export default class GroupAdminBrowser extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + studyId: { + type: String, + }, + study: { + type: Object, + }, + organizationId: { + type: String, + }, + organization: { + type: Object, + }, + opencgaSession: { + type: Object, + }, + // QUESTION: pending to decide if we allow browser settings here. + settings: { + type: Object, + }, + }; + } + + #init() { + this.COMPONENT_ID = "groups-admin-browser"; + + this._study = {}; + this._groups = []; + this._config = this.getDefaultConfig(); + this.isLoading = false; + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #getGroups(isSingleStudy) { + // FIXME: refactor + // If the component is used for managing the groups of the whole organization + this._groups = []; + if (isSingleStudy) { + this._study.groups?.forEach(group => { + let protectedGroup = false; + if (group.id === "@admins" || group.id === "@members") { + protectedGroup = true; + } + const newGroup = { + studyId: this._study.id, + groupId: group.id, + protectedGroup: protectedGroup, + }; + this._groups.push(newGroup); + }); + } else { + // FIXME 20240321 Vero: + // ********************************************************************************* + // The method info from the ws Organizations is returning an empty array of projects. + // The following bug has been created: + // https://app.clickup.com/t/36631768/TASK-5923. + // Meanwhile, I use the list of projects from opencgaSession. + // ********************************************************************************* + /* + this.organization?.projects?.forEach(project => { + project.studies?.forEach(study => { + study.groups?.forEach(group => { + const newGroup = { + studyId: study.id, + groupId: group.id, + }; + this._groups.push(newGroup); + }); + }); + }); + */ + this.opencgaSession?.projects?.forEach(project => { + project.studies?.forEach(study => { + study.groups?.forEach(group => { + const newGroup = { + studyId: study.id, + groupId: group.id, + creationDate: group.creationDate, + }; + this._groups.push(newGroup); + }); + }); + }); + } + } + + update(changedProperties) { + if (changedProperties.has("organization") || + changedProperties.has("study") || + changedProperties.has("opencgaSession")) { + this.#getGroups(!this.organization); + } + if (changedProperties.has("settings")) { + this.settingsObserver(); + } + super.update(changedProperties); + } + + settingsObserver() { + this._config = { + ...this.getDefaultConfig(), + ...this.settings, + }; + } + + studyIdObserver() { + if (this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this._study = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + this._study = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + this.#setLoading(false); + }); + } else { + this._study = {}; + } + } + + organizationIdObserver() { + if (this.organizationId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + .info(this.organizationId) + .then(response => { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); + this.#setLoading(false); + }); + + } + } + + renderFilterGraphics() { + if (this._config.showGraphicFilters) { + return html ` + + `; + } + } + + render() { + if (Object.keys(this._groups).length === 0) { + return html ` +
+ + This organization does not have studies yet. + Please create some projects or studies to see the list of existent groups. +
+ `; + } + + return html ` + + ${this.renderFilterGraphics()} + + + + `; + } + + getDefaultConfig() { + return { + showGraphicFilters: false, + }; + } + +} + +customElements.define("group-admin-browser", GroupAdminBrowser); diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js new file mode 100644 index 000000000..0b5c14a33 --- /dev/null +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -0,0 +1,216 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; + +export default class GroupAdminCreate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.group = {}; + this.isLoading = false; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + defaultLayout: "horizontal", + buttonOkText: "Create" + }; + this._config = this.getDefaultConfig(); + } + + #initOriginalObjects() { + this.group = {}; + this.allowedValues = []; + + // Read Projects and Study to prepare the allowed values in the Study select menu + if (this.opencgaSession?.projects) { + // Prepare allowedValues for the select options menu + for (const project of this.opencgaSession.projects) { + const fields = []; + for (const study of project.studies) { + if (OpencgaCatalogUtils.isAdmin(study, this.opencgaSession.user.id)) { + fields.push({id: study.fqn, name: study.fqn}); + } + } + if (fields.length > 0) { + this.allowedValues.push({name: `Project '${project.name}'`, fields: fields}); + } + } + } + + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("displayConfig")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + } + if (changedProperties.has("opencgaSession")) { + this.opencgaSessionObserver(); + } + super.update(changedProperties); + } + + opencgaSessionObserver() { + // Read Projects and Study to prepare the select studies menu + this.#initOriginalObjects(); + } + + onFieldChange(e, field) { + const param = field || e.detail.param; + // 1. Update group id + if (param === "id") { + // QUESTION 20240325 Vero: verify group name starts with @? + this.group.id = e.detail.data.id; + } + // 2. Update the list of studies + if (param === "fqn") { + this.group.listStudies = e.detail.value?.length > 0 ? e.detail.value?.split(",") : []; + } + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Clear group", + message: "Are you sure to clear?", + ok: () => { + this.group = {}; + this._config = this.getDefaultConfig(); + this.requestUpdate(); + }, + }); + } + + onSubmit() { + this.#setLoading(true); + const groupPromises = this.group.listStudies + .map(study => { + let error; + return this.opencgaSession.opencgaClient.studies() + .updateGroups(study, {id: this.group.id}, {action: "ADD"}) + .then(() => { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `Group Create`, + message: `Group ${this.group.id} created in study ${study} correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_ERROR, { + message: `Error creating group: ${reason.message || reason}`, + }); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "groupCreate", {}, { + id: this.group.id, + study: study, + }, error); + }); + }); + + Promise.all(groupPromises) + .finally(() => { + this.#setLoading(false); + this.#initOriginalObjects(); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); + }); + } + + render() { + if (this.isLoading) { + return html``; + } + + return html` + + `; + } + + getDefaultConfig() { + return { + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + title: "General Information", + elements: [ + { + title: "Group ID", + field: "id", + type: "input-text", + required: true, + display: { + placeholder: "Add a short ID...", + helpMessage: "short group id...", + }, + }, + { + title: "Study", + field: "fqn", + type: "select", + multiple: true, + all: true, + required: true, + allowedValues: this.allowedValues, + display: { + placeholder: "Select study or studies..." + }, + }, + ], + }, + ], + }; + } + +} + +customElements.define("group-admin-create", GroupAdminCreate); diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js new file mode 100644 index 000000000..de4b825a9 --- /dev/null +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -0,0 +1,327 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html, nothing} from "lit"; +import GridCommons from "../../commons/grid-commons"; +import UtilsNew from "../../../core/utils-new"; +import ModalUtils from "../../commons/modal/modal-utils"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; +import "./group-admin-create.js"; +import "./group-admin-update.js"; + +export default class GroupAdminGrid extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + toolId: { + type: String, + }, + opencgaSession: { + type: Object + }, + groups: { + type: Array + }, + active: { + type: Boolean + }, + config: { + type: Object + }, + }; + } + + #init() { + this.COMPONENT_ID = "group-grid"; + this._prefix = UtilsNew.randomString(8); + this.gridId = this._prefix + this.COMPONENT_ID; + this.active = true; + this._config = this.getDefaultConfig(); + } + + updated(changedProperties) { + if ((changedProperties.has("opencgaSession") || + changedProperties.has("toolId") || + changedProperties.has("config") || + changedProperties.has("active")) && this.active) { + this.propertyObserver(); + } + } + + propertyObserver() { + // With each property change we must be updated config and create the columns again. No extra checks are needed. + this._config = { + ...this.getDefaultConfig(), + ...this.config, + }; + + this.gridCommons = new GridCommons(this.gridId, this, this._config); + + // Config for the grid toolbar + this.toolbarSetting = { + ...this._config, + }; + + this.toolbarConfig = { + toolId: this.toolId, + resource: "GROUPS", + columns: this._getDefaultColumns(), + create: { + display: { + modalTitle: "Group Create", + modalDraggable: true, + modalCyDataName: "modal-create", + modalSize: "modal-lg" + // disabled: true, + // disabledTooltip: "...", + }, + render: () => html ` + + ` + }, + }; + this.renderTable(); + } + + renderTable() { + if (this.groups?.length > 0) { + this.renderLocalTable(); + } + this.requestUpdate(); + } + + renderLocalTable() { + this.table = $("#" + this.gridId); + this.table.bootstrapTable("destroy"); + this.table.bootstrapTable({ + theadClasses: "table-light", + buttonsClass: "light", + columns: this._getDefaultColumns(), + sidePagination: "server", + // Josemi Note 2024-01-18: we have added the ajax function for local variants also to support executing + // async calls when getting additional data from columns extensions. + ajax: params => { + const tableOptions = $(this.table).bootstrapTable("getOptions"); + const limit = params.data.limit || tableOptions.pageSize; + const skip = params.data.offset || 0; + const rows = this.groups.slice(skip, skip + limit); + + // Get data for extensions + this.gridCommons.prepareDataForExtensions(this.COMPONENT_ID, this.opencgaSession, null, rows) + .then(() => params.success(rows)) + .catch(error => params.error(error)); + }, + // Josemi Note 2024-01-18: we use this method to tell bootstrap-table how many rows we have in our data + responseHandler: response => { + return { + total: this.groups.length, + rows: response, + }; + }, + iconsPrefix: GridCommons.GRID_ICONS_PREFIX, + icons: GridCommons.GRID_ICONS, + + // Set table properties, these are read from config property + uniqueId: "id", + pagination: this._config.pagination, + pageSize: this._config.pageSize, + pageList: this._config.pageList, + detailView: this._config.detailView, + gridContext: this, + loadingTemplate: () => GridCommons.loadingFormatter(), + }); + } + + async onActionClick(e, value, row) { + const action = e.currentTarget.dataset.action; + switch (action) { + case "edit": + this.groupId = row.groupId; + this.studyId = row.studyId; + debugger + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}UpdateModal`); + break; + case "delete": + this.groupId = row.groupId; + this.studyId = row.studyId; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}DeleteModal`); + break; + default: + break; + } + } + + _getDefaultColumns() { + this._columns = [ + { + title: "Group ID", + field: "groupId", + scope: "col", + visible: this.gridCommons.isColumnVisible("id") + }, + { + title: "Study ID", + field: "studyId", + visible: this.gridCommons.isColumnVisible("individualId") + }, + { + title: "Creation Date", + field: "creationDate", + formatter: CatalogGridFormatter.dateFormatter, + sortable: true, + visible: this.gridCommons.isColumnVisible("creationDate") + }, + ]; + + if (this._config.annotations?.length > 0) { + this.gridCommons.addColumnsFromAnnotations(this._columns, CatalogGridFormatter.customAnnotationFormatter, this._config); + } + + if (this.opencgaSession && this._config.showActions) { + this._columns.push({ + id: "actions", + title: "Actions", + field: "actions", + formatter: () => ` +
+ + + +
`, + events: { + "click button": (e, value, row) => this.onActionClick(e, value, row), + }, + }); + } + + this._columns = this.gridCommons.addColumnsFromExtensions(this._columns, this.COMPONENT_ID); + return this._columns; + } + + renderModalUpdate() { + return ModalUtils.create(this, `${this._prefix}UpdateModal`, { + display: { + modalTitle: `Group Update: group ${this.groupId} in study ${this.studyId}`, + modalDraggable: true, + modalCyDataName: "modal-update", + modalSize: "modal-lg" + }, + render: active => html` + + + `, + }); + } + + renderModalDelete() { + return ModalUtils.create(this, `${this._prefix}DeleteModal`, { + display: { + modalTitle: `Group Delete: ${this.groupId}`, + modalDraggable: true, + modalCyDataName: "modal-update", + modalSize: "modal-lg" + }, + render: active => html` + + + `, + }); + } + + renderToolbar() { + if (this._config.showToolbar) { + return html ` + + + `; + } + } + + render() { + return html` + + ${this.renderToolbar()} + +
+
+
+ + ${this.renderModalDelete()} + + ${this.renderModalUpdate()} + `; + } + + getDefaultConfig() { + return { + pagination: true, + pageSize: 10, + pageList: [5, 10, 25], + multiSelection: false, + showSelectCheckbox: false, + // detailView: true, + + showToolbar: true, + showActions: true, + + showCreate: true, + showExport: false, + showSettings: false, + exportTabs: ["download", "link", "code"], + }; + } + +} + +customElements.define("group-admin-grid", GroupAdminGrid); diff --git a/src/webcomponents/organization/admin/group-admin-update.js b/src/webcomponents/organization/admin/group-admin-update.js new file mode 100644 index 000000000..3558f6c6b --- /dev/null +++ b/src/webcomponents/organization/admin/group-admin-update.js @@ -0,0 +1,306 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import FormUtils from "../../commons/forms/form-utils"; +import NotificationUtils from "../../commons/utils/notification-utils"; + +export default class GroupAdminUpdate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + groupId: { + type: String + }, + studyId: { + type: String, + }, + active: { + type: Boolean, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.group = {}; + this.groupId = ""; + this.studyId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this.displayConfigDefault = { + style: "margin: 10px", + defaultLayout: "horizontal", + labelAlign: "right", + labelWidth: 3, + buttonOkText: "Update", + }; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initGroup() { + // 1. Group contains params: (a) id: e.g. "@admins", (b) userIds: e.g. ["test"] + this.group = this._study.groups.find(group => group.id === this.groupId); + // 2. In the update form, we need to manage as well the permissions of this group. + // Retrieve ACL permissions. Check if this study group has acl + // CAUTION: study does not have acl? + const groupPermissions = this._study?.acl + ?.find(acl => acl.member === this.opencgaSession.user.id)?.groups + ?.find(group => group.id === this.group.id)?.permissions || []; + // 3. Add current permissions and template key to the object group + this.group = { + ...this.group, + permissions: groupPermissions, + template: "", // Fixme: not sure how to retrieve template + }; + this.initOriginalObjects(); + + } + + initOriginalObjects() { + this._group = UtilsNew.objectClone(this.group); + this.updatedFields = {}; + } + + update(changedProperties) { + if ((changedProperties.has("groupId") || (changedProperties.has("studyId")) && this.active)) { + this.groupIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + groupIdObserver() { + if (this.groupId && this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this._study = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initGroup(); + }) + .catch(reason => { + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "studyInfo", this.study, {}, error); + this.#setLoading(false); + }); + } + } + + // Uncomment to post-process data-form manipulation + // onFieldChange(e) { + // debugger + // this.updatedFields = e.detail?.updatedFields || {}; + // this.requestUpdate(); + // } + + onFieldChange(e) { + const param = e.detail.param; + this.updatedFields = FormUtils.getUpdatedFields( + this.group, + this.updatedFields, + param, + e.detail.value, + e.detail.action); + if (param === "template") { + this._group.template = e.detail.value; + } + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Discard changes", + message: "Are you sure you want to discard the changes made?", + ok: () => { + this.initOriginalObjects(); + this.requestUpdate(); + // We need to dispatch a component clear event + LitUtils.dispatchCustomEvent(this, "groupClear", null, { + group: this._group, + }); + }, + }); + } + + onSubmit() { + const paramsAction = { + action: "SET" + }; + const studyAclParams = { + study: this.studyId, + template: this._group.template, + // permissions: this._group.permissions, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .updateAcl(this.groupId, paramsAction, studyAclParams) + .then(response => { + this.group = UtilsNew.objectClone(response.responses[0].results[0]); + this.updatedFields = {}; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `Group Update`, + message: `Group ${this.group.id} updated correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "updateGroup", this.group, {}, error); + this.#setLoading(false); + }); + } + + render() { + return html ` + + + `; + } + + getDefaultConfig() { + return { + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig, + sections: [ + { + title: "Details", + elements: [ + { + title: "Group ID", + field: "id", + type: "input-text", + required: true, + display: { + placeholder: "Add a short ID...", + helpMessage: "short group id...", + }, + }, + ], + }, + { + title: "Permissions", + elements: [ + { + title: "Templates", + field: "template", + type: "toggle-buttons", + allowedValues: ["analyst", "view_only"], + }, + // TODO: Implement customised permissions for the group + // { + // title: "Permissions", + // field: "permissions", + // type: "toggle-buttons", + // }, + ], + }, + { + title: "Users", + elements: [ + { + field: "users", + type: "custom", + display: { + layout: "vertical", + defaultLayout: "vertical", + width: 12, + style: "padding-left: 0px", + render: family => { + if (family && family.members) { + const individualGridConfig = { + showSelectCheckbox: false, + showToolbar: false + }; + return html` + + + `; + } + }, + }, + } + ], + }, + ], + }; + } + +} + +customElements.define("group-admin-update", GroupAdminUpdate); From 4f08a480ad7ce3a6126b4aaf832fd61573143d34 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 28 Mar 2024 14:18:00 +0100 Subject: [PATCH 005/177] wp - WiP user components Signed-off-by: gpveronica --- .../organization/admin/user-admin-browser.js | 257 +++++++++++++ .../organization/admin/user-admin-create.js | 225 ++++++++++++ .../organization/admin/user-admin-grid.js | 347 ++++++++++++++++++ .../organization/admin/user-admin-update.js | 281 ++++++++++++++ 4 files changed, 1110 insertions(+) create mode 100644 src/webcomponents/organization/admin/user-admin-browser.js create mode 100644 src/webcomponents/organization/admin/user-admin-create.js create mode 100644 src/webcomponents/organization/admin/user-admin-grid.js create mode 100644 src/webcomponents/organization/admin/user-admin-update.js diff --git a/src/webcomponents/organization/admin/user-admin-browser.js b/src/webcomponents/organization/admin/user-admin-browser.js new file mode 100644 index 000000000..187b8fb45 --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-browser.js @@ -0,0 +1,257 @@ +/** + * Copyright 2015-2024 OpenCB * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import UtilsNew from "../../../core/utils-new.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import "./user-admin-grid.js"; +import NotificationUtils from "../../commons/utils/notification-utils"; + +export default class UserAdminBrowser extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + studyId: { + type: String, + }, + study: { + type: Object, + }, + organizationId: { + type: String, + }, + organization: { + type: Object, + }, + opencgaSession: { + type: Object, + }, + // QUESTION: pending to decide if we allow browser settings here. + settings: { + type: Object, + }, + }; + } + + #init() { + this.COMPONENT_ID = "user-admin-browser"; + this.users = []; + this._config = this.getDefaultConfig(); + this.isLoading = false; + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + // TODO to remove when BUG 2 fixed + onUserCreated(e) { + this.users.push(e.detail.user); + } + #getUsers(isSingleStudy) { + // FIXME: refactor + // If the component is used for managing the groups of the whole organization + this._users = []; + if (isSingleStudy) { + this._study.groups?.forEach(group => { + let protectedGroup = false; + if (group.id === "@admins" || group.id === "@members") { + protectedGroup = true; + } + const newGroup = { + studyId: this._study.id, + groupId: group.id, + users: group.userIds.map(user => { + debugger + return {id: user, name: user}; + }), + protectedGroup: protectedGroup, + }; + this._groups.push(newGroup); + }); + } else { + // FIXME 20240321 Vero: + // ********************************************************************************* + // [ BUG 1 ] + // The method info from the ws Organizations is returning an empty array of projects. + // The following bug has been created: + // https://app.clickup.com/t/36631768/TASK-5923. + // Meanwhile, I use the list of projects from opencgaSession. + // ********************************************************************************* + // [ BUG 2 ] + // The list of organization users: + // - Should use the endpoint: admin/users/search + // but not allowed for owner/admin organization user. + // - For listing in the user-grid a new user that still hasn't joined a group in study, + // we temporarily retrieve the users in study groups and fake a new user created. + // ********************************************************************************* + + // TODO: to remove and to use enpoint admin/users/search when [ BUG 2 ] fixed + const users = this.opencgaSession?.projects + .map(project => project.studies).flat() + .map(study => study.groups).flat() + .map(group => group.userIds).flat() + .filter(user => user !=="opencga"); + // Unique users + this.allUsersIds = UtilsNew.sort([...new Set(users)]); + + let error; + this.#setLoading(true); + const params = { + organization: this.organization.id, + }; + // this.opencgaSession.opencgaClient.admin() + // .searchUsers(params) + // TODO: not needed when [ BUG 2 ] fixed + this.opencgaSession.opencgaClient.users() + .info(this.allUsersIds.join(","), params) + .then(response => { + // this.users = UtilsNew.objectClone(response.responses[0]?.results); + // TODO: To remove when [ BUG 2 ] fixed + this.users.push(...UtilsNew.objectClone(response.responses[0]?.results)); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "usersInfo", this.component, {}, error); + this.#setLoading(false); + }); + } + } + + update(changedProperties) { + if (changedProperties.has("organization") || + changedProperties.has("study") || + changedProperties.has("opencgaSession")) { + this.#getUsers(!this.organization); + } + if (changedProperties.has("settings")) { + this.settingsObserver(); + } + super.update(changedProperties); + } + + settingsObserver() { + this._config = { + ...this.getDefaultConfig(), + ...this.settings, + }; + } + + studyIdObserver() { + if (this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this._study = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + this._study = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + this.#setLoading(false); + }); + } else { + this._study = {}; + } + } + + organizationIdObserver() { + if (this.organizationId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + .info(this.organizationId) + .then(response => { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); + this.#setLoading(false); + }); + + } + } + + renderFilterGraphics() { + if (this._config.showGraphicFilters) { + return html ` + + `; + } + } + + render() { + if (Object.keys(this.users).length === 0) { + return html ` +
+ + This organization does not have users yet. + Please create some users. +
+ `; + } + + return html ` + + ${this.renderFilterGraphics()} + + + + `; + } + + getDefaultConfig() { + return { + showGraphicFilters: false, + }; + } + +} + +customElements.define("user-admin-browser", UserAdminBrowser); diff --git a/src/webcomponents/organization/admin/user-admin-create.js b/src/webcomponents/organization/admin/user-admin-create.js new file mode 100644 index 000000000..465a0cb6a --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-create.js @@ -0,0 +1,225 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; +import UtilsNew from "../../../core/utils-new"; + +export default class UserAdminCreate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + organization: { + type: Object, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.user = {}; + this.isLoading = false; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + defaultLayout: "horizontal", + buttonOkText: "Create" + }; + this._config = this.getDefaultConfig(); + } + + #initOriginalObjects() { + this.user = {}; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("displayConfig")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + } + if (changedProperties.has("opencgaSession")) { + this.opencgaSessionObserver(); + } + super.update(changedProperties); + } + + opencgaSessionObserver() { + // Read Projects and Study to prepare the select studies menu + this.#initOriginalObjects(); + } + + onFieldChange(e, field) { + const param = field || e.detail.param; + // 1. Update user id + if (param === "id") { + // TODO 20240325 Vero: verify user id does not exist + this.user.id = e.detail.data.id; + } + // 2. Update the list of studies + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Clear user", + message: "Are you sure to clear?", + ok: () => { + this.user = {}; + this._config = this.getDefaultConfig(); + this.requestUpdate(); + }, + }); + } + + onSubmit() { + debugger + this.#setLoading(true); + this.user.organization = this.organization.id; + let error; + const promise = this.opencgaSession.opencgaClient.users() + .create(this.user) + .then(response => { + this.newUser = UtilsNew.objectClone(response.responses[0]?.results); + debugger + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `User Create`, + message: `User ${this.newUser.id} created in organization ${this.organization.id} correctly`, + }); + }) + .catch(reason => { + debugger + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_ERROR, { + message: `Error creating user: ${reason}`, + }); + // NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userCreate", this.newUser, {}, error); + }); + + promise.finally(() => { + this.#setLoading(false); + this.#initOriginalObjects(); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); + }); + } + + render() { + if (this.isLoading) { + return html``; + } + + return html` + + `; + } + + getDefaultConfig() { + return { + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + elements: [ + { + title: "User ID", + field: "id", + type: "input-text", + required: true, + display: { + placeholder: "Add a short ID...", + }, + }, + { + title: "User Name", + field: "name", + type: "input-text", + required: true, + display: { + placeholder: "Add the user name...", + }, + }, + { + title: "User Email", + field: "email", + type: "input-text", + required: true, + display: { + placeholder: "Add the user email...", + }, + }, + { + title: "User Password", + field: "password", + type: "input-password", + required: true, + display: { + helpMessage: ` + Type a strong password of a minimum length of 8 characters, combining at least: + 1 upper-case letter, 1 lower-case letter, 1 digit, and 1 special character. + `, + }, + }, + { + title: "Change password", + field: "requiredAction", + type: "toggle-switch", + required: false, + display: { + disabled: true, + helpMessage: "Coming soon: Required user action for changing password.", + }, + }, + + ], + }, + ], + }; + } + +} + +customElements.define("user-admin-create", UserAdminCreate); diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js new file mode 100644 index 000000000..a67b31dad --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -0,0 +1,347 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html, nothing} from "lit"; +import GridCommons from "../../commons/grid-commons"; +import UtilsNew from "../../../core/utils-new"; +import ModalUtils from "../../commons/modal/modal-utils"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; +import "./user-admin-create.js"; +import "./user-admin-update.js"; + +export default class UserAdminGrid extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + toolId: { + type: String, + }, + organization: { + type: Object, + }, + studyId: { + type: String, + }, + users: { + type: Array + }, + active: { + type: Boolean + }, + opencgaSession: { + type: Object + }, + config: { + type: Object + }, + }; + } + + #init() { + this.COMPONENT_ID = "user-grid"; + this._prefix = UtilsNew.randomString(8); + this.gridId = this._prefix + this.COMPONENT_ID; + this.active = true; + this._config = this.getDefaultConfig(); + } + + // update() { + // if (changedProperties.has("studyId")) { + // this.studyIdPropertyObserver(); + // } + // } + + updated(changedProperties) { + if ((changedProperties.has("opencgaSession") || + changedProperties.has("organization") || + changedProperties.has("toolId") || + changedProperties.has("config") || + changedProperties.has("active")) && this.active) { + this.propertyObserver(); + } + } + + studyIdPropertyObserver() { + // 1. Get users from the study + let error; + //this.opencgaSession.opencgaClient. + } + + propertyObserver() { + // With each property change we must be updated config and create the columns again. No extra checks are needed. + this._config = { + ...this.getDefaultConfig(), + ...this.config, + }; + + this.gridCommons = new GridCommons(this.gridId, this, this._config); + + // Config for the grid toolbar + this.toolbarSetting = { + ...this._config, + }; + + this.toolbarConfig = { + toolId: this.toolId, + resource: "USERS", + columns: this._getDefaultColumns(), + create: { + display: { + modalTitle: "User Create", + modalDraggable: true, + modalCyDataName: "modal-create", + modalSize: "modal-lg" + // disabled: true, + // disabledTooltip: "...", + }, + render: () => html ` + + ` + }, + }; + this.renderTable(); + } + + renderTable() { + if (this.users?.length > 0) { + this.renderLocalTable(); + } + this.requestUpdate(); + } + + renderLocalTable() { + this.table = $("#" + this.gridId); + this.table.bootstrapTable("destroy"); + this.table.bootstrapTable({ + theadClasses: "table-light", + buttonsClass: "light", + columns: this._getDefaultColumns(), + sidePagination: "server", + // Josemi Note 2024-01-18: we have added the ajax function for local variants also to support executing + // async calls when getting additional data from columns extensions. + ajax: params => { + const tableOptions = $(this.table).bootstrapTable("getOptions"); + const limit = params.data.limit || tableOptions.pageSize; + const skip = params.data.offset || 0; + const rows = this.users.slice(skip, skip + limit); + + // Get data for extensions + this.gridCommons.prepareDataForExtensions(this.COMPONENT_ID, this.opencgaSession, null, rows) + .then(() => params.success(rows)) + .catch(error => params.error(error)); + }, + // Josemi Note 2024-01-18: we use this method to tell bootstrap-table how many rows we have in our data + responseHandler: response => { + return { + total: this.users.length, + rows: response, + }; + }, + iconsPrefix: GridCommons.GRID_ICONS_PREFIX, + icons: GridCommons.GRID_ICONS, + + // Set table properties, these are read from config property + uniqueId: "id", + pagination: this._config.pagination, + pageSize: this._config.pageSize, + pageList: this._config.pageList, + detailView: this._config.detailView, + gridContext: this, + loadingTemplate: () => GridCommons.loadingFormatter(), + }); + } + + async onActionClick(e, value, row) { + const action = e.currentTarget.dataset.action; + switch (action) { + case "edit": + this.userId = row.userId; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}UpdateModal`); + break; + case "delete": + this.userId = row.userId; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}DeleteModal`); + break; + default: + break; + } + } + + _getDefaultColumns() { + this._columns = [ + { + title: "User ID", + field: "id", + visible: this.gridCommons.isColumnVisible("id") + }, + { + title: "Name", + field: "name", + visible: this.gridCommons.isColumnVisible("individualId") + }, + { + title: "Email", + field: "email", + visible: this.gridCommons.isColumnVisible("individualId") + }, + { + title: "Creation Date", + field: "account.creationDate", + formatter: CatalogGridFormatter.dateFormatter, + visible: this.gridCommons.isColumnVisible("creationDate") + }, + ]; + + if (this._config.annotations?.length > 0) { + this.gridCommons.addColumnsFromAnnotations(this._columns, CatalogGridFormatter.customAnnotationFormatter, this._config); + } + + if (this.opencgaSession && this._config.showActions) { + this._columns.push({ + id: "actions", + title: "Actions", + field: "actions", + formatter: () => ` +
+ + + +
`, + events: { + "click button": (e, value, row) => this.onActionClick(e, value, row), + }, + }); + } + + this._columns = this.gridCommons.addColumnsFromExtensions(this._columns, this.COMPONENT_ID); + return this._columns; + } + + renderModalUpdate() { + return ModalUtils.create(this, `${this._prefix}UpdateModal`, { + display: { + modalTitle: `Group Update: group ${this.groupId} in study ${this.studyId}`, + modalDraggable: true, + modalCyDataName: "modal-update", + modalSize: "modal-lg" + }, + render: active => html` + + + `, + }); + } + + renderModalDelete() { + return ModalUtils.create(this, `${this._prefix}DeleteModal`, { + display: { + modalTitle: `Group Delete: ${this.groupId}`, + modalDraggable: true, + modalCyDataName: "modal-update", + modalSize: "modal-lg" + }, + render: active => html` + + + `, + }); + } + + renderToolbar() { + if (this._config.showToolbar) { + return html ` + + + `; + } + } + + render() { + return html` + + ${this.renderToolbar()} + +
+
+
+ + ${this.renderModalDelete()} + + ${this.renderModalUpdate()} + `; + } + + getDefaultConfig() { + return { + pagination: true, + pageSize: 10, + pageList: [5, 10, 25], + multiSelection: false, + showSelectCheckbox: false, + // detailView: true, + + showToolbar: true, + showActions: true, + + showCreate: true, + showExport: false, + showSettings: false, + exportTabs: ["download", "link", "code"], + }; + } + +} + +customElements.define("user-admin-grid", UserAdminGrid); diff --git a/src/webcomponents/organization/admin/user-admin-update.js b/src/webcomponents/organization/admin/user-admin-update.js new file mode 100644 index 000000000..78e42742e --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-update.js @@ -0,0 +1,281 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import FormUtils from "../../commons/forms/form-utils"; +import NotificationUtils from "../../commons/utils/notification-utils"; + +export default class UserAdminUpdate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + userId: { + type: String + }, + studyId: { + type: String, + }, + active: { + type: Boolean, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.group = {}; + this.groupId = ""; + this.studyId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this.displayConfigDefault = { + style: "margin: 10px", + defaultLayout: "horizontal", + labelAlign: "right", + labelWidth: 3, + buttonOkText: "Update", + }; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initGroup() { + // 1. Group contains params: (a) id: e.g. "@admins", (b) userIds: e.g. ["test"] + this.group = this._study.groups.find(group => group.id === this.groupId); + // 2. In the update form, we need to manage as well the permissions of this group. + // Retrieve ACL permissions. Check if this study group has acl + // CAUTION: study does not have acl? + const groupPermissions = this._study?.acl + ?.find(acl => acl.member === this.opencgaSession.user.id)?.groups + ?.find(group => group.id === this.group.id)?.permissions || []; + // 3. Add current permissions and template key to the object group + this.group = { + ...this.group, + permissions: groupPermissions, + template: "", // Fixme: not sure how to retrieve template + }; + this.initOriginalObjects(); + + } + + initOriginalObjects() { + this._group = UtilsNew.objectClone(this.group); + this.updatedFields = {}; + } + + update(changedProperties) { + if ((changedProperties.has("groupId") || (changedProperties.has("studyId")) && this.active)) { + this.groupIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + groupIdObserver() { + if (this.groupId && this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this._study = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initGroup(); + }) + .catch(reason => { + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "studyInfo", this.study, {}, error); + this.#setLoading(false); + }); + } + } + + // Uncomment to post-process data-form manipulation + // onFieldChange(e) { + // debugger + // this.updatedFields = e.detail?.updatedFields || {}; + // this.requestUpdate(); + // } + + onFieldChange(e) { + const param = e.detail.param; + this.updatedFields = FormUtils.getUpdatedFields( + this.group, + this.updatedFields, + param, + e.detail.value, + e.detail.action); + if (param === "template") { + this._group.template = e.detail.value; + } + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Discard changes", + message: "Are you sure you want to discard the changes made?", + ok: () => { + this.initOriginalObjects(); + this.requestUpdate(); + // We need to dispatch a component clear event + LitUtils.dispatchCustomEvent(this, "groupClear", null, { + group: this._group, + }); + }, + }); + } + + onSubmit() { + const paramsAction = { + action: "SET" + }; + const studyAclParams = { + study: this.studyId, + template: this._group.template, + // permissions: this._group.permissions, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .updateAcl(this.groupId, paramsAction, studyAclParams) + .then(response => { + this.group = UtilsNew.objectClone(response.responses[0].results[0]); + this.updatedFields = {}; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `Group Update`, + message: `Group ${this.group.id} updated correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "updateGroup", this.group, {}, error); + this.#setLoading(false); + }); + } + + render() { + return html ` + + + `; + } + + getDefaultConfig() { + return { + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig, + sections: [ + { + title: "Details", + elements: [ + { + title: "Group ID", + field: "id", + type: "input-text", + required: true, + display: { + placeholder: "Add a short ID...", + helpMessage: "short group id...", + }, + }, + ], + }, + { + title: "Permissions", + elements: [ + { + title: "Templates", + field: "template", + type: "toggle-buttons", + allowedValues: ["analyst", "view_only"], + }, + // TODO: Implement customised permissions for the group + // { + // title: "Permissions", + // field: "permissions", + // type: "toggle-buttons", + // }, + ], + }, + // { + // title: "Users", + // elements: [ + // ], + // }, + ], + }; + } + +} + +customElements.define("user-admin-update", UserAdminUpdate); From cf9da4f597735fb589996917390f036780539c2b Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 4 Apr 2024 09:41:11 +0200 Subject: [PATCH 006/177] wc - Minor changes Signed-off-by: gpveronica --- src/webcomponents/organization/admin/group-admin-create.js | 6 ++---- src/webcomponents/organization/admin/group-admin-update.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index 0b5c14a33..a9e9d46ea 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -136,14 +136,12 @@ export default class GroupAdminCreate extends LitElement { .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `Group Create`, - message: `Group ${this.group.id} created in study ${study} correctly`, + message: `Group ${this.group.id} created in study ${study} successfully`, }); }) .catch(reason => { error = reason; - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_ERROR, { - message: `Error creating group: ${reason.message || reason}`, - }); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { LitUtils.dispatchCustomEvent(this, "groupCreate", {}, { diff --git a/src/webcomponents/organization/admin/group-admin-update.js b/src/webcomponents/organization/admin/group-admin-update.js index 3558f6c6b..5f81c1cf9 100644 --- a/src/webcomponents/organization/admin/group-admin-update.js +++ b/src/webcomponents/organization/admin/group-admin-update.js @@ -137,7 +137,7 @@ export default class GroupAdminUpdate extends LitElement { }) .catch(reason => { error = reason; - console.error(reason); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { LitUtils.dispatchCustomEvent(this, "studyInfo", this.study, {}, error); From c78c181f3465980830a055173f8d50929a781720 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 4 Apr 2024 09:42:53 +0200 Subject: [PATCH 007/177] wc - WiP listing users and updating. Workarounds until bugs in back fixed Signed-off-by: gpveronica --- .../organization/admin/user-admin-browser.js | 36 ++--- .../organization/admin/user-admin-create.js | 25 ++-- .../organization/admin/user-admin-grid.js | 36 +++-- .../organization/admin/user-admin-update.js | 130 ++++++++++++++---- 4 files changed, 144 insertions(+), 83 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-browser.js b/src/webcomponents/organization/admin/user-admin-browser.js index 187b8fb45..b3cf9420a 100644 --- a/src/webcomponents/organization/admin/user-admin-browser.js +++ b/src/webcomponents/organization/admin/user-admin-browser.js @@ -70,31 +70,10 @@ export default class UserAdminBrowser extends LitElement { this.requestUpdate(); } - // TODO to remove when BUG 2 fixed - onUserCreated(e) { - this.users.push(e.detail.user); - } #getUsers(isSingleStudy) { - // FIXME: refactor - // If the component is used for managing the groups of the whole organization - this._users = []; + // FIXME: Big refactor when BUG 2 fixed. if (isSingleStudy) { - this._study.groups?.forEach(group => { - let protectedGroup = false; - if (group.id === "@admins" || group.id === "@members") { - protectedGroup = true; - } - const newGroup = { - studyId: this._study.id, - groupId: group.id, - users: group.userIds.map(user => { - debugger - return {id: user, name: user}; - }), - protectedGroup: protectedGroup, - }; - this._groups.push(newGroup); - }); + // TODO } else { // FIXME 20240321 Vero: // ********************************************************************************* @@ -111,7 +90,6 @@ export default class UserAdminBrowser extends LitElement { // - For listing in the user-grid a new user that still hasn't joined a group in study, // we temporarily retrieve the users in study groups and fake a new user created. // ********************************************************************************* - // TODO: to remove and to use enpoint admin/users/search when [ BUG 2 ] fixed const users = this.opencgaSession?.projects .map(project => project.studies).flat() @@ -126,9 +104,10 @@ export default class UserAdminBrowser extends LitElement { const params = { organization: this.organization.id, }; - // this.opencgaSession.opencgaClient.admin() - // .searchUsers(params) + debugger // TODO: not needed when [ BUG 2 ] fixed + // this.opencgaSession.opencgaClient.admin() + // .searchUsers({organization: "test"}) this.opencgaSession.opencgaClient.users() .info(this.allUsersIds.join(","), params) .then(response => { @@ -151,6 +130,7 @@ export default class UserAdminBrowser extends LitElement { if (changedProperties.has("organization") || changedProperties.has("study") || changedProperties.has("opencgaSession")) { + debugger this.#getUsers(!this.organization); } if (changedProperties.has("settings")) { @@ -222,6 +202,7 @@ export default class UserAdminBrowser extends LitElement { } render() { + debugger if (Object.keys(this.users).length === 0) { return html `
@@ -240,8 +221,7 @@ export default class UserAdminBrowser extends LitElement { .toolId="${this.COMPONENT_ID}" .organization="${this.organization}" .users="${this.users}" - .opencgaSession="${this.opencgaSession}" - @userCreate="${e => this.onUserCreated(e)}"> + .opencgaSession="${this.opencgaSession}"> `; } diff --git a/src/webcomponents/organization/admin/user-admin-create.js b/src/webcomponents/organization/admin/user-admin-create.js index 465a0cb6a..f883915c7 100644 --- a/src/webcomponents/organization/admin/user-admin-create.js +++ b/src/webcomponents/organization/admin/user-admin-create.js @@ -113,34 +113,27 @@ export default class UserAdminCreate extends LitElement { debugger this.#setLoading(true); this.user.organization = this.organization.id; - let error; - const promise = this.opencgaSession.opencgaClient.users() + let error = {}; + let newUser = {}; + this.opencgaSession.opencgaClient.users() .create(this.user) .then(response => { - this.newUser = UtilsNew.objectClone(response.responses[0]?.results); + newUser = UtilsNew.objectClone(response.responses[0].results[0]); debugger NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `User Create`, - message: `User ${this.newUser.id} created in organization ${this.organization.id} correctly`, + message: `User ${newUser.id} created in organization ${this.organization.id} successfully`, }); }) .catch(reason => { - debugger error = reason; - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_ERROR, { - message: `Error creating user: ${reason}`, - }); - // NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "userCreate", this.newUser, {}, error); + LitUtils.dispatchCustomEvent(this, "userCreate", newUser, {}, error); + this.#initOriginalObjects(); + this.#setLoading(false); }); - - promise.finally(() => { - this.#setLoading(false); - this.#initOriginalObjects(); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); - }); } render() { diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index a67b31dad..535f275ac 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -128,7 +128,17 @@ export default class UserAdminGrid extends LitElement { this.renderTable(); } + // TODO to remove when BUG 2 fixed + onUserCreate(e) { + debugger + const user = e.detail.value; + if (UtilsNew.isNotEmpty(user)) { + this.users.push(user); + this.renderTable(); + } + } renderTable() { + debugger if (this.users?.length > 0) { this.renderLocalTable(); } @@ -181,6 +191,7 @@ export default class UserAdminGrid extends LitElement { const action = e.currentTarget.dataset.action; switch (action) { case "edit": + debugger this.userId = row.userId; this.requestUpdate(); await this.updateComplete; @@ -261,15 +272,19 @@ export default class UserAdminGrid extends LitElement { modalCyDataName: "modal-update", modalSize: "modal-lg" }, - render: active => html` - - - `, + render: active => { + debugger + return html` + + + `; + }, }); } @@ -302,13 +317,14 @@ export default class UserAdminGrid extends LitElement { .settings="${this.toolbarSetting}" .config="${this.toolbarConfig}" @actionClick="${e => this.onActionClick(e)}" - @sampleCreate="${this.renderTable}"> + @userCreate="${e => this.onUserCreate(e)}"> `; } } render() { + debugger return html` ${this.renderToolbar()} diff --git a/src/webcomponents/organization/admin/user-admin-update.js b/src/webcomponents/organization/admin/user-admin-update.js index 78e42742e..df155beef 100644 --- a/src/webcomponents/organization/admin/user-admin-update.js +++ b/src/webcomponents/organization/admin/user-admin-update.js @@ -19,6 +19,8 @@ import UtilsNew from "../../../core/utils-new.js"; import LitUtils from "../../commons/utils/lit-utils.js"; import FormUtils from "../../commons/forms/form-utils"; import NotificationUtils from "../../commons/utils/notification-utils"; +import "../../user/user-password-change.js"; +import "../../user/user-password-reset.js"; export default class UserAdminUpdate extends LitElement { @@ -37,6 +39,9 @@ export default class UserAdminUpdate extends LitElement { userId: { type: String }, + organization: { + type: Object, + }, studyId: { type: String, }, @@ -53,8 +58,8 @@ export default class UserAdminUpdate extends LitElement { } #init() { - this.group = {}; - this.groupId = ""; + this._user = {}; + this.userId = ""; this.studyId = ""; this.displayConfig = {}; this.updatedFields = {}; @@ -88,33 +93,32 @@ export default class UserAdminUpdate extends LitElement { }; } - #initGroup() { + #initUser() { // 1. Group contains params: (a) id: e.g. "@admins", (b) userIds: e.g. ["test"] - this.group = this._study.groups.find(group => group.id === this.groupId); + this._user = UtilsNew.objectClone(this.user); // 2. In the update form, we need to manage as well the permissions of this group. // Retrieve ACL permissions. Check if this study group has acl // CAUTION: study does not have acl? - const groupPermissions = this._study?.acl - ?.find(acl => acl.member === this.opencgaSession.user.id)?.groups - ?.find(group => group.id === this.group.id)?.permissions || []; - // 3. Add current permissions and template key to the object group - this.group = { - ...this.group, - permissions: groupPermissions, - template: "", // Fixme: not sure how to retrieve template - }; + // const groupPermissions = this._study?.acl + // ?.find(acl => acl.member === this.opencgaSession.user.id)?.groups + // ?.find(group => group.id === this.group.id)?.permissions || []; + // // 3. Add current permissions and template key to the object group + // this.group = { + // ...this.group, + // permissions: groupPermissions, + // template: "", // Fixme: not sure how to retrieve template + // }; this.initOriginalObjects(); - } initOriginalObjects() { - this._group = UtilsNew.objectClone(this.group); + this._user = UtilsNew.objectClone(this.user); this.updatedFields = {}; } update(changedProperties) { - if ((changedProperties.has("groupId") || (changedProperties.has("studyId")) && this.active)) { - this.groupIdObserver(); + if ((changedProperties.has("userId") && this.active)) { + this.userIdObserver(); } if (changedProperties.has("displayConfig")) { this._config = this.getDefaultConfig(); @@ -125,15 +129,20 @@ export default class UserAdminUpdate extends LitElement { super.update(changedProperties); } - groupIdObserver() { - if (this.groupId && this.studyId && this.opencgaSession) { + userIdObserver() { + if (this.userId && this.opencgaSession) { + const params = { + users: this.userId, + organization: this.organization.id, + }; let error; this.#setLoading(true); - this.opencgaSession.opencgaClient.studies() - .info(this.studyId) + this.opencgaSession.opencgaClient.users() + .info(params) .then(response => { - this._study = UtilsNew.objectClone(response.responses[0].results[0]); - this.#initGroup(); + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + debugger + this.#initUser(); }) .catch(reason => { error = reason; @@ -216,7 +225,7 @@ export default class UserAdminUpdate extends LitElement { render() { return html ` html` + + + `, + }, + }, + { + title: "Reset password", + type: "custom", + display: { + render: (data, active, opencgaSession) => html` + + + `, + }, + }, + /* + { + title: "Reset password", + field: "pwdReset", + type: "toggle-switch", + display: { + disabled: true, + helpMessage: "Coming soon: Force user to reset the password", + }, + }, + { + title: "Expires in", + field: "pwdExpiration", type: "input-text", - required: true, display: { - placeholder: "Add a short ID...", - helpMessage: "short group id...", + disabled: true, + helpMessage: "Coming soon: Enable password expiration", }, }, + */ ], }, { From 1c67a2abf08bb7cb72cc29374e429b3bae001958 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 5 Apr 2024 15:44:05 +0200 Subject: [PATCH 008/177] wc - WiP minor fixes Signed-off-by: gpveronica --- src/webcomponents/api/opencga-rest-input.js | 3 ++- src/webcomponents/organization/admin/user-admin-grid.js | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/webcomponents/api/opencga-rest-input.js b/src/webcomponents/api/opencga-rest-input.js index 72bd0d392..29a7d09ef 100644 --- a/src/webcomponents/api/opencga-rest-input.js +++ b/src/webcomponents/api/opencga-rest-input.js @@ -405,7 +405,8 @@ export default class OpencgaRestInput extends LitElement { #postEndpoint(url, isForm) { // Add Study - url += "study=" + encodeURIComponent(this.opencgaSession.study.fqn); + // Fixme: not all endpoints require study. E.g. POST /users/password/ + url += "study=" + encodeURIComponent(this.opencgaSession?.study?.fqn); // Replace PATH params this.endpoint.parameters diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 535f275ac..78b1f4ed7 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -191,14 +191,13 @@ export default class UserAdminGrid extends LitElement { const action = e.currentTarget.dataset.action; switch (action) { case "edit": - debugger - this.userId = row.userId; + this.userId = row.id; this.requestUpdate(); await this.updateComplete; ModalUtils.show(`${this._prefix}UpdateModal`); break; case "delete": - this.userId = row.userId; + this.userId = row.id; this.requestUpdate(); await this.updateComplete; ModalUtils.show(`${this._prefix}DeleteModal`); @@ -267,7 +266,7 @@ export default class UserAdminGrid extends LitElement { renderModalUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateModal`, { display: { - modalTitle: `Group Update: group ${this.groupId} in study ${this.studyId}`, + modalTitle: `User Update: User ${this.userId} in organization ${this.organization.id}`, modalDraggable: true, modalCyDataName: "modal-update", modalSize: "modal-lg" From ea0fdbc023b5b355db489073c998c2e7db57a4f1 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Tue, 16 Apr 2024 11:19:31 +0200 Subject: [PATCH 009/177] wc - WiP minor fix Signed-off-by: gpveronica --- .../organization/admin/user-admin-update.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-update.js b/src/webcomponents/organization/admin/user-admin-update.js index df155beef..97f9c7350 100644 --- a/src/webcomponents/organization/admin/user-admin-update.js +++ b/src/webcomponents/organization/admin/user-admin-update.js @@ -111,7 +111,7 @@ export default class UserAdminUpdate extends LitElement { this.initOriginalObjects(); } - initOriginalObjects() { + #initOriginalObjects() { this._user = UtilsNew.objectClone(this.user); this.updatedFields = {}; } @@ -132,21 +132,19 @@ export default class UserAdminUpdate extends LitElement { userIdObserver() { if (this.userId && this.opencgaSession) { const params = { - users: this.userId, organization: this.organization.id, }; let error; this.#setLoading(true); this.opencgaSession.opencgaClient.users() - .info(params) + .info(this.userId, params) .then(response => { this.user = UtilsNew.objectClone(response.responses[0].results[0]); - debugger - this.#initUser(); + this.#initOriginalObjects(); }) .catch(reason => { error = reason; - console.error(reason); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { LitUtils.dispatchCustomEvent(this, "studyInfo", this.study, {}, error); @@ -208,8 +206,8 @@ export default class UserAdminUpdate extends LitElement { this.group = UtilsNew.objectClone(response.responses[0].results[0]); this.updatedFields = {}; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { - title: `Group Update`, - message: `Group ${this.group.id} updated correctly`, + title: `User Update`, + message: `User ${this.userId} updated correctly`, }); }) .catch(reason => { @@ -217,7 +215,7 @@ export default class UserAdminUpdate extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "updateGroup", this.group, {}, error); + LitUtils.dispatchCustomEvent(this, "updateUser", this.group, {}, error); this.#setLoading(false); }); } From 488c5c58859012726de5c783522b61dda814cf3e Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 19 Apr 2024 15:31:19 +0200 Subject: [PATCH 010/177] wc - WiP opencga TASK-5922 fixed, fixing the user/group grids #TASK-5866 Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 185 +++++++++--------- .../organization/admin/group-admin-create.js | 54 ++--- .../organization/admin/group-admin-grid.js | 54 +++-- .../organization/admin/organization-admin.js | 15 +- .../organization/admin/user-admin-browser.js | 34 ++-- .../organization/admin/user-admin-create.js | 2 - .../organization/admin/user-admin-grid.js | 99 +++++++--- 7 files changed, 260 insertions(+), 183 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js index c762cd414..feb6b266f 100644 --- a/src/webcomponents/organization/admin/group-admin-browser.js +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -23,11 +23,15 @@ import {LitElement, html} from "lit"; import LitUtils from "../../commons/utils/lit-utils"; -import UtilsNew from "../../../core/utils-new"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import UtilsNew from "../../../core/utils-new.js"; import "./group-admin-grid.js"; export default class GroupAdminBrowser extends LitElement { + /* ----------------------------------------------------------------------------------------------------------------- + CONSTRUCTOR AND PROPERTIES + ----------------------------------------------------------------------------------------------------------------- */ constructor() { super(); @@ -62,11 +66,14 @@ export default class GroupAdminBrowser extends LitElement { }; } + /* ----------------------------------------------------------------------------------------------------------------- + PRIVATE METHODS + ----------------------------------------------------------------------------------------------------------------- */ #init() { this.COMPONENT_ID = "groups-admin-browser"; - - this._study = {}; this._groups = []; + this._study = {}; + this._studies = []; this._config = this.getDefaultConfig(); this.isLoading = false; } @@ -76,64 +83,22 @@ export default class GroupAdminBrowser extends LitElement { this.requestUpdate(); } - #getGroups(isSingleStudy) { - // FIXME: refactor - // If the component is used for managing the groups of the whole organization - this._groups = []; - if (isSingleStudy) { - this._study.groups?.forEach(group => { - let protectedGroup = false; - if (group.id === "@admins" || group.id === "@members") { - protectedGroup = true; - } - const newGroup = { - studyId: this._study.id, - groupId: group.id, - protectedGroup: protectedGroup, - }; - this._groups.push(newGroup); - }); - } else { - // FIXME 20240321 Vero: - // ********************************************************************************* - // The method info from the ws Organizations is returning an empty array of projects. - // The following bug has been created: - // https://app.clickup.com/t/36631768/TASK-5923. - // Meanwhile, I use the list of projects from opencgaSession. - // ********************************************************************************* - /* - this.organization?.projects?.forEach(project => { - project.studies?.forEach(study => { - study.groups?.forEach(group => { - const newGroup = { - studyId: study.id, - groupId: group.id, - }; - this._groups.push(newGroup); - }); - }); - }); - */ - this.opencgaSession?.projects?.forEach(project => { - project.studies?.forEach(study => { - study.groups?.forEach(group => { - const newGroup = { - studyId: study.id, - groupId: group.id, - creationDate: group.creationDate, - }; - this._groups.push(newGroup); - }); - }); - }); - } - } - + /* ----------------------------------------------------------------------------------------------------------------- + LIT LIFE-CYCLE + ----------------------------------------------------------------------------------------------------------------- */ update(changedProperties) { - if (changedProperties.has("organization") || - changedProperties.has("study") || - changedProperties.has("opencgaSession")) { - this.#getGroups(!this.organization); + debugger + if (changedProperties.has("organization")) { + this.organizationObserver(); + } + if (changedProperties.has("organizationId")) { + this.organizationIdObserver(); + } + if (changedProperties.has("study")) { + this.studyObserver(); + } + if (changedProperties.has("studyId")) { + this.studyIdObserver(); } if (changedProperties.has("settings")) { this.settingsObserver(); @@ -141,60 +106,96 @@ export default class GroupAdminBrowser extends LitElement { super.update(changedProperties); } - settingsObserver() { - this._config = { - ...this.getDefaultConfig(), - ...this.settings, - }; + /* ----------------------------------------------------------------------------------------------------------------- + OBSERVERS + ----------------------------------------------------------------------------------------------------------------- */ + organizationObserver() { + // Get all organization groups + this._groups = []; + this._studies = []; + this.organization?.projects?.forEach(project => { + project.studies?.forEach(study => { + this._studies.push({projectId: project.id, fqn: study.fqn, name: study.alias}); + study.groups?.forEach(group => { + const newGroup = { + projectId: project.id, + studyId: study.id, + groupId: group.id, + }; + this._groups.push(newGroup); + }); + }); + }); } - studyIdObserver() { - if (this.studyId && this.opencgaSession) { + organizationIdObserver() { + if (this.organizationId && this.opencgaSession) { let error; this.#setLoading(true); - this.opencgaSession.opencgaClient.studies() - .info(this.studyId) + this.opencgaSession.opencgaClient.organization() + .info(this.organizationId) .then(response => { - this._study = UtilsNew.objectClone(response.responses[0].results[0]); + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); }) .catch(reason => { - this._study = {}; + this.organization = {}; error = reason; console.error(reason); }) .finally(() => { this._config = this.getDefaultConfig(); - LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); this.#setLoading(false); }); - } else { - this._study = {}; + } } - organizationIdObserver() { - if (this.organizationId && this.opencgaSession) { + studyObserver() { + // Get all study groups + this._groups = []; + this._studies = [this._study]; + this.study.groups?.forEach(group => { + const newGroup = { + studyId: this.study.id, + groupId: group.id, + }; + this._groups.push(newGroup); + }); + } + + studyIdObserver() { + if (this.studyId && this.opencgaSession) { let error; this.#setLoading(true); - this.opencgaSession.opencgaClient.organization() - .info(this.organizationId) + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) .then(response => { - this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + this.study = UtilsNew.objectClone(response.responses[0].results[0]); }) .catch(reason => { - this.organization = {}; + this.study = {}; error = reason; console.error(reason); }) .finally(() => { this._config = this.getDefaultConfig(); - LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); this.#setLoading(false); }); - } } + settingsObserver() { + this._config = { + ...this.getDefaultConfig(), + ...this.settings, + }; + } + + /* ----------------------------------------------------------------------------------------------------------------- + RENDER + ----------------------------------------------------------------------------------------------------------------- */ renderFilterGraphics() { if (this._config.showGraphicFilters) { return html ` @@ -204,28 +205,28 @@ export default class GroupAdminBrowser extends LitElement { } render() { - if (Object.keys(this._groups).length === 0) { - return html ` -
- - This organization does not have studies yet. - Please create some projects or studies to see the list of existent groups. -
- `; + if (!this.opencgaSession) { + return html`
Not valid session
`; } - +debugger return html ` ${this.renderFilterGraphics()} + .studies="${this._studies}" + .config="${this._config}" + .active="${true}"> `; } + /* ----------------------------------------------------------------------------------------------------------------- + DEFAULT CONFIG + ----------------------------------------------------------------------------------------------------------------- */ getDefaultConfig() { return { showGraphicFilters: false, diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index a9e9d46ea..99c2e6104 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -33,11 +33,14 @@ export default class GroupAdminCreate extends LitElement { static get properties() { return { + studies: { + type: Array, + }, opencgaSession: { - type: Object + type: Object, }, displayConfig: { - type: Object + type: Object, }, }; } @@ -45,6 +48,7 @@ export default class GroupAdminCreate extends LitElement { #init() { this.group = {}; this.isLoading = false; + this.isStudyAdmin = false; this.displayConfigDefault = { style: "margin: 10px", titleWidth: 3, @@ -58,22 +62,28 @@ export default class GroupAdminCreate extends LitElement { this.group = {}; this.allowedValues = []; - // Read Projects and Study to prepare the allowed values in the Study select menu - if (this.opencgaSession?.projects) { - // Prepare allowedValues for the select options menu - for (const project of this.opencgaSession.projects) { - const fields = []; - for (const study of project.studies) { - if (OpencgaCatalogUtils.isAdmin(study, this.opencgaSession.user.id)) { - fields.push({id: study.fqn, name: study.fqn}); - } - } - if (fields.length > 0) { - this.allowedValues.push({name: `Project '${project.name}'`, fields: fields}); - } + if (this.studies && this.opencgaSession) { + if (Array.isArray(this.studies) && this.studies.length === 1) { + this.isStudyAdmin = true; + this.allowedValues = this.studies[0].fqn; + } else { + // 1. Prepare structure for displaying studies per project in dropdown + const projects = this.studies.reduce((acc, {fqn, name, projectId}) => { + const study = {fqn, name}; + const item = acc.find(y => y.projectId === projectId); + (item) ? item.studies.push(study) : + acc.push({projectId: projectId, studies: [study]}); + return acc; + }, []); + // 2. Fill allowed values + this.allowedValues = projects + .filter(({studies}) => studies.length > 0) + .map(({projectId, studies}) => ({ + name: `Project '${projectId}'`, + fields: studies.map(({fqn, name}) => ({id: fqn, name})) + })); } } - this._config = this.getDefaultConfig(); } @@ -83,23 +93,18 @@ export default class GroupAdminCreate extends LitElement { } update(changedProperties) { + if (changedProperties.has("studies") || changedProperties.has("opencgaSession")) { + this.#initOriginalObjects(); + } if (changedProperties.has("displayConfig")) { this.displayConfig = { ...this.displayConfigDefault, ...this.displayConfig }; } - if (changedProperties.has("opencgaSession")) { - this.opencgaSessionObserver(); - } super.update(changedProperties); } - opencgaSessionObserver() { - // Read Projects and Study to prepare the select studies menu - this.#initOriginalObjects(); - } - onFieldChange(e, field) { const param = field || e.detail.param; // 1. Update group id @@ -200,6 +205,7 @@ export default class GroupAdminCreate extends LitElement { required: true, allowedValues: this.allowedValues, display: { + disabled: this.isStudyAdmin, placeholder: "Select study or studies..." }, }, diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index de4b825a9..9502ba03d 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -40,16 +40,19 @@ export default class GroupAdminGrid extends LitElement { type: String, }, opencgaSession: { - type: Object + type: Object, }, groups: { - type: Array + type: Array, + }, + studies: { + type: Object, }, active: { - type: Boolean + type: Boolean, }, config: { - type: Object + type: Object, }, }; } @@ -62,13 +65,20 @@ export default class GroupAdminGrid extends LitElement { this._config = this.getDefaultConfig(); } - updated(changedProperties) { - if ((changedProperties.has("opencgaSession") || + update(changedProperties) { + if (changedProperties.has("opencgaSession") || changedProperties.has("toolId") || changedProperties.has("config") || - changedProperties.has("active")) && this.active) { + changedProperties.has("studies")) { this.propertyObserver(); } + super.update(changedProperties); + } + + updated(changedProperties) { + if (changedProperties.size > 0 && this.active) { + this.renderTable(); + } } propertyObserver() { @@ -98,19 +108,25 @@ export default class GroupAdminGrid extends LitElement { // disabled: true, // disabledTooltip: "...", }, - render: () => html ` - - ` + render: () => { + debugger + return html ` + + + `; + } }, }; - this.renderTable(); } renderTable() { if (this.groups?.length > 0) { this.renderLocalTable(); + } else { + this.renderRemoteTable(); } this.requestUpdate(); } @@ -152,7 +168,6 @@ export default class GroupAdminGrid extends LitElement { pageSize: this._config.pageSize, pageList: this._config.pageList, detailView: this._config.detailView, - gridContext: this, loadingTemplate: () => GridCommons.loadingFormatter(), }); } @@ -163,7 +178,6 @@ export default class GroupAdminGrid extends LitElement { case "edit": this.groupId = row.groupId; this.studyId = row.studyId; - debugger this.requestUpdate(); await this.updateComplete; ModalUtils.show(`${this._prefix}UpdateModal`); @@ -191,7 +205,12 @@ export default class GroupAdminGrid extends LitElement { { title: "Study ID", field: "studyId", - visible: this.gridCommons.isColumnVisible("individualId") + visible: this.gridCommons.isColumnVisible("studyId") + }, + { + title: "Project ID", + field: "projectId", + visible: this.gridCommons.isColumnVisible("projectId") }, { title: "Creation Date", @@ -298,7 +317,7 @@ export default class GroupAdminGrid extends LitElement {
${this.renderModalDelete()} - + ${this.renderModalUpdate()} `; } @@ -310,7 +329,6 @@ export default class GroupAdminGrid extends LitElement { pageList: [5, 10, 25], multiSelection: false, showSelectCheckbox: false, - // detailView: true, showToolbar: true, showActions: true, diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index 89a4f7780..abc7ae0b6 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -58,6 +58,7 @@ export default class OrganizationAdmin extends LitElement { } update(changedProperties) { + debugger if (changedProperties.has("organizationId")) { this.organizationIdObserver(); } @@ -66,11 +67,20 @@ export default class OrganizationAdmin extends LitElement { } organizationIdObserver() { - if (this.organizationId && this.opencgaSession) { + // FIXME Vero: on creating a new group, for instance, + // the session is updated but the org id does not change. + // I need to get the organization info again to refresh the grid. + // For now, I will query org info only with property opencgaSession change. + // TO think about it. + // if (this.organizationId && this.opencgaSession) { + if (this.organizationId || this.opencgaSession) { let error; this.#setLoading(true); this.opencgaSession.opencgaClient.organization() - .info(this.organizationId) + // FIXME Vero: To remove hardcoded organization when the following bug is fixed: + // https://app.clickup.com/t/36631768/TASK-5980 + // .info(this.organizationId) + .info("test") .then(response => { this.organization = UtilsNew.objectClone(response.responses[0].results[0]); }) @@ -83,7 +93,6 @@ export default class OrganizationAdmin extends LitElement { LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); this.#setLoading(false); }); - } } diff --git a/src/webcomponents/organization/admin/user-admin-browser.js b/src/webcomponents/organization/admin/user-admin-browser.js index b3cf9420a..7fdc2028d 100644 --- a/src/webcomponents/organization/admin/user-admin-browser.js +++ b/src/webcomponents/organization/admin/user-admin-browser.js @@ -104,10 +104,9 @@ export default class UserAdminBrowser extends LitElement { const params = { organization: this.organization.id, }; - debugger // TODO: not needed when [ BUG 2 ] fixed // this.opencgaSession.opencgaClient.admin() - // .searchUsers({organization: "test"}) + // .searchUsers({organization: "test", limit: 25}) this.opencgaSession.opencgaClient.users() .info(this.allUsersIds.join(","), params) .then(response => { @@ -127,12 +126,6 @@ export default class UserAdminBrowser extends LitElement { } update(changedProperties) { - if (changedProperties.has("organization") || - changedProperties.has("study") || - changedProperties.has("opencgaSession")) { - debugger - this.#getUsers(!this.organization); - } if (changedProperties.has("settings")) { this.settingsObserver(); } @@ -202,17 +195,16 @@ export default class UserAdminBrowser extends LitElement { } render() { - debugger - if (Object.keys(this.users).length === 0) { - return html ` -
- - This organization does not have users yet. - Please create some users. -
- `; - } - + // if (Object.keys(this.users).length === 0) { + // return html ` + //
+ // + // This organization does not have users yet. + // Please create some users. + //
+ // `; + // } + // .users="${this.users}" return html ` ${this.renderFilterGraphics()} @@ -220,8 +212,8 @@ export default class UserAdminBrowser extends LitElement { + .opencgaSession="${this.opencgaSession}" + .active="${true}"> `; } diff --git a/src/webcomponents/organization/admin/user-admin-create.js b/src/webcomponents/organization/admin/user-admin-create.js index f883915c7..8176fe377 100644 --- a/src/webcomponents/organization/admin/user-admin-create.js +++ b/src/webcomponents/organization/admin/user-admin-create.js @@ -110,7 +110,6 @@ export default class UserAdminCreate extends LitElement { } onSubmit() { - debugger this.#setLoading(true); this.user.organization = this.organization.id; let error = {}; @@ -119,7 +118,6 @@ export default class UserAdminCreate extends LitElement { .create(this.user) .then(response => { newUser = UtilsNew.objectClone(response.responses[0].results[0]); - debugger NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `User Create`, message: `User ${newUser.id} created in organization ${this.organization.id} successfully`, diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 78b1f4ed7..c28d62357 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -21,6 +21,7 @@ import ModalUtils from "../../commons/modal/modal-utils"; import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; import "./user-admin-create.js"; import "./user-admin-update.js"; +import NotificationUtils from "../../commons/utils/notification-utils"; export default class UserAdminGrid extends LitElement { @@ -39,6 +40,9 @@ export default class UserAdminGrid extends LitElement { toolId: { type: String, }, + opencgaSession: { + type: Object + }, organization: { type: Object, }, @@ -51,9 +55,6 @@ export default class UserAdminGrid extends LitElement { active: { type: Boolean }, - opencgaSession: { - type: Object - }, config: { type: Object }, @@ -68,26 +69,24 @@ export default class UserAdminGrid extends LitElement { this._config = this.getDefaultConfig(); } - // update() { - // if (changedProperties.has("studyId")) { - // this.studyIdPropertyObserver(); - // } - // } - - updated(changedProperties) { - if ((changedProperties.has("opencgaSession") || - changedProperties.has("organization") || + update(changedProperties) { + if (changedProperties.has("opencgaSession") || changedProperties.has("toolId") || - changedProperties.has("config") || - changedProperties.has("active")) && this.active) { + changedProperties.has("organization") || + changedProperties.has("config")) { this.propertyObserver(); } + super.update(changedProperties); + } + + updated(changedProperties) { + if (changedProperties.size > 0 && this.active) { + this.renderTable(); + } } studyIdPropertyObserver() { // 1. Get users from the study - let error; - //this.opencgaSession.opencgaClient. } propertyObserver() { @@ -125,12 +124,10 @@ export default class UserAdminGrid extends LitElement { ` }, }; - this.renderTable(); } // TODO to remove when BUG 2 fixed onUserCreate(e) { - debugger const user = e.detail.value; if (UtilsNew.isNotEmpty(user)) { this.users.push(user); @@ -138,13 +135,73 @@ export default class UserAdminGrid extends LitElement { } } renderTable() { - debugger if (this.users?.length > 0) { this.renderLocalTable(); + } else { + this.renderRemoteTable(); } this.requestUpdate(); } + renderRemoteTable() { + if (this.opencgaSession?.opencgaClient) { + this._columns = this._getDefaultColumns(); + this.table = $("#" + this.gridId); + this.table.bootstrapTable("destroy"); + this.table.bootstrapTable({ + theadClasses: "table-light", + buttonsClass: "light", + columns: this._columns, + method: "get", + sidePagination: "server", + iconsPrefix: GridCommons.GRID_ICONS_PREFIX, + icons: GridCommons.GRID_ICONS, + uniqueId: "id", + // Table properties + pagination: this._config.pagination, + pageSize: this._config.pageSize, + pageList: this._config.pageList, + paginationVAlign: "both", + formatShowingRows: this.gridCommons.formatShowingRows, + detailView: !!this.detailFormatter, + loadingTemplate: () => GridCommons.loadingFormatter(), + ajax: params => { + let result = null; + this.filters = { + limit: params.data.limit, + skip: params.data.offset || 0, + count: !this.table.bootstrapTable("getOptions").pageNumber || this.table.bootstrapTable("getOptions").pageNumber === 1, + }; + + // Store the current filters + this.opencgaSession.opencgaClient.admin() + .searchUsers({organization: "test", ...this.filters}) + .then(response => { + result = response; + return response; + }) + .then(() => { + // Prepare data for columns extensions + const rows = result.responses?.[0]?.results || []; + return this.gridCommons.prepareDataForExtensions(this.COMPONENT_ID, this.opencgaSession, this.filters, rows); + }) + .then(() => params.success(result)) + .catch(error => { + console.error(error); + params.error(error); + }); + }, + responseHandler: response => { + const result = this.gridCommons.responseHandler(response, $(this.table).bootstrapTable("getOptions")); + return result.response; + }, + onClickRow: (row, selectedElement) => this.gridCommons.onClickRow(row.id, row, selectedElement), + onLoadSuccess: data => this.gridCommons.onLoadSuccess(data, 1), + onLoadError: (e, restResponse) => this.gridCommons.onLoadError(e, restResponse), + }); + } + } + renderLocalTable() { this.table = $("#" + this.gridId); this.table.bootstrapTable("destroy"); @@ -182,7 +239,6 @@ export default class UserAdminGrid extends LitElement { pageSize: this._config.pageSize, pageList: this._config.pageList, detailView: this._config.detailView, - gridContext: this, loadingTemplate: () => GridCommons.loadingFormatter(), }); } @@ -272,7 +328,6 @@ export default class UserAdminGrid extends LitElement { modalSize: "modal-lg" }, render: active => { - debugger return html` ${this.renderToolbar()} @@ -345,7 +399,6 @@ export default class UserAdminGrid extends LitElement { pageList: [5, 10, 25], multiSelection: false, showSelectCheckbox: false, - // detailView: true, showToolbar: true, showActions: true, From de64d4b646e1c3688047c025fe84c9df74a77074 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Apr 2024 12:31:58 +0200 Subject: [PATCH 011/177] wc - WiP group delete in admin organization Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 11 +- .../organization/admin/group-admin-delete.js | 150 ++++++++++++++++++ .../organization/admin/group-admin-grid.js | 35 ++-- .../organization/admin/organization-admin.js | 3 +- 4 files changed, 173 insertions(+), 26 deletions(-) create mode 100644 src/webcomponents/organization/admin/group-admin-delete.js diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js index feb6b266f..a18903527 100644 --- a/src/webcomponents/organization/admin/group-admin-browser.js +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -87,7 +87,6 @@ export default class GroupAdminBrowser extends LitElement { LIT LIFE-CYCLE ----------------------------------------------------------------------------------------------------------------- */ update(changedProperties) { - debugger if (changedProperties.has("organization")) { this.organizationObserver(); } @@ -120,7 +119,9 @@ export default class GroupAdminBrowser extends LitElement { const newGroup = { projectId: project.id, studyId: study.id, - groupId: group.id, + fqn: study.fqn, + group: group, + isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), }; this._groups.push(newGroup); }); @@ -158,7 +159,9 @@ export default class GroupAdminBrowser extends LitElement { this.study.groups?.forEach(group => { const newGroup = { studyId: this.study.id, - groupId: group.id, + fqn: this.study.fqn, + group: group, + isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), }; this._groups.push(newGroup); }); @@ -208,7 +211,7 @@ export default class GroupAdminBrowser extends LitElement { if (!this.opencgaSession) { return html`
Not valid session
`; } -debugger + return html ` ${this.renderFilterGraphics()} diff --git a/src/webcomponents/organization/admin/group-admin-delete.js b/src/webcomponents/organization/admin/group-admin-delete.js new file mode 100644 index 000000000..570b32790 --- /dev/null +++ b/src/webcomponents/organization/admin/group-admin-delete.js @@ -0,0 +1,150 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; + +export default class GroupAdminDelete extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + group: { + type: Object, + }, + studyFqn: { + type: String, + }, + active: { + type: Boolean, + }, + opencgaSession: { + type: Object, + }, + displayConfig: { + type: Object, + }, + }; + } + + #init() { + this.isLoading = false; + this.isStudyAdmin = false; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + defaultLayout: "horizontal", + buttonOkText: "I understand. Let's delete this group" + }; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("displayConfig")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + } + super.update(changedProperties); + } + + onSubmit() { + this.#setLoading(true); + let error; + return this.opencgaSession.opencgaClient.studies() + .updateGroups(this.studyFqn, {id: this.group.id}, {action: "REMOVE"}) + .then(() => { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `Group Delete`, + message: `Group ${this.group.id} in study ${this.studyId} deleted successfully`, + }); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "groupDelete", {}, { + id: this.group.id, + study: this.studyFqn, + }, error); + this.#setLoading(false); + + }); + } + + render() { + if (this.isLoading) { + return html``; + } + + return html` + + `; + } + + getDefaultConfig() { + return { + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + title: "Do you really want to delete this group?", + elements: [ + { + type: "notification", + text: "The following users could have unexpected permissions if you remove this group", + display: { + visible: true, + icon: "fas fa-exclamation-triangle", + notificationType: "error", + }, + }, + { + type: "list", + display: { + contentLayout: "vertical", + getData: group => group.ids || ["This group does not have users"], + }, + }, + ], + }, + ], + }; + } + +} + +customElements.define("group-admin-delete", GroupAdminDelete); diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index 9502ba03d..01c57a461 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -21,6 +21,7 @@ import ModalUtils from "../../commons/modal/modal-utils"; import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; import "./group-admin-create.js"; import "./group-admin-update.js"; +import "./group-admin-delete.js"; export default class GroupAdminGrid extends LitElement { @@ -109,7 +110,6 @@ export default class GroupAdminGrid extends LitElement { // disabledTooltip: "...", }, render: () => { - debugger return html ` ` + formatter: (value, row) => `
- -
` : null} - ${this.config.enabledComponents["projects-admin"] ? html` - -
- - -
- ` : null} - ${this.config.enabledComponents["catalog-admin"] ? html`
` : null} - ${this.config.enabledComponents["study-variant-admin"] ? html` -
- - -
- ` : null} + ${this.config.enabledComponents["operations-admin"] ? html` +
+ + +
+ ` : null} + ${this.config.enabledComponents["rest-api"] ? html` diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index 7fc1cd7b3..189954cf0 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -16,6 +16,7 @@ import {LitElement, html} from "lit"; import UtilsNew from "../../../core/utils-new"; import LitUtils from "../../commons/utils/lit-utils"; +import "../../project/projects-admin.js"; import "./group-admin-browser.js"; import "./user-admin-browser.js"; @@ -65,6 +66,8 @@ export default class OrganizationAdmin extends LitElement { super.update(changedProperties); } + + organizationIdObserver() { // FIXME Vero: on creating a new group, for instance, // the session is updated but the org id does not change. @@ -117,7 +120,7 @@ export default class OrganizationAdmin extends LitElement { name: "Dashboard", description: "", icon: "", - featured: "", // true | false + featured: "", visibility: "private", submenu: [ // TODO: pending refactor and fix @@ -174,7 +177,15 @@ export default class OrganizationAdmin extends LitElement { name: "Projects/Studies", icon: "fas fa-vial", visibility: "private", - render: (opencgaSession, study) => html``, + render: (opencgaSession, study) => { + return html` +
+ + +
+ `; + }, }, ], }, @@ -183,7 +194,7 @@ export default class OrganizationAdmin extends LitElement { name: "Configure", description: "", icon: "", - featured: "", // true | false + featured: "", visibility: "private", submenu: [ { diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index e6e14b9bb..a710899f2 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -21,6 +21,10 @@ import "./study-admin-permissions.js"; import "./study-admin-variable.js"; import "./study-admin-audit.js"; import "./study-admin-configuration.js"; + +import "../../variant/operation/clinical-analysis-configuration-operation.js"; +import "../../variant/operation/variant-secondary-sample-index-configure-operation.js"; + import LitUtils from "../../commons/utils/lit-utils"; import "../../commons/layouts/custom-vertical-navbar.js"; @@ -449,8 +453,6 @@ export default class StudyAdmin extends LitElement { logo: "", icon: "fas fa-sliders-h", visibility: "private", // public | private | none - // title: "Study", - // sections: [ menu: [ { id: "configuration", @@ -460,28 +462,6 @@ export default class StudyAdmin extends LitElement { featured: "", // true | false visibility: "private", submenu: [ - // { - // id: "Dashboard", - // name: "Dashboard", - // visibility: "private", - // icon: "fas fa-tachometer-alt", - // // QUESTION: Which one: (a) or (b) - // // question: (a) - // // display: { - // // contentClass: "", - // // contentStyle: "" - // // defaultLayout: "vertical", - // // render: () => html` - // // - // // .title="Study dashboard" - // // `, - // // }, - // // question: (b) - // render: () => html` - // - // .title="Study dashboard" - // `, - // }, { id: "UsersAndGroups", // label: "Users and Groups", @@ -530,6 +510,34 @@ export default class StudyAdmin extends LitElement { .study="${study}"> `, }, + { + id: "clinical-analysis-configuration-operation", + name: "Clinical Analysis Configuration", + icon: "fas fa-key", + visibility: "private", + render: (opencgaSession, study) => { + return html ` + + + `; + } + }, + { + id: "variant-secondary-sample-configure-index", + name: "Sample Index Configuration", + icon: "fas fa-key", + visibility: "private", + render: (opencgaSession, study) => { + return html ` + + + `; + } + }, // { // id: "Configuration", // // label: "Configuration", @@ -544,28 +552,31 @@ export default class StudyAdmin extends LitElement { // }, ], }, - { - id: "Operations", - name: "Operations", - category: true, // true | false - visibility: "none", - submenu: [ - { - id: "Solr", - // label: "Solr", - name: "Solr", - // CAUTION: icon vs. img in config.js? - img: "/sites/iva/img/logos/Solr.png", - visibility: "private", - }, - { - id: "Rysnc", - label: "Rysnc", - icon: "", - visibility: "private", - }, - ], - }, + // { + // id: "Operations", + // name: "Operations", + // category: true, // true | false + // visibility: "private", + // description: "", + // icon: "", + // featured: "", // true | false + // submenu: [ + // // { + // // id: "Solr", + // // // label: "Solr", + // // name: "Solr", + // // // CAUTION: icon vs. img in config.js? + // // img: "/sites/iva/img/logos/Solr.png", + // // visibility: "private", + // // }, + // // { + // // id: "Rysnc", + // // label: "Rysnc", + // // icon: "", + // // visibility: "private", + // // }, + // ], + // }, ], }; } diff --git a/src/webcomponents/study/admin/variant/operations-admin.js b/src/webcomponents/study/admin/variant/operations-admin.js new file mode 100644 index 000000000..d618e51ff --- /dev/null +++ b/src/webcomponents/study/admin/variant/operations-admin.js @@ -0,0 +1,210 @@ +/** + * Copyright 2015-2019 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html} from "lit"; +import LitUtils from "../../../commons/utils/lit-utils"; +import "../../../variant/operation/variant-index-operation.js"; +import "../../../variant/operation/variant-stats-index-operation.js"; +import "../../../variant/operation/variant-annotation-index-operation.js"; +import "../../../variant/operation/variant-secondary-annotation-index-operation.js"; +import "../../../variant/operation/variant-secondary-sample-index-operation.js"; +import "../../../commons/layouts/custom-vertical-navbar.js"; + +export default class OperationsAdmin extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + studyId: { + type: String + }, + study: { + type: Object + }, + opencgaSession: { + type: Object + }, + }; + } + + #init() { + this.study = {}; + this._config = this.getDefaultConfig(); + } + + update(changedProperties) { + if (changedProperties.has("studyId")) { + this.studyIdObserver(); + } + if (changedProperties.has("opencgaSession")) { + this.opencgaSessionObserver(); + } + super.update(changedProperties); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + studyIdObserver() { + if (this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this.study = response.responses[0].results[0]; + }) + .catch(reason => { + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + this.#setLoading(false); + }); + } + } + + opencgaSessionObserver() { + this._config = this.getDefaultConfig(); + } + + render() { + const activeMenuItem = "variant-annotation-index"; + return html` + + + + `; + } + + getDefaultConfig() { + return { + id: "", + name: "Operations Admin", + logo: "", + icon: "", + visibility: "", // public | private | none + menu: [ + { + id: "organization-operations", + name: "Organization Operations", + description: "", + icon: "", + visibility: "private", + featured: "", + category: true, + submenu: [ + { + id: "variant-annotation-index", + name: "Variant Annotation Index", + icon: "fas fa-key", + visibility: "private", + render: opencgaSession => html` + + + `, + }, + { + id: "variant-secondary-annotation-index", + name: "Variant Secondary Annotation Index. *** CAUTION: Automatic in OpenCGA for 2.2? ***", + icon: "fas fa-key", + visibility: "private", + render: opencgaSession => html` + + + `, + }, + ], + }, + { + id: "variant-operations", + name: "Study Operations", + description: "", + icon: "", + visibility: "private", + featured: "", + category: true, + submenu: [ + { + id: "variant-index", + name: "Variant Index", + icon: "fas fa-key", + visibility: "private", + render: (opencgaSession, study) => html` + + + `, + }, + { + id: "variant-stats-index", + name: "Variant Stats Index", + icon: "fas fa-key", + visibility: "private", + render: (opencgaSession, study) => html` + + + `, + }, + { + id: "variant-secondary-sample-index", + name: "Variant Secondary Sample Index. *** CAUTION: Automatic in OpenCGA for 2.2? ***", + icon: "fas fa-key", + visibility: "private", + type: "navitem", + render: (opencgaSession, study) => { + // CAUTION: no .fqn? in toolParams property? + return html` + + + `; + }, + }, + ], + }, + ], + }; + } + +} + +customElements.define("operations-admin", OperationsAdmin); From 95e8fb3d2494fc9ef595d10615158d19f9c7a251 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 13:58:26 +0200 Subject: [PATCH 014/177] wc - WiP Moved configuration indexes here, slightly restructured menu Signed-off-by: gpveronica --- src/webcomponents/study/admin/study-admin.js | 71 +++++++++++++------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index a710899f2..f3b4189ae 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -498,18 +498,28 @@ export default class StudyAdmin extends LitElement { .study="${study}"> `, }, - { - id: "Audit", - // label: "Audit", - name: "Audit", - icon: "fas fa-book", - visibility: "private", - render: (opencgaSession, study) => html` - - `, - }, + // { + // id: "Configuration", + // // label: "Configuration", + // name: "Configuration", + // icon: "fas fa-cog", + // visibility: "private", + // render: (opencgaSession, study) => html` + // + // `, + // }, + ], + }, + { + id: "variant-configuration", + name: "Variant Configuration", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ { id: "clinical-analysis-configuration-operation", name: "Clinical Analysis Configuration", @@ -518,7 +528,7 @@ export default class StudyAdmin extends LitElement { render: (opencgaSession, study) => { return html ` `; @@ -532,24 +542,33 @@ export default class StudyAdmin extends LitElement { render: (opencgaSession, study) => { return html ` `; } }, - // { - // id: "Configuration", - // // label: "Configuration", - // name: "Configuration", - // icon: "fas fa-cog", - // visibility: "private", - // render: (opencgaSession, study) => html` - // - // `, - // }, + ], + }, + { + id: "audit", + name: "Audit", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ + { + id: "Audit", + name: "Audit", + icon: "fas fa-book", + visibility: "private", + render: (opencgaSession, study) => html` + + `, + }, ], }, // { From 47f5491fbeaf768dc489fe7216e9f7417445c5ff Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 13:58:54 +0200 Subject: [PATCH 015/177] wc - WiP Restructured menu Signed-off-by: gpveronica --- .../organization/admin/organization-admin.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index 189954cf0..c1c844485 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -123,10 +123,10 @@ export default class OrganizationAdmin extends LitElement { featured: "", visibility: "private", submenu: [ - // TODO: pending refactor and fix + // TODO { - id: "audit", - name: "Audit", + id: "dashboard", + name: "Dashboard", icon: "fas fa-vial", visibility: "private", render: (opencgaSession, study) => html``, @@ -213,6 +213,26 @@ export default class OrganizationAdmin extends LitElement { }, ], }, + { + id: "audit", + name: "Audit", + description: "", + icon: "", + featured: "", + visibility: "private", + submenu: [ + // TODO + { + id: "audit", + name: "Audit", + type: "category", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, + ], + }, + ]; return { From d6e6664c546d01c63c995731f0c7320990d3b6c4 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 17:32:52 +0200 Subject: [PATCH 016/177] client - Updated clients from TASK-5980 Signed-off-by: gpveronica --- src/core/clients/opencga/api/Admin.js | 7 +- src/core/clients/opencga/api/Alignment.js | 2 +- .../clients/opencga/api/ClinicalAnalysis.js | 2 +- src/core/clients/opencga/api/Cohort.js | 2 +- src/core/clients/opencga/api/DiseasePanel.js | 2 +- src/core/clients/opencga/api/Family.js | 2 +- src/core/clients/opencga/api/File.js | 15 +++- src/core/clients/opencga/api/GA4GH.js | 2 +- src/core/clients/opencga/api/Individual.js | 2 +- src/core/clients/opencga/api/Job.js | 2 +- src/core/clients/opencga/api/Meta.js | 2 +- src/core/clients/opencga/api/Organization.js | 60 +++++++++++++++- src/core/clients/opencga/api/Project.js | 2 +- src/core/clients/opencga/api/Sample.js | 2 +- src/core/clients/opencga/api/Study.js | 69 +++++++++++++++++-- src/core/clients/opencga/api/User.js | 20 +++++- src/core/clients/opencga/api/Variant.js | 2 +- .../clients/opencga/api/VariantOperation.js | 2 +- 18 files changed, 173 insertions(+), 24 deletions(-) diff --git a/src/core/clients/opencga/api/Admin.js b/src/core/clients/opencga/api/Admin.js index 5997bed88..7fcab0384 100644 --- a/src/core/clients/opencga/api/Admin.js +++ b/src/core/clients/opencga/api/Admin.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -34,8 +34,8 @@ export default class Admin extends OpenCGAParentClass { /** Group by operation * @param {String} fields - Comma separated list of fields by which to group by. - * @param {"AUDIT ORGANIZATION USER PROJECT STUDY FILE SAMPLE JOB INDIVIDUAL COHORT DISEASE_PANEL FAMILY CLINICAL_ANALYSIS INTERPRETATION - * VARIANT ALIGNMENT CLINICAL EXPRESSION RGA FUNCTIONAL"} entity - Entity to be grouped by. + * @param {"AUDIT NOTE ORGANIZATION USER PROJECT STUDY FILE SAMPLE JOB INDIVIDUAL COHORT DISEASE_PANEL FAMILY CLINICAL_ANALYSIS + * INTERPRETATION VARIANT ALIGNMENT CLINICAL EXPRESSION RGA FUNCTIONAL"} entity - Entity to be grouped by. * @param {Object} [params] - The Object containing the following optional parameters: * @param {Boolean} [params.count] - Count the number of elements matching the group. * @param {Number} [params.limit = "50"] - Maximum number of documents (groups) to be returned. The default value is 50. @@ -107,7 +107,6 @@ export default class Admin extends OpenCGAParentClass { * value is false. * @param {String} [params.organization] - Organization id. * @param {String} [params.user] - User ID. - * @param {String} [params.account] - Account type [GUEST, FULL, ADMINISTRATOR]. * @param {String} [params.authenticationId] - Authentication origin ID. * @returns {Promise} Promise object in the form of RestResponse instance. */ diff --git a/src/core/clients/opencga/api/Alignment.js b/src/core/clients/opencga/api/Alignment.js index 9173d6738..1ec703a5d 100644 --- a/src/core/clients/opencga/api/Alignment.js +++ b/src/core/clients/opencga/api/Alignment.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/ClinicalAnalysis.js b/src/core/clients/opencga/api/ClinicalAnalysis.js index 2d47cced7..e445a6139 100644 --- a/src/core/clients/opencga/api/ClinicalAnalysis.js +++ b/src/core/clients/opencga/api/ClinicalAnalysis.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Cohort.js b/src/core/clients/opencga/api/Cohort.js index 237d874af..6f9ac1e3c 100644 --- a/src/core/clients/opencga/api/Cohort.js +++ b/src/core/clients/opencga/api/Cohort.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/DiseasePanel.js b/src/core/clients/opencga/api/DiseasePanel.js index 44b47ec7d..4343bc420 100644 --- a/src/core/clients/opencga/api/DiseasePanel.js +++ b/src/core/clients/opencga/api/DiseasePanel.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Family.js b/src/core/clients/opencga/api/Family.js index 028113d98..245c24abe 100644 --- a/src/core/clients/opencga/api/Family.js +++ b/src/core/clients/opencga/api/Family.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/File.js b/src/core/clients/opencga/api/File.js index 4419c507e..0a085be81 100644 --- a/src/core/clients/opencga/api/File.js +++ b/src/core/clients/opencga/api/File.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -389,6 +389,19 @@ export default class File extends OpenCGAParentClass { return this._get("files", file, null, null, "image", params); } + /** Move file to a different path + * @param {String} file - File id, UUID or name. + * @param {Object} data - Parameters to modify. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + move(file, data, params) { + return this._post("files", file, null, null, "move", data, params); + } + /** Refresh metadata from the selected file or folder. Return updated files. * @param {String} file - File id, name or path. Paths must be separated by : instead of /. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/GA4GH.js b/src/core/clients/opencga/api/GA4GH.js index b06055721..1bef974d3 100644 --- a/src/core/clients/opencga/api/GA4GH.js +++ b/src/core/clients/opencga/api/GA4GH.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Individual.js b/src/core/clients/opencga/api/Individual.js index a3307d522..ce94d5060 100644 --- a/src/core/clients/opencga/api/Individual.js +++ b/src/core/clients/opencga/api/Individual.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Job.js b/src/core/clients/opencga/api/Job.js index b83184040..1d2aa95b0 100644 --- a/src/core/clients/opencga/api/Job.js +++ b/src/core/clients/opencga/api/Job.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Meta.js b/src/core/clients/opencga/api/Meta.js index 7028dd5ea..6d9869452 100644 --- a/src/core/clients/opencga/api/Meta.js +++ b/src/core/clients/opencga/api/Meta.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Organization.js b/src/core/clients/opencga/api/Organization.js index 3884dc598..a429ccf68 100644 --- a/src/core/clients/opencga/api/Organization.js +++ b/src/core/clients/opencga/api/Organization.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -45,6 +45,64 @@ export default class Organization extends OpenCGAParentClass { return this._post("organizations", null, null, null, "create", data, params); } + /** Create a new note + * @param {Object} data - JSON containing the Note to be added. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + createNotes(data, params) { + return this._post("organizations", null, "notes", null, "create", data, params); + } + + /** Search for notes of scope ORGANIZATION + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {String} [params.creationDate] - Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {String} [params.modificationDate] - Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {String} [params.id] - Note unique identifier. + * @param {String} [params.scope] - Scope of the Note. + * @param {String} [params.visibility] - Visibility of the Note. + * @param {String} [params.uuid] - Unique 32-character identifier assigned automatically by OpenCGA. + * @param {String} [params.userId] - User that wrote that Note. + * @param {String} [params.tags] - Note tags. + * @param {String} [params.version] - Autoincremental version assigned to the registered entry. By default, updates does not create new + * versions. To enable versioning, users must set the `incVersion` flag from the /update web service when updating the document. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + searchNotes(params) { + return this._get("organizations", null, "notes", null, "search", params); + } + + /** Delete note + * @param {String} id - Note unique identifier. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + deleteNotes(id, params) { + return this._delete("organizations", null, "notes", id, "delete", params); + } + + /** Update a note + * @param {String} id - Note unique identifier. + * @param {Object} data - JSON containing the Note fields to be updated. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + updateNotes(id, data, params) { + return this._post("organizations", null, "notes", id, "update", data, params); + } + /** Return the organization information * @param {String} organization - Organization id. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Project.js b/src/core/clients/opencga/api/Project.js index 3767afc6b..e58af550d 100644 --- a/src/core/clients/opencga/api/Project.js +++ b/src/core/clients/opencga/api/Project.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Sample.js b/src/core/clients/opencga/api/Sample.js index 1d4f379fa..f4ae4e296 100644 --- a/src/core/clients/opencga/api/Sample.js +++ b/src/core/clients/opencga/api/Sample.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Study.js b/src/core/clients/opencga/api/Study.js index b170fbf1c..d13f1d427 100644 --- a/src/core/clients/opencga/api/Study.js +++ b/src/core/clients/opencga/api/Study.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -116,8 +116,8 @@ export default class Study extends OpenCGAParentClass { * @param {String} [params.operationId] - Audit operation UUID. * @param {String} [params.userId] - User ID. * @param {String} [params.action] - Action performed by the user. - * @param {"AUDIT ORGANIZATION USER PROJECT STUDY FILE SAMPLE JOB INDIVIDUAL COHORT DISEASE_PANEL FAMILY CLINICAL_ANALYSIS INTERPRETATION - * VARIANT ALIGNMENT CLINICAL EXPRESSION RGA FUNCTIONAL"} [params.resource] - Resource involved. + * @param {"AUDIT NOTE ORGANIZATION USER PROJECT STUDY FILE SAMPLE JOB INDIVIDUAL COHORT DISEASE_PANEL FAMILY CLINICAL_ANALYSIS + * INTERPRETATION VARIANT ALIGNMENT CLINICAL EXPRESSION RGA FUNCTIONAL"} [params.resource] - Resource involved. * @param {String} [params.resourceId] - Resource ID. * @param {String} [params.resourceUuid] - resource UUID. * @param {"SUCCESS ERROR"} [params.status] - Filter by status. @@ -164,6 +164,67 @@ export default class Study extends OpenCGAParentClass { return this._post("studies", study, "groups", group, "users/update", data, params); } + /** Create a new note + * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {Object} data - JSON containing the Note to be added. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + createNotes(study, data, params) { + return this._post("studies", study, "notes", null, "create", data, params); + } + + /** Search for notes of scope STUDY + * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {String} [params.creationDate] - Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {String} [params.modificationDate] - Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {String} [params.id] - Note unique identifier. + * @param {String} [params.uuid] - Unique 32-character identifier assigned automatically by OpenCGA. + * @param {String} [params.userId] - User that wrote that Note. + * @param {String} [params.tags] - Note tags. + * @param {String} [params.visibility] - Visibility of the Note. + * @param {String} [params.version] - Autoincremental version assigned to the registered entry. By default, updates does not create new + * versions. To enable versioning, users must set the `incVersion` flag from the /update web service when updating the document. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + searchNotes(study, params) { + return this._get("studies", study, "notes", null, "search", params); + } + + /** Delete note + * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {String} id - Note unique identifier. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + deleteNotes(study, id, params) { + return this._delete("studies", study, "notes", id, "delete", params); + } + + /** Update a note + * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {String} id - Note unique identifier. + * @param {Object} data - JSON containing the Note fields to be updated. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + updateNotes(study, id, data, params) { + return this._post("studies", study, "notes", id, "update", data, params); + } + /** Fetch permission rules * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @param {"SAMPLES FILES COHORTS INDIVIDUALS FAMILIES JOBS CLINICAL_ANALYSES DISEASE_PANELS"} entity - Entity where the permission rules @@ -216,7 +277,7 @@ export default class Study extends OpenCGAParentClass { } /** Delete template - * @param {String} [study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {String} study - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @param {String} templateId - Template id. * @returns {Promise} Promise object in the form of RestResponse instance. */ diff --git a/src/core/clients/opencga/api/User.js b/src/core/clients/opencga/api/User.js index c5c7544c6..e478e03db 100644 --- a/src/core/clients/opencga/api/User.js +++ b/src/core/clients/opencga/api/User.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -64,6 +64,24 @@ export default class User extends OpenCGAParentClass { return this._post("users", null, null, null, "password", data); } + /** User search method + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Number} [params.limit] - Number of results to be returned. + * @param {Number} [params.skip] - Number of results to skip. + * @param {Boolean} [params.count = "false"] - Get the total number of results matching the query. Deactivated by default. The default + * value is false. + * @param {String} [params.organization] - Organization id. + * @param {String} [params.id] - Comma separated list user IDs up to a maximum of 100. Also admits basic regular expressions using the + * operator '~', i.e. '~{perl-regex}' e.g. '~value' for case sensitive, '~/value/i' for case insensitive search. + * @param {String} [params.authenticationId] - Authentication origin ID. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + search(params) { + return this._get("users", null, null, null, "search", params); + } + /** Return the user information including its projects and studies * @param {String} users - Comma separated list of user IDs. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Variant.js b/src/core/clients/opencga/api/Variant.js index 98d42a16f..c341d110c 100644 --- a/src/core/clients/opencga/api/Variant.js +++ b/src/core/clients/opencga/api/Variant.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/VariantOperation.js b/src/core/clients/opencga/api/VariantOperation.js index 9ceb02dd5..a178fbbdd 100644 --- a/src/core/clients/opencga/api/VariantOperation.js +++ b/src/core/clients/opencga/api/VariantOperation.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-03-06 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. From 64b36e5a296662f7e3f3846151aae62b9740e2e9 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 18:56:10 +0200 Subject: [PATCH 017/177] client - Removed userId path param automatically set in search method Signed-off-by: gpveronica --- src/core/clients/opencga/opencga-parent-class.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/clients/opencga/opencga-parent-class.js b/src/core/clients/opencga/opencga-parent-class.js index 14e74f6ee..7e8651e24 100644 --- a/src/core/clients/opencga/opencga-parent-class.js +++ b/src/core/clients/opencga/opencga-parent-class.js @@ -33,11 +33,14 @@ export default class OpenCGAParentClass { _options.token = sid; } } - + // CAUTION Vero 2024-05-10: We believe this bit of code is useless. Temporarily commented out. + // In users endpoint, we cannot find GET method where the path param {user/users} should be autocompleted. + // When needed, they should be explicitly set. // If category == users and userId is not given, we try to set it - if (category1 === "users" && (ids1 === undefined || ids1 === null || ids1 === "")) { - ids1 = this._getUserId(); - } + // if (category1 === "users" && (ids1 === undefined || ids1 === null || ids1 === "")) { + // ids1 = this._getUserId(); + // } + let url = this._createRestUrl(host, version, category1, ids1, category2, ids2, action); // if (method === "GET") { url = this._addQueryParams(url, _params); From c8a100c592f3d4d665e07215351b7f2b9224ebc7 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 19:04:11 +0200 Subject: [PATCH 018/177] wc - Replaced correct endpoint and method for retrieving list of users after TASK in openCGA finished, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/user-admin-grid.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index c28d62357..19798d1ec 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -144,7 +144,7 @@ export default class UserAdminGrid extends LitElement { } renderRemoteTable() { - if (this.opencgaSession?.opencgaClient) { + if (this.opencgaSession?.opencgaClient && this.organization.id) { this._columns = this._getDefaultColumns(); this.table = $("#" + this.gridId); this.table.bootstrapTable("destroy"); @@ -168,14 +168,15 @@ export default class UserAdminGrid extends LitElement { ajax: params => { let result = null; this.filters = { + organization: this.organization.id, limit: params.data.limit, skip: params.data.offset || 0, count: !this.table.bootstrapTable("getOptions").pageNumber || this.table.bootstrapTable("getOptions").pageNumber === 1, }; // Store the current filters - this.opencgaSession.opencgaClient.admin() - .searchUsers({organization: "test", ...this.filters}) + this.opencgaSession.opencgaClient.users() + .search(this.filters) .then(response => { result = response; return response; From 5c69c0dfb7b5a5eee2b373f9efd11332f549f359 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 10 May 2024 19:06:10 +0200 Subject: [PATCH 019/177] wc - WiP Refactored menu in organizations, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/organization-admin.js | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index c1c844485..032f790bb 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -141,18 +141,18 @@ export default class OrganizationAdmin extends LitElement { featured: "", // true | false visibility: "private", submenu: [ - { - id: "groups", - name: "Groups", - icon: "fas fa-vial", - visibility: "private", - render: (opencgaSession, organization) => html` - - - `, - }, + // { + // id: "groups", + // name: "Groups", + // icon: "fas fa-vial", + // visibility: "private", + // render: (opencgaSession, organization) => html` + // + // + // `, + // }, { id: "users", name: "Users", @@ -165,13 +165,6 @@ export default class OrganizationAdmin extends LitElement { `, }, - { - id: "settings", - name: "Settings", - icon: "fas fa-vial", - visibility: "private", - render: (opencgaSession, study) => html``, - }, { id: "studies", name: "Projects/Studies", @@ -198,19 +191,26 @@ export default class OrganizationAdmin extends LitElement { visibility: "private", submenu: [ { - id: "identity-providers", - name: "Identity Providers", - icon: "fas fa-vial", - visibility: "private", - render: (opencgaSession, study) => html``, - }, - { - id: "optimization", - name: "Optimizations", + id: "settings", + name: "Organization", icon: "fas fa-vial", visibility: "private", render: (opencgaSession, study) => html``, }, + // { + // id: "identity-providers", + // name: "Identity Providers", + // icon: "fas fa-vial", + // visibility: "private", + // render: (opencgaSession, study) => html``, + // }, + // { + // id: "optimization", + // name: "Optimizations", + // icon: "fas fa-vial", + // visibility: "private", + // render: (opencgaSession, study) => html``, + // }, ], }, { From 3f0614875be98641fad919839ddff162b4e38bbb Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 15 May 2024 15:58:15 +0200 Subject: [PATCH 020/177] wc - WiP Set dashboard/audit under General menu, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/organization-admin.js | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index 032f790bb..f4518ab31 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -116,8 +116,8 @@ export default class OrganizationAdmin extends LitElement { getDefaultConfig() { const menu = [ { - id: "dashboard", - name: "Dashboard", + id: "general", + name: "General", description: "", icon: "", featured: "", @@ -131,6 +131,15 @@ export default class OrganizationAdmin extends LitElement { visibility: "private", render: (opencgaSession, study) => html``, }, + // TODO + { + id: "audit", + name: "Audit", + type: "category", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, study) => html``, + }, ], }, { @@ -213,26 +222,6 @@ export default class OrganizationAdmin extends LitElement { // }, ], }, - { - id: "audit", - name: "Audit", - description: "", - icon: "", - featured: "", - visibility: "private", - submenu: [ - // TODO - { - id: "audit", - name: "Audit", - type: "category", - icon: "fas fa-vial", - visibility: "private", - render: (opencgaSession, study) => html``, - }, - ], - }, - ]; return { From 62a3c8553ffe98928d262ca86a3b093f125a02fb Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 17:13:30 +0200 Subject: [PATCH 021/177] wc - WiP Admin user password change, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-password-change.js | 220 ++++++++++++++++++ .../user/user-password-change.js | 141 +++++++---- src/webcomponents/user/user-profile.js | 2 + 3 files changed, 316 insertions(+), 47 deletions(-) create mode 100644 src/webcomponents/organization/admin/user-admin-password-change.js diff --git a/src/webcomponents/organization/admin/user-admin-password-change.js b/src/webcomponents/organization/admin/user-admin-password-change.js new file mode 100644 index 000000000..ac7265265 --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-password-change.js @@ -0,0 +1,220 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import "../../user/user-password-change.js"; + +export default class UserAdminPasswordChange extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + userId: { + type: String + }, + organization: { + type: Object, + }, + active: { + type: Boolean, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this._user = {}; // Updated object + this.userId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initOriginalObjects() { + this._user = UtilsNew.objectClone(this.user); + this.updatedFields = {}; + } + + update(changedProperties) { + if (changedProperties.has("userId")) { + this.userIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + userIdObserver() { + if (this.userId && this.opencgaSession) { + const params = { + organization: this.organization.id, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.users() + .info(this.userId, params) + .then(response => { + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userInfo", this.user, {}, error); + this.#setLoading(false); + }); + } + } + + render() { + return html ` + + + `; + } + + getDefaultConfig() { + return { + title: "", + showTitle: false, + items: [ + { + id: "change-password", + name: "Change Password", + active: true, + render: (user, active, opencgaSession) => { + return html` + + + `; + }, + }, + ], + }; + /* + return { + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig, + sections: [ + { + title: "Change Password", + elements: [ + { + type: "custom", + display: { + render: () => { + debugger + return html` + + + `; + }, + }, + }, + /* + { + title: "Reset password", + field: "pwdReset", + type: "toggle-switch", + display: { + disabled: true, + helpMessage: "Coming soon: Force user to reset the password", + }, + }, + { + title: "Expires in", + field: "pwdExpiration", + type: "input-text", + display: { + disabled: true, + helpMessage: "Coming soon: Enable password expiration", + }, + }, + */ + /* + ], + }, + ], + }; + */ + } + +} + +customElements.define("user-admin-password-change", UserAdminPasswordChange); diff --git a/src/webcomponents/user/user-password-change.js b/src/webcomponents/user/user-password-change.js index 70a514cc8..4e5d61908 100644 --- a/src/webcomponents/user/user-password-change.js +++ b/src/webcomponents/user/user-password-change.js @@ -2,6 +2,7 @@ import {LitElement, html} from "lit"; import UtilsNew from "../../core/utils-new.js"; import NotificationUtils from "../commons/utils/notification-utils.js"; import "../commons/forms/data-form.js"; +import LitUtils from "../commons/utils/lit-utils"; export default class UserPasswordChange extends LitElement { @@ -16,55 +17,99 @@ export default class UserPasswordChange extends LitElement { static get properties() { return { + userId: { + type: String, + }, opencgaSession: { type: Object }, + organizationId: { + type: String, + }, + displayConfig: { + type: Object + }, }; } #init() { - this.updateParams = {}; - this.config = this.getDefaultConfig(); + this._password = {}; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + titleStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", + defaultLayout: "horizontal", + buttonOkText: "Change password", + }; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initOriginalObjects() { + this._password = {}; + this._config = this.getDefaultConfig(); + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("displayConfig")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + this._config = this.getDefaultConfig(); + } + super.update(changedProperties); } onFieldChange(e) { - this.updateParams[e.detail.param] = e.detail.value; - this.updateParams = {...this.updateParams}; + this._password = {...e.detail.data}; // force to refresh the object-list this.requestUpdate(); } onSubmit() { - this.opencgaSession.opencgaClient.getClient("user").password({ - user: this.opencgaSession.user.id, - password: this.updateParams.oldPassword, - newPassword: this.updateParams.newPassword, - }) + const params = { + user: this.userId, + password: this._password.oldPassword, + newPassword: this._password.newPassword, + organizationId: this.organizationId, + }; + this.#setLoading(true); + debugger + this.opencgaSession.opencgaClient.users() + .password(params) .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { message: "Your password has been changed", }); - this.onClear(); + this.#initOriginalObjects(); }) .catch(response => { - // console.error(response); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, response); + }) + .finally(() => { + this.#setLoading(false); }); } onClear() { - this.updateParams = {}; - // Terrible hack to reset the values in the input elements - // eslint-disable-next-line no-param-reassign - Array.from(this.querySelectorAll("input")).forEach(el => el.value = ""); - this.requestUpdate(); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Clear password", + message: "Are you sure to clear?", + ok: () => this.#initOriginalObjects(), + }); } render() { // TODO: check if opencgaSession has been provided return html` @@ -74,45 +119,47 @@ export default class UserPasswordChange extends LitElement { getDefaultConfig() { return { - icon: "", - display: { - buttonOkText: "Change password", - }, - // validation: { - // validate: () => this.updateParams.newPassword === this.updateParams.confirmNewPassword, - // message: "New passwords do not match", + // icon: "", + // display: { + // buttonOkText: "Change password", // }, + // // validation: { + // // validate: () => this.updateParams.newPassword === this.updateParams.confirmNewPassword, + // // message: "New passwords do not match", + // // }, + title: "Change Password", + display: this.displayConfig || this.displayConfigDefault, sections: [ { // title: "Change password", // description: "Here you can change your password. Make sure it has at least 8 characters.", elements: [ - { - type: "text", - text: "Change password", - display: { - icon: "user-shield", - textClassName: "h2", - textStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", - }, - }, - { - type: "text", - text: ` - Here you can change your password. We recommend that your new password has at least - 8 characters long and uses uppercase and lowercase letters and numbers. - `, - display: { - textStyle: "margin-bottom:16px;", - }, - }, + // { + // type: "text", + // text: "Change password", + // display: { + // icon: "user-shield", + // textClassName: "h2", + // textStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", + // }, + // }, + // { + // type: "text", + // text: ` + // Here you can change your password. We recommend that your new password has at least + // 8 characters long and uses uppercase and lowercase letters and numbers. + // `, + // display: { + // textStyle: "margin-bottom:16px;", + // }, + // }, { title: "Current password", type: "input-password", field: "oldPassword", defaultValue: "", validation: { - validate: () => !!this.updateParams.oldPassword, + validate: () => !!this._password.oldPassword, message: "Please enter your existing password.", }, }, @@ -122,7 +169,7 @@ export default class UserPasswordChange extends LitElement { field: "newPassword", defaultValue: "", validation: { - validate: () => !!this.updateParams.newPassword, + validate: () => !!this._password.newPassword, message: "Your new password can not be empty.", }, }, @@ -133,7 +180,7 @@ export default class UserPasswordChange extends LitElement { defaultValue: "", validation: { validate: () => { - return !!this.updateParams.confirmNewPassword && this.updateParams.confirmNewPassword === this.updateParams.newPassword; + return !!this._password.confirmNewPassword && this._password.confirmNewPassword === this._password.newPassword; }, message: "New passwords do not match.", }, diff --git a/src/webcomponents/user/user-profile.js b/src/webcomponents/user/user-profile.js index 0b29cf204..c0848f9aa 100644 --- a/src/webcomponents/user/user-profile.js +++ b/src/webcomponents/user/user-profile.js @@ -95,6 +95,8 @@ export default class UserProfile extends LitElement { render: (data, active, opencgaSession) => html`
From ec58dc8932c19636658e9d2c6dbfcbecad7e44f5 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 17:14:37 +0200 Subject: [PATCH 022/177] wc - WiP Change Actions to dropdown, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 180 +++++++++++++++--- 1 file changed, 156 insertions(+), 24 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 19798d1ec..0d5a061a3 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -15,13 +15,17 @@ */ import {LitElement, html, nothing} from "lit"; -import GridCommons from "../../commons/grid-commons"; -import UtilsNew from "../../../core/utils-new"; -import ModalUtils from "../../commons/modal/modal-utils"; -import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; +import GridCommons from "../../commons/grid-commons.js"; +import UtilsNew from "../../../core/utils-new.js"; +import ModalUtils from "../../commons/modal/modal-utils.js"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; + import "./user-admin-create.js"; import "./user-admin-update.js"; -import NotificationUtils from "../../commons/utils/notification-utils"; +import "./user-admin-details-update.js"; +import "./user-admin-password-change.js"; +import "./user-admin-password-reset.js"; export default class UserAdminGrid extends LitElement { @@ -119,21 +123,13 @@ export default class UserAdminGrid extends LitElement { render: () => html ` ` }, }; } - // TODO to remove when BUG 2 fixed - onUserCreate(e) { - const user = e.detail.value; - if (UtilsNew.isNotEmpty(user)) { - this.users.push(user); - this.renderTable(); - } - } renderTable() { if (this.users?.length > 0) { this.renderLocalTable(); @@ -247,12 +243,32 @@ export default class UserAdminGrid extends LitElement { async onActionClick(e, value, row) { const action = e.currentTarget.dataset.action; switch (action) { + /* case "edit": this.userId = row.id; this.requestUpdate(); await this.updateComplete; ModalUtils.show(`${this._prefix}UpdateModal`); break; + */ + case "edit-details": + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}UpdateDetailsModal`); + break; + case "change-password": + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}ChangePasswordModal`); + break; + case "reset-password": + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(`${this._prefix}ResetPasswordModal`); + break; case "delete": this.userId = row.id; this.requestUpdate(); @@ -298,20 +314,61 @@ export default class UserAdminGrid extends LitElement { id: "actions", title: "Actions", field: "actions", - formatter: () => ` -
+ formatter: (value, row) => ` + + + + `, events: { - "click button": (e, value, row) => this.onActionClick(e, value, row), + "click ul>li>a": (e, value, row) => this.onActionClick(e, value, row), }, }); } @@ -320,6 +377,7 @@ export default class UserAdminGrid extends LitElement { return this._columns; } + /* renderModalUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateModal`, { display: { @@ -335,13 +393,81 @@ export default class UserAdminGrid extends LitElement { .organization="${this.organization}" .studyId="${this.studyId}" .active="${active}" - .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" + .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "top"}}" .opencgaSession="${this.opencgaSession}"> `; }, }); } + */ + + renderModalDetailsUpdate() { + return ModalUtils.create(this, `${this._prefix}UpdateDetailsModal`, { + display: { + modalTitle: `Update Details: User ${this.userId} in organization ${this.organization.id}`, + modalDraggable: true, + modalCyDataName: "modal-details-update", + modalSize: "modal-lg" + }, + render: active => { + debugger + return html` + + + `; + }, + }); + } + + renderModalPasswordUpdate() { + return ModalUtils.create(this, `${this._prefix}ChangePasswordModal`, { + display: { + modalTitle: `Change Password: User ${this.userId} in organization ${this.organization.id}`, + modalDraggable: true, + modalCyDataName: "modal-password-change", + modalSize: "modal-lg" + }, + render: active => { + return html` + + + `; + }, + }); + } + + renderModalPasswordReset() { + return ModalUtils.create(this, `${this._prefix}ResetPasswordModal`, { + display: { + modalTitle: `Reset Password: User ${this.userId} in organization ${this.organization.id}`, + modalDraggable: true, + modalCyDataName: "modal-password-reset", + modalSize: "modal-lg" + }, + render: active => { + return html` + + + `; + }, + }); + } renderModalDelete() { return ModalUtils.create(this, `${this._prefix}DeleteModal`, { @@ -371,8 +497,7 @@ export default class UserAdminGrid extends LitElement { .opencgaSession="${this.opencgaSession}" .settings="${this.toolbarSetting}" .config="${this.toolbarConfig}" - @actionClick="${e => this.onActionClick(e)}" - @userCreate="${e => this.onUserCreate(e)}"> + @actionClick="${e => this.onActionClick(e)}"> `; } @@ -386,10 +511,17 @@ export default class UserAdminGrid extends LitElement {
- - ${this.renderModalDelete()} - ${this.renderModalUpdate()} + + + ${this.renderModalDetailsUpdate()} + + ${this.renderModalPasswordUpdate()} + + ${this.renderModalPasswordReset()} + + ${this.renderModalDelete()} + `; } From 02936c4f3afeede6de56dea303f3f2418373966e Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 17:22:47 +0200 Subject: [PATCH 023/177] core - WiP Update Javascript clients from TASK-6013, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/api/Admin.js | 3 ++- src/core/clients/opencga/api/Alignment.js | 2 +- .../clients/opencga/api/ClinicalAnalysis.js | 2 +- src/core/clients/opencga/api/Cohort.js | 2 +- src/core/clients/opencga/api/DiseasePanel.js | 2 +- src/core/clients/opencga/api/Family.js | 2 +- src/core/clients/opencga/api/File.js | 2 +- src/core/clients/opencga/api/GA4GH.js | 2 +- src/core/clients/opencga/api/Individual.js | 2 +- src/core/clients/opencga/api/Job.js | 2 +- src/core/clients/opencga/api/Meta.js | 2 +- src/core/clients/opencga/api/Organization.js | 2 +- src/core/clients/opencga/api/Project.js | 2 +- src/core/clients/opencga/api/Sample.js | 2 +- src/core/clients/opencga/api/Study.js | 2 +- src/core/clients/opencga/api/User.js | 20 +------------------ src/core/clients/opencga/api/Variant.js | 2 +- .../clients/opencga/api/VariantOperation.js | 2 +- 18 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/core/clients/opencga/api/Admin.js b/src/core/clients/opencga/api/Admin.js index 7fcab0384..a17bf1209 100644 --- a/src/core/clients/opencga/api/Admin.js +++ b/src/core/clients/opencga/api/Admin.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -107,6 +107,7 @@ export default class Admin extends OpenCGAParentClass { * value is false. * @param {String} [params.organization] - Organization id. * @param {String} [params.user] - User ID. + * @param {String} [params.account] - Account type [GUEST, FULL, ADMINISTRATOR]. * @param {String} [params.authenticationId] - Authentication origin ID. * @returns {Promise} Promise object in the form of RestResponse instance. */ diff --git a/src/core/clients/opencga/api/Alignment.js b/src/core/clients/opencga/api/Alignment.js index 1ec703a5d..3b0cf840b 100644 --- a/src/core/clients/opencga/api/Alignment.js +++ b/src/core/clients/opencga/api/Alignment.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/ClinicalAnalysis.js b/src/core/clients/opencga/api/ClinicalAnalysis.js index e445a6139..3a2d4044b 100644 --- a/src/core/clients/opencga/api/ClinicalAnalysis.js +++ b/src/core/clients/opencga/api/ClinicalAnalysis.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Cohort.js b/src/core/clients/opencga/api/Cohort.js index 6f9ac1e3c..e8c016fe8 100644 --- a/src/core/clients/opencga/api/Cohort.js +++ b/src/core/clients/opencga/api/Cohort.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/DiseasePanel.js b/src/core/clients/opencga/api/DiseasePanel.js index 4343bc420..f9401a609 100644 --- a/src/core/clients/opencga/api/DiseasePanel.js +++ b/src/core/clients/opencga/api/DiseasePanel.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Family.js b/src/core/clients/opencga/api/Family.js index 245c24abe..1568ca19a 100644 --- a/src/core/clients/opencga/api/Family.js +++ b/src/core/clients/opencga/api/Family.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/File.js b/src/core/clients/opencga/api/File.js index 0a085be81..3aaf33d45 100644 --- a/src/core/clients/opencga/api/File.js +++ b/src/core/clients/opencga/api/File.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/GA4GH.js b/src/core/clients/opencga/api/GA4GH.js index 1bef974d3..50c5f4569 100644 --- a/src/core/clients/opencga/api/GA4GH.js +++ b/src/core/clients/opencga/api/GA4GH.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Individual.js b/src/core/clients/opencga/api/Individual.js index ce94d5060..81bc55cc8 100644 --- a/src/core/clients/opencga/api/Individual.js +++ b/src/core/clients/opencga/api/Individual.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Job.js b/src/core/clients/opencga/api/Job.js index 1d2aa95b0..a7faefab0 100644 --- a/src/core/clients/opencga/api/Job.js +++ b/src/core/clients/opencga/api/Job.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Meta.js b/src/core/clients/opencga/api/Meta.js index 6d9869452..5f46d6668 100644 --- a/src/core/clients/opencga/api/Meta.js +++ b/src/core/clients/opencga/api/Meta.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Organization.js b/src/core/clients/opencga/api/Organization.js index a429ccf68..6e96cfe29 100644 --- a/src/core/clients/opencga/api/Organization.js +++ b/src/core/clients/opencga/api/Organization.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Project.js b/src/core/clients/opencga/api/Project.js index e58af550d..8728cf804 100644 --- a/src/core/clients/opencga/api/Project.js +++ b/src/core/clients/opencga/api/Project.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Sample.js b/src/core/clients/opencga/api/Sample.js index f4ae4e296..5687de66b 100644 --- a/src/core/clients/opencga/api/Sample.js +++ b/src/core/clients/opencga/api/Sample.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Study.js b/src/core/clients/opencga/api/Study.js index d13f1d427..1d8a7d978 100644 --- a/src/core/clients/opencga/api/Study.js +++ b/src/core/clients/opencga/api/Study.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/User.js b/src/core/clients/opencga/api/User.js index e478e03db..1b72aa833 100644 --- a/src/core/clients/opencga/api/User.js +++ b/src/core/clients/opencga/api/User.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -64,24 +64,6 @@ export default class User extends OpenCGAParentClass { return this._post("users", null, null, null, "password", data); } - /** User search method - * @param {Object} [params] - The Object containing the following optional parameters: - * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. - * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. - * @param {Number} [params.limit] - Number of results to be returned. - * @param {Number} [params.skip] - Number of results to skip. - * @param {Boolean} [params.count = "false"] - Get the total number of results matching the query. Deactivated by default. The default - * value is false. - * @param {String} [params.organization] - Organization id. - * @param {String} [params.id] - Comma separated list user IDs up to a maximum of 100. Also admits basic regular expressions using the - * operator '~', i.e. '~{perl-regex}' e.g. '~value' for case sensitive, '~/value/i' for case insensitive search. - * @param {String} [params.authenticationId] - Authentication origin ID. - * @returns {Promise} Promise object in the form of RestResponse instance. - */ - search(params) { - return this._get("users", null, null, null, "search", params); - } - /** Return the user information including its projects and studies * @param {String} users - Comma separated list of user IDs. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Variant.js b/src/core/clients/opencga/api/Variant.js index c341d110c..60baa0f5a 100644 --- a/src/core/clients/opencga/api/Variant.js +++ b/src/core/clients/opencga/api/Variant.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/VariantOperation.js b/src/core/clients/opencga/api/VariantOperation.js index a178fbbdd..bfd6f99aa 100644 --- a/src/core/clients/opencga/api/VariantOperation.js +++ b/src/core/clients/opencga/api/VariantOperation.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-04-10 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. From 250726c9448f2af4b39027cf9f4e46e1be2e1f49 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 17:41:07 +0200 Subject: [PATCH 024/177] core - WiP Update Javascript clients from develop, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/api/Admin.js | 3 +-- src/core/clients/opencga/api/Alignment.js | 2 +- .../clients/opencga/api/ClinicalAnalysis.js | 2 +- src/core/clients/opencga/api/Cohort.js | 2 +- src/core/clients/opencga/api/DiseasePanel.js | 2 +- src/core/clients/opencga/api/Family.js | 2 +- src/core/clients/opencga/api/File.js | 2 +- src/core/clients/opencga/api/GA4GH.js | 2 +- src/core/clients/opencga/api/Individual.js | 2 +- src/core/clients/opencga/api/Job.js | 2 +- src/core/clients/opencga/api/Meta.js | 2 +- src/core/clients/opencga/api/Organization.js | 2 +- src/core/clients/opencga/api/Project.js | 2 +- src/core/clients/opencga/api/Sample.js | 2 +- src/core/clients/opencga/api/Study.js | 2 +- src/core/clients/opencga/api/User.js | 20 ++++++++++++++++++- src/core/clients/opencga/api/Variant.js | 2 +- .../clients/opencga/api/VariantOperation.js | 2 +- 18 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/core/clients/opencga/api/Admin.js b/src/core/clients/opencga/api/Admin.js index a17bf1209..7fcab0384 100644 --- a/src/core/clients/opencga/api/Admin.js +++ b/src/core/clients/opencga/api/Admin.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -107,7 +107,6 @@ export default class Admin extends OpenCGAParentClass { * value is false. * @param {String} [params.organization] - Organization id. * @param {String} [params.user] - User ID. - * @param {String} [params.account] - Account type [GUEST, FULL, ADMINISTRATOR]. * @param {String} [params.authenticationId] - Authentication origin ID. * @returns {Promise} Promise object in the form of RestResponse instance. */ diff --git a/src/core/clients/opencga/api/Alignment.js b/src/core/clients/opencga/api/Alignment.js index 3b0cf840b..1ec703a5d 100644 --- a/src/core/clients/opencga/api/Alignment.js +++ b/src/core/clients/opencga/api/Alignment.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/ClinicalAnalysis.js b/src/core/clients/opencga/api/ClinicalAnalysis.js index 3a2d4044b..e445a6139 100644 --- a/src/core/clients/opencga/api/ClinicalAnalysis.js +++ b/src/core/clients/opencga/api/ClinicalAnalysis.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Cohort.js b/src/core/clients/opencga/api/Cohort.js index e8c016fe8..6f9ac1e3c 100644 --- a/src/core/clients/opencga/api/Cohort.js +++ b/src/core/clients/opencga/api/Cohort.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/DiseasePanel.js b/src/core/clients/opencga/api/DiseasePanel.js index f9401a609..4343bc420 100644 --- a/src/core/clients/opencga/api/DiseasePanel.js +++ b/src/core/clients/opencga/api/DiseasePanel.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Family.js b/src/core/clients/opencga/api/Family.js index 1568ca19a..245c24abe 100644 --- a/src/core/clients/opencga/api/Family.js +++ b/src/core/clients/opencga/api/Family.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/File.js b/src/core/clients/opencga/api/File.js index 3aaf33d45..0a085be81 100644 --- a/src/core/clients/opencga/api/File.js +++ b/src/core/clients/opencga/api/File.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/GA4GH.js b/src/core/clients/opencga/api/GA4GH.js index 50c5f4569..1bef974d3 100644 --- a/src/core/clients/opencga/api/GA4GH.js +++ b/src/core/clients/opencga/api/GA4GH.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Individual.js b/src/core/clients/opencga/api/Individual.js index 81bc55cc8..ce94d5060 100644 --- a/src/core/clients/opencga/api/Individual.js +++ b/src/core/clients/opencga/api/Individual.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Job.js b/src/core/clients/opencga/api/Job.js index a7faefab0..1d2aa95b0 100644 --- a/src/core/clients/opencga/api/Job.js +++ b/src/core/clients/opencga/api/Job.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Meta.js b/src/core/clients/opencga/api/Meta.js index 5f46d6668..6d9869452 100644 --- a/src/core/clients/opencga/api/Meta.js +++ b/src/core/clients/opencga/api/Meta.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Organization.js b/src/core/clients/opencga/api/Organization.js index 6e96cfe29..a429ccf68 100644 --- a/src/core/clients/opencga/api/Organization.js +++ b/src/core/clients/opencga/api/Organization.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Project.js b/src/core/clients/opencga/api/Project.js index 8728cf804..e58af550d 100644 --- a/src/core/clients/opencga/api/Project.js +++ b/src/core/clients/opencga/api/Project.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Sample.js b/src/core/clients/opencga/api/Sample.js index 5687de66b..f4ae4e296 100644 --- a/src/core/clients/opencga/api/Sample.js +++ b/src/core/clients/opencga/api/Sample.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Study.js b/src/core/clients/opencga/api/Study.js index 1d8a7d978..d13f1d427 100644 --- a/src/core/clients/opencga/api/Study.js +++ b/src/core/clients/opencga/api/Study.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/User.js b/src/core/clients/opencga/api/User.js index 1b72aa833..e478e03db 100644 --- a/src/core/clients/opencga/api/User.js +++ b/src/core/clients/opencga/api/User.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -64,6 +64,24 @@ export default class User extends OpenCGAParentClass { return this._post("users", null, null, null, "password", data); } + /** User search method + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Number} [params.limit] - Number of results to be returned. + * @param {Number} [params.skip] - Number of results to skip. + * @param {Boolean} [params.count = "false"] - Get the total number of results matching the query. Deactivated by default. The default + * value is false. + * @param {String} [params.organization] - Organization id. + * @param {String} [params.id] - Comma separated list user IDs up to a maximum of 100. Also admits basic regular expressions using the + * operator '~', i.e. '~{perl-regex}' e.g. '~value' for case sensitive, '~/value/i' for case insensitive search. + * @param {String} [params.authenticationId] - Authentication origin ID. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + search(params) { + return this._get("users", null, null, null, "search", params); + } + /** Return the user information including its projects and studies * @param {String} users - Comma separated list of user IDs. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Variant.js b/src/core/clients/opencga/api/Variant.js index 60baa0f5a..c341d110c 100644 --- a/src/core/clients/opencga/api/Variant.js +++ b/src/core/clients/opencga/api/Variant.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/VariantOperation.js b/src/core/clients/opencga/api/VariantOperation.js index bfd6f99aa..a178fbbdd 100644 --- a/src/core/clients/opencga/api/VariantOperation.js +++ b/src/core/clients/opencga/api/VariantOperation.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-10 + * Autogenerated on: 2024-04-29 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. From 5478bf71197d13c8cc156c7a6eb538b473a6e3ad Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 19:35:24 +0200 Subject: [PATCH 025/177] core - WiP Add authentication method and expiration date to the grid, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 0d5a061a3..922851f53 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -175,6 +175,7 @@ export default class UserAdminGrid extends LitElement { .search(this.filters) .then(response => { result = response; + debugger return response; }) .then(() => { @@ -297,11 +298,22 @@ export default class UserAdminGrid extends LitElement { field: "email", visible: this.gridCommons.isColumnVisible("individualId") }, + { + title: "Authentication", + field: "account.authentication.id", + visible: this.gridCommons.isColumnVisible("account.authentication.id") + }, { title: "Creation Date", field: "account.creationDate", formatter: CatalogGridFormatter.dateFormatter, - visible: this.gridCommons.isColumnVisible("creationDate") + visible: this.gridCommons.isColumnVisible("account.creationDate") + }, + { + title: "Expiration Date", + field: "account.expirationDate", + formatter: CatalogGridFormatter.dateFormatter, + visible: this.gridCommons.isColumnVisible("account.expirationDate") }, ]; From 5c39e951bb400cd5b08fda7b57973b9dcaac06e9 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 23 May 2024 19:38:33 +0200 Subject: [PATCH 026/177] wp - WiP Add user admin details update with: name, email, expiration date, quota, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-details-update.js | 282 ++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 src/webcomponents/organization/admin/user-admin-details-update.js diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js new file mode 100644 index 000000000..8712fcdaa --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -0,0 +1,282 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import FormUtils from "../../commons/forms/form-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; + +export default class UserAdminDetailsUpdate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + userId: { + type: String + }, + organization: { + type: Object, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.user = {}; // Original object + this._user = {}; // Updated object + this.userId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initOriginalObjects() { + this._user = UtilsNew.objectClone(this.user); + this.updatedFields = {}; + } + + update(changedProperties) { + if (changedProperties.has("userId")) { + this.userIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + userIdObserver() { + if (this.userId && this.opencgaSession) { + const params = { + organization: this.organization.id, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.users() + .info(this.userId, params) + .then(response => { + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userInfo", this.user, {}, error); + this.#setLoading(false); + }); + } + } + + onFieldChange(e) { + this.updatedFields = e.detail?.data || {}; + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Discard changes", + message: "Are you sure you want to discard the changes made?", + ok: () => { + this.#initOriginalObjects(); + this.requestUpdate(); + // We need to dispatch a component clear event + LitUtils.dispatchCustomEvent(this, "userClear", null, { + user: this._user, + }); + }, + }); + } + + onSubmit() { + const data = { + includeResult: true, + }; + let error; + this.#setLoading(true); + // Fixme: waiting for task: + // https://app.clickup.com/t/36631768/TASK-6013 + // Check endpoint when released. +/* + this.opencgaSession.opencgaClient.organization() + .updateUser(this.userId, data, this.updatedFields) + .then(response => { + this._user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `User Update`, + message: `User ${this.userId} updated correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "updateUser", this._user, {}, error); + this.#setLoading(false); + }); +*/ + } + + render() { + return html ` + + + `; + } + + getDefaultConfig() { + return { + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig, + sections: [ + { + title: "Details", + display: { + titleVisible: false, + }, + elements: [ + { + title: "User Name", + field: "name", + type: "input-text", + display: { + helpMessage: "Edit the user name...", + }, + }, + { + title: "User email", + field: "email", + type: "input-text", + display: { + helpMessage: "Edit the user email...", + }, + }, + { + title: "Enable user", + field: "enabled", + type: "toggle-switch", + display: { + disabled: true, + helpMessage: "Coming soon: Enable/Disable a user in an organization", + }, + }, + + ], + }, + { + title: "Account", + display: { + titleVisible: false, + }, + elements: [ + { + title: "Expiration Date", + field: "account.expirationDate", + type: "input-date", + display: { + render: date => moment(date, "YYYYMMDDHHmmss").format("DD/MM/YYYY") + }, + }, + ], + }, + { + title: "Quota", + display: { + titleVisible: false, + }, + elements: [ + { + title: "CPU Usage", + field: "quota.cpuUsage", + type: "input-num", + }, + { + title: "Disk Usage", + field: "quota.diskUsage", + type: "input-num", + }, + { + title: "Max CPU", + field: "quota.maxCpu", + type: "input-num", + }, + { + title: "Max Disk", + field: "quota.maxDisk", + type: "input-num", + }, + ], + }, + + ], + }; + } + +} + +customElements.define("user-admin-details-update", UserAdminDetailsUpdate); From a72ba6b6d4214f081e1794b47c68a2218421ffb6 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 10:18:46 +0200 Subject: [PATCH 027/177] core - Updated JS Clientes, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/api/Admin.js | 2 +- src/core/clients/opencga/api/Alignment.js | 2 +- .../clients/opencga/api/ClinicalAnalysis.js | 2 +- src/core/clients/opencga/api/Cohort.js | 2 +- src/core/clients/opencga/api/DiseasePanel.js | 2 +- src/core/clients/opencga/api/Family.js | 2 +- src/core/clients/opencga/api/File.js | 2 +- src/core/clients/opencga/api/GA4GH.js | 2 +- src/core/clients/opencga/api/Individual.js | 2 +- src/core/clients/opencga/api/Job.js | 2 +- src/core/clients/opencga/api/Meta.js | 2 +- src/core/clients/opencga/api/Organization.js | 32 ++++++++++++++++++- src/core/clients/opencga/api/Project.js | 2 +- src/core/clients/opencga/api/Sample.js | 2 +- src/core/clients/opencga/api/Study.js | 2 +- src/core/clients/opencga/api/User.js | 2 +- src/core/clients/opencga/api/Variant.js | 2 +- .../clients/opencga/api/VariantOperation.js | 2 +- 18 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/core/clients/opencga/api/Admin.js b/src/core/clients/opencga/api/Admin.js index 7fcab0384..6d42c5646 100644 --- a/src/core/clients/opencga/api/Admin.js +++ b/src/core/clients/opencga/api/Admin.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Alignment.js b/src/core/clients/opencga/api/Alignment.js index 1ec703a5d..0c5d7cfeb 100644 --- a/src/core/clients/opencga/api/Alignment.js +++ b/src/core/clients/opencga/api/Alignment.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/ClinicalAnalysis.js b/src/core/clients/opencga/api/ClinicalAnalysis.js index e445a6139..25c6cd4c4 100644 --- a/src/core/clients/opencga/api/ClinicalAnalysis.js +++ b/src/core/clients/opencga/api/ClinicalAnalysis.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Cohort.js b/src/core/clients/opencga/api/Cohort.js index 6f9ac1e3c..1d9d146d8 100644 --- a/src/core/clients/opencga/api/Cohort.js +++ b/src/core/clients/opencga/api/Cohort.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/DiseasePanel.js b/src/core/clients/opencga/api/DiseasePanel.js index 4343bc420..b034b4a06 100644 --- a/src/core/clients/opencga/api/DiseasePanel.js +++ b/src/core/clients/opencga/api/DiseasePanel.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Family.js b/src/core/clients/opencga/api/Family.js index 245c24abe..196bb8147 100644 --- a/src/core/clients/opencga/api/Family.js +++ b/src/core/clients/opencga/api/Family.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/File.js b/src/core/clients/opencga/api/File.js index 0a085be81..2c4acdbd2 100644 --- a/src/core/clients/opencga/api/File.js +++ b/src/core/clients/opencga/api/File.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/GA4GH.js b/src/core/clients/opencga/api/GA4GH.js index 1bef974d3..f4d6eef05 100644 --- a/src/core/clients/opencga/api/GA4GH.js +++ b/src/core/clients/opencga/api/GA4GH.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Individual.js b/src/core/clients/opencga/api/Individual.js index ce94d5060..1744c4611 100644 --- a/src/core/clients/opencga/api/Individual.js +++ b/src/core/clients/opencga/api/Individual.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Job.js b/src/core/clients/opencga/api/Job.js index 1d2aa95b0..a6ec63d51 100644 --- a/src/core/clients/opencga/api/Job.js +++ b/src/core/clients/opencga/api/Job.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Meta.js b/src/core/clients/opencga/api/Meta.js index 6d9869452..599d48eca 100644 --- a/src/core/clients/opencga/api/Meta.js +++ b/src/core/clients/opencga/api/Meta.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Organization.js b/src/core/clients/opencga/api/Organization.js index a429ccf68..176753b98 100644 --- a/src/core/clients/opencga/api/Organization.js +++ b/src/core/clients/opencga/api/Organization.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -103,6 +103,36 @@ export default class Organization extends OpenCGAParentClass { return this._post("organizations", null, "notes", id, "update", data, params); } + /** Update the user status + * @param {String} user - User ID. + * @param {Object} data - JSON containing the User fields to be updated. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {String} [params.organization] - Organization id. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + userUpdateStatus(user, data, params) { + return this._post("organizations/user", user, "status", null, "update", data, params); + } + + /** Update the user information + * @param {String} user - User ID. + * @param {Object} data - JSON containing the User fields to be updated. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {String} [params.organization] - Organization id. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + updateUser(user, data, params) { + return this._post("organizations", null, "user", user, "update", data, params); + } + /** Return the organization information * @param {String} organization - Organization id. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Project.js b/src/core/clients/opencga/api/Project.js index e58af550d..1aa374428 100644 --- a/src/core/clients/opencga/api/Project.js +++ b/src/core/clients/opencga/api/Project.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Sample.js b/src/core/clients/opencga/api/Sample.js index f4ae4e296..2150b03db 100644 --- a/src/core/clients/opencga/api/Sample.js +++ b/src/core/clients/opencga/api/Sample.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Study.js b/src/core/clients/opencga/api/Study.js index d13f1d427..a144ce485 100644 --- a/src/core/clients/opencga/api/Study.js +++ b/src/core/clients/opencga/api/Study.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/User.js b/src/core/clients/opencga/api/User.js index e478e03db..b4cd42455 100644 --- a/src/core/clients/opencga/api/User.js +++ b/src/core/clients/opencga/api/User.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Variant.js b/src/core/clients/opencga/api/Variant.js index c341d110c..7d165e13c 100644 --- a/src/core/clients/opencga/api/Variant.js +++ b/src/core/clients/opencga/api/Variant.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/VariantOperation.js b/src/core/clients/opencga/api/VariantOperation.js index a178fbbdd..8a616734c 100644 --- a/src/core/clients/opencga/api/VariantOperation.js +++ b/src/core/clients/opencga/api/VariantOperation.js @@ -12,7 +12,7 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-04-29 + * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. From 52def92d8aea97f5d180bfb905349c3c175fde9b Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 12:35:13 +0200 Subject: [PATCH 028/177] wc - Add new endpoint for user details update, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-details-update.js | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index 8712fcdaa..40995cd4a 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -56,7 +56,15 @@ export default class UserAdminDetailsUpdate extends LitElement { this.userId = ""; this.displayConfig = {}; this.updatedFields = {}; - + // Some of the user fields modeled in the form cannot be updated + this.updateCustomisation = [ + params => { + if (params.account?.expirationDate) { + // eslint-disable-next-line no-param-reassign + params.account = {expirationDate: params.account.expirationDate}; + } + }, + ]; this._config = this.getDefaultConfig(); } @@ -121,8 +129,17 @@ export default class UserAdminDetailsUpdate extends LitElement { } } - onFieldChange(e) { - this.updatedFields = e.detail?.data || {}; + onFieldChange(e, field) { + const param = field || e.detail.param; + this.updatedFields = FormUtils.getUpdatedFields( + this.user, + this.updatedFields, + param, + e.detail.value, + e.detail.action); + + debugger + // this.updatedFields = e.detail?.data || {}; this.requestUpdate(); } @@ -142,17 +159,19 @@ export default class UserAdminDetailsUpdate extends LitElement { } onSubmit() { - const data = { + const params = { includeResult: true, }; + + const updateParams = FormUtils.getUpdateParams(this._user, this.updatedFields, this.updateCustomisation); +debugger let error; this.#setLoading(true); // Fixme: waiting for task: // https://app.clickup.com/t/36631768/TASK-6013 - // Check endpoint when released. -/* + // PR to approve this.opencgaSession.opencgaClient.organization() - .updateUser(this.userId, data, this.updatedFields) + .updateUser(this.userId, updateParams, params) .then(response => { this._user = UtilsNew.objectClone(response.responses[0].results[0]); this.#initOriginalObjects(); @@ -166,10 +185,10 @@ export default class UserAdminDetailsUpdate extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "updateUser", this._user, {}, error); + LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); this.#setLoading(false); }); -*/ + } render() { From 22579936a488e24a3744fcc2cdbfa95540d0c31b Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 12:58:14 +0200 Subject: [PATCH 029/177] wc - Delete quota tab in user details update. Further discussion and implementation needed, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-details-update.js | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index 40995cd4a..38189b5ba 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -263,35 +263,6 @@ debugger }, ], }, - { - title: "Quota", - display: { - titleVisible: false, - }, - elements: [ - { - title: "CPU Usage", - field: "quota.cpuUsage", - type: "input-num", - }, - { - title: "Disk Usage", - field: "quota.diskUsage", - type: "input-num", - }, - { - title: "Max CPU", - field: "quota.maxCpu", - type: "input-num", - }, - { - title: "Max Disk", - field: "quota.maxDisk", - type: "input-num", - }, - ], - }, - ], }; } From aba411f27282b72acf9833aa2fbd2244f3832165 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 15:26:43 +0200 Subject: [PATCH 030/177] wc - Refresh grid on user update, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-details-update.js | 7 +++--- .../organization/admin/user-admin-grid.js | 25 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index 38189b5ba..764a2423f 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -90,6 +90,7 @@ export default class UserAdminDetailsUpdate extends LitElement { #initOriginalObjects() { this._user = UtilsNew.objectClone(this.user); this.updatedFields = {}; + this.requestUpdate(); } update(changedProperties) { @@ -152,7 +153,7 @@ export default class UserAdminDetailsUpdate extends LitElement { this.requestUpdate(); // We need to dispatch a component clear event LitUtils.dispatchCustomEvent(this, "userClear", null, { - user: this._user, + user: this.user, }); }, }); @@ -173,7 +174,7 @@ debugger this.opencgaSession.opencgaClient.organization() .updateUser(this.userId, updateParams, params) .then(response => { - this._user = UtilsNew.objectClone(response.responses[0].results[0]); + this.user = UtilsNew.objectClone(response.responses[0].results[0]); this.#initOriginalObjects(); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `User Update`, @@ -182,7 +183,7 @@ debugger }) .catch(reason => { error = reason; - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 922851f53..7ab892380 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -26,6 +26,7 @@ import "./user-admin-update.js"; import "./user-admin-details-update.js"; import "./user-admin-password-change.js"; import "./user-admin-password-reset.js"; +import LitUtils from "../../commons/utils/lit-utils"; export default class UserAdminGrid extends LitElement { @@ -123,8 +124,9 @@ export default class UserAdminGrid extends LitElement { render: () => html ` + .displayConfig="${{mode: "page", type: "form", buttonsLayout: "top"}}" + .opencgaSession="${this.opencgaSession}" + @userCreate="${e => this.onUserEvent(e)}"> ` }, }; @@ -175,7 +177,6 @@ export default class UserAdminGrid extends LitElement { .search(this.filters) .then(response => { result = response; - debugger return response; }) .then(() => { @@ -413,6 +414,9 @@ export default class UserAdminGrid extends LitElement { }); } */ + onUserEvent() { + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); + } renderModalDetailsUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateDetailsModal`, { @@ -423,14 +427,13 @@ export default class UserAdminGrid extends LitElement { modalSize: "modal-lg" }, render: active => { - debugger return html` + .opencgaSession="${this.opencgaSession}" + @userUpdate="${e => this.onUserEvent(e)}"> `; }, @@ -452,7 +455,8 @@ export default class UserAdminGrid extends LitElement { .organization="${this.organization}" .active="${active}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" - .opencgaSession="${this.opencgaSession}"> + .opencgaSession="${this.opencgaSession}" + @userUpdate="${e => this.onUserEvent(e)}"> `; }, @@ -468,13 +472,15 @@ export default class UserAdminGrid extends LitElement { modalSize: "modal-lg" }, render: active => { + debugger return html` + .opencgaSession="${this.opencgaSession}" + @userUpdate="${e => this.onUserEvent(e)}"> `; }, @@ -495,7 +501,8 @@ export default class UserAdminGrid extends LitElement { .studyId="${this.studyId}" .active="${active}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" - .opencgaSession="${this.opencgaSession}"> + .opencgaSession="${this.opencgaSession}" + @userUpdate="${e => this.onUserEvent(e)}"> `, }); From c722ac561cd8258d5c0600d537199b931799f55a Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 16:43:16 +0200 Subject: [PATCH 031/177] wc - WiP Reset password action for organization admins/owners, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/user/user-password-reset.js | 187 +++++++++++++----- 1 file changed, 134 insertions(+), 53 deletions(-) diff --git a/src/webcomponents/user/user-password-reset.js b/src/webcomponents/user/user-password-reset.js index 3773f0c89..91a2d3b78 100644 --- a/src/webcomponents/user/user-password-reset.js +++ b/src/webcomponents/user/user-password-reset.js @@ -1,6 +1,7 @@ import {LitElement, html} from "lit"; import LitUtils from "../commons/utils/lit-utils.js"; import NotificationUtils from "../commons/utils/notification-utils.js"; +import UtilsNew from "../../core/utils-new.js"; export default class UserPasswordReset extends LitElement { @@ -16,83 +17,163 @@ export default class UserPasswordReset extends LitElement { static get properties() { return { + user: { + type: Object, + }, opencgaSession: { type: Object }, + displayConfig: { + type: Object + }, }; } #init() { - this.hasEmptyUser = false; + this._user = {}; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + titleStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", + defaultLayout: "horizontal", + buttonOkText: "Reset password", + }; + this._config = this.getDefaultConfig(); } - redirect(to) { - LitUtils.dispatchCustomEvent(this, "redirect", null, {hash: to}); + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); } - onSubmit(e) { - e.preventDefault(); - const user = (this.querySelector("#user").value || "").trim(); + #initOriginalObjects() { + this._config = this.getDefaultConfig(); + this.requestUpdate(); + } - // Check for empty user ID - this.hasEmptyUser = user.length === 0; - if (this.hasEmptyUser) { - return this.requestUpdate(); + update(changedProperties) { + if (changedProperties.has("displayConfig") || changedProperties.has("user")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + this._config = this.getDefaultConfig(); } + super.update(changedProperties); + } - // Reset password mockup - // TODO: call openCGA to the correct endpoint - Promise.resolve().then(() => { - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { - "message": "We have just send you an email with the new password.", - }); + /* + onSubmit(e) { + e.preventDefault(); + const user = (this.querySelector("#user").value || "").trim(); - this.querySelector("#user").value = ""; - this.hasEmptyUser = false; - this.requestUpdate(); - }); - } + // Check for empty user ID + this.hasEmptyUser = user.length === 0; + if (this.hasEmptyUser) { + return this.requestUpdate(); + } - // Handle keyup event --> check for enter key to submit the form - onKeyUp(e) { - if (e.key === "Enter") { - return this.onSubmit(e); + // Reset password mockup + // TODO: call openCGA to the correct endpoint + Promise.resolve().then(() => { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + "message": "We have just send you an email with the new password.", + }); + + this.querySelector("#user").value = ""; + this.hasEmptyUser = false; + this.requestUpdate(); + }); } + */ + + onSubmit() { + // QUESTION: + // - TASK-1667, includeResult + // - JS client do not have argument for params, only user + const data = { + includeResult: true, + }; + let error; + this.#setLoading(true); + // Reset password + // Fixme: waiting for task: + // https://app.clickup.com/t/36631768/TASK-464 + // Check endpoint when released + this.opencgaSession.opencgaClient.users() + .resetPassword(this.user.id) + .then(response => { + this._user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `User Reset Password`, + message: `User ${this.userId} password reset correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); + this.#setLoading(false); + }); + } render() { + // TODO: check if opencgaSession has been provided + debugger return html` -
-
-
-
-

- Reset your password -

-
-
- Please enter your user ID and we will send you an email with your password reset link. -
-
-
- - - - -
-
- -
-
- -
+ + `; } + getDefaultConfig() { + return { + title: "Reset Password", + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + title: `Do you really want to reset ${this.user?.id}'s password?`, + elements: [ + { + type: "notification", + text: `${this.user?.id} will receive an email with a temporary password... [ TO ELABORATE ]`, + display: { + visible: true, + icon: "fas fa-exclamation-triangle", + notificationType: "error", + }, + }, + { + title: "User ID", + field: "id", + type: "input-text", + display: { + disabled: true, + } + }, + { + title: "Email", + field: "email", + type: "input-text", + display: { + disabled: true, + } + }, + ], + }, + ], + }; + } + + } customElements.define("user-password-reset", UserPasswordReset); From 91388a1ff48b61f3ab7790d902daa649defe578e Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 16:43:27 +0200 Subject: [PATCH 032/177] wc - WiP Reset password action for organization admins/owners, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-password-reset.js | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 src/webcomponents/organization/admin/user-admin-password-reset.js diff --git a/src/webcomponents/organization/admin/user-admin-password-reset.js b/src/webcomponents/organization/admin/user-admin-password-reset.js new file mode 100644 index 000000000..eaef0c962 --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-password-reset.js @@ -0,0 +1,190 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import "../../user/user-password-reset.js"; + +export default class UserAdminPasswordReset extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + userId: { + type: String + }, + organization: { + type: Object, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.user = {}; // Original object + this._user = {}; // Updated object + this.userId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initOriginalObjects() { + this._user = UtilsNew.objectClone(this.user); + this.updatedFields = {}; + } + + update(changedProperties) { + if (changedProperties.has("userId")) { + this.userIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + userIdObserver() { + if (this.userId && this.opencgaSession) { + const params = { + organization: this.organization.id, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.users() + .info(this.userId, params) + .then(response => { + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userInfo", this.user, {}, error); + this.#setLoading(false); + }); + } + } + + render() { + debugger + return html ` + + + `; + } + + getDefaultConfig() { + return { + title: "", + showTitle: false, + items: [ + { + id: "reset-password", + name: "Reset Password", + active: true, + render: (user, active, opencgaSession) => { + return html` + + + `; + } + }, + ], + }; + + /* + return { + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig, + sections: [ + { + title: "Credentials", + elements: [ + { + title: "Reset password hola", + type: "custom", + display: { + titleVisible: false, + render: (data, active, opencgaSession) => html` + + + `, + }, + }, + ], + }, + + ], + }; + */ + } + +} + +customElements.define("user-admin-password-reset", UserAdminPasswordReset); From d094d219d9ed5f440bf97a5fba28b82250b1fd6c Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 18:24:49 +0200 Subject: [PATCH 033/177] wc - WiP User password change, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-password-change.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-password-change.js b/src/webcomponents/organization/admin/user-admin-password-change.js index ac7265265..25fdd3fbc 100644 --- a/src/webcomponents/organization/admin/user-admin-password-change.js +++ b/src/webcomponents/organization/admin/user-admin-password-change.js @@ -40,9 +40,6 @@ export default class UserAdminPasswordChange extends LitElement { organization: { type: Object, }, - active: { - type: Boolean, - }, opencgaSession: { type: Object }, @@ -53,6 +50,7 @@ export default class UserAdminPasswordChange extends LitElement { } #init() { + this.user = {}; // Original object this._user = {}; // Updated object this.userId = ""; this.displayConfig = {}; From 7eaabdd8a67a1ebe8b902e3340ca631c936887e0 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 18:24:59 +0200 Subject: [PATCH 034/177] wc - WiP User admin create, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/user-admin-create.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webcomponents/organization/admin/user-admin-create.js b/src/webcomponents/organization/admin/user-admin-create.js index 8176fe377..401cd6e69 100644 --- a/src/webcomponents/organization/admin/user-admin-create.js +++ b/src/webcomponents/organization/admin/user-admin-create.js @@ -82,7 +82,6 @@ export default class UserAdminCreate extends LitElement { } opencgaSessionObserver() { - // Read Projects and Study to prepare the select studies menu this.#initOriginalObjects(); } @@ -114,6 +113,9 @@ export default class UserAdminCreate extends LitElement { this.user.organization = this.organization.id; let error = {}; let newUser = {}; + // CAUTION: + // - POST admin/users/create or + // - POST users/create ? this.opencgaSession.opencgaClient.users() .create(this.user) .then(response => { From 2afe2f2f0b253264a38e243829bdec125d3a647f Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 18:25:12 +0200 Subject: [PATCH 035/177] wc - WiP User admin grid, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 7ab892380..481e7f3af 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -126,7 +126,7 @@ export default class UserAdminGrid extends LitElement { .organization="${this.organization}" .displayConfig="${{mode: "page", type: "form", buttonsLayout: "top"}}" .opencgaSession="${this.opencgaSession}" - @userCreate="${e => this.onUserEvent(e)}"> + @userCreate="${e => this.renderRemoteTable(e)}"> ` }, }; @@ -414,9 +414,6 @@ export default class UserAdminGrid extends LitElement { }); } */ - onUserEvent() { - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); - } renderModalDetailsUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateDetailsModal`, { @@ -433,7 +430,7 @@ export default class UserAdminGrid extends LitElement { .organization="${this.organization}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" .opencgaSession="${this.opencgaSession}" - @userUpdate="${e => this.onUserEvent(e)}"> + @userUpdate="${e => this.renderRemoteTable(e)}"> `; }, @@ -456,7 +453,7 @@ export default class UserAdminGrid extends LitElement { .active="${active}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" .opencgaSession="${this.opencgaSession}" - @userUpdate="${e => this.onUserEvent(e)}"> + @userUpdate="${e => this.renderRemoteTable(e)}"> `; }, @@ -477,10 +474,9 @@ export default class UserAdminGrid extends LitElement { + @userUpdate="${e => this.renderRemoteTable(e)}"> `; }, @@ -502,7 +498,7 @@ export default class UserAdminGrid extends LitElement { .active="${active}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" .opencgaSession="${this.opencgaSession}" - @userUpdate="${e => this.onUserEvent(e)}"> + @userUpdate="${e => this.renderRemoteTable(e)}"> `, }); @@ -516,7 +512,7 @@ export default class UserAdminGrid extends LitElement { .opencgaSession="${this.opencgaSession}" .settings="${this.toolbarSetting}" .config="${this.toolbarConfig}" - @actionClick="${e => this.onActionClick(e)}"> + @userUpdate="${e => this.renderRemoteTable(e)}"> `; } From 15360ac6b3bc94ccd723ac909537d9a3e3e94b0b Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 18:26:41 +0200 Subject: [PATCH 036/177] wc - WiP Add user pasword change, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-update.js | 13 +++---------- src/webcomponents/user/user-password-change.js | 10 ++++++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-update.js b/src/webcomponents/organization/admin/user-admin-update.js index 97f9c7350..ebd8d6236 100644 --- a/src/webcomponents/organization/admin/user-admin-update.js +++ b/src/webcomponents/organization/admin/user-admin-update.js @@ -17,8 +17,8 @@ import {html, LitElement} from "lit"; import UtilsNew from "../../../core/utils-new.js"; import LitUtils from "../../commons/utils/lit-utils.js"; -import FormUtils from "../../commons/forms/form-utils"; -import NotificationUtils from "../../commons/utils/notification-utils"; +import FormUtils from "../../commons/forms/form-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; import "../../user/user-password-change.js"; import "../../user/user-password-reset.js"; @@ -64,13 +64,6 @@ export default class UserAdminUpdate extends LitElement { this.displayConfig = {}; this.updatedFields = {}; - this.displayConfigDefault = { - style: "margin: 10px", - defaultLayout: "horizontal", - labelAlign: "right", - labelWidth: 3, - buttonOkText: "Update", - }; this._config = this.getDefaultConfig(); } @@ -147,7 +140,7 @@ export default class UserAdminUpdate extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "studyInfo", this.study, {}, error); + LitUtils.dispatchCustomEvent(this, "userInfo", this.study, {}, error); this.#setLoading(false); }); } diff --git a/src/webcomponents/user/user-password-change.js b/src/webcomponents/user/user-password-change.js index 4e5d61908..af0140f56 100644 --- a/src/webcomponents/user/user-password-change.js +++ b/src/webcomponents/user/user-password-change.js @@ -1,8 +1,8 @@ import {LitElement, html} from "lit"; -import UtilsNew from "../../core/utils-new.js"; import NotificationUtils from "../commons/utils/notification-utils.js"; import "../commons/forms/data-form.js"; import LitUtils from "../commons/utils/lit-utils"; +import UtilsNew from "../../core/utils-new"; export default class UserPasswordChange extends LitElement { @@ -78,18 +78,20 @@ export default class UserPasswordChange extends LitElement { newPassword: this._password.newPassword, organizationId: this.organizationId, }; + let error; this.#setLoading(true); - debugger this.opencgaSession.opencgaClient.users() .password(params) .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { message: "Your password has been changed", }); + LitUtils.dispatchCustomEvent(this, "userUpdate"); this.#initOriginalObjects(); }) - .catch(response => { - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, response); + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { this.#setLoading(false); From 5f53ac319c2d55e04eb6dccbb99bab19eca1b436 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 24 May 2024 20:22:28 +0200 Subject: [PATCH 037/177] wc - WiP Improve performance, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 84 +++++++------------ 1 file changed, 30 insertions(+), 54 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 481e7f3af..d8a094aa5 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -72,6 +72,19 @@ export default class UserAdminGrid extends LitElement { this.gridId = this._prefix + this.COMPONENT_ID; this.active = true; this._config = this.getDefaultConfig(); + this.action = ""; + this._renderModal = { + "edit-details": () => this.renderModalDetailsUpdate(), + "change-password": () => this.renderModalPasswordUpdate(), + "reset-password": () => this.renderModalPasswordReset(), + "delete": () => this.renderModalDelete(), + }; + this._showModal = { + "edit-details": () => ModalUtils.show(`${this._prefix}UpdateDetailsModal`), + "change-password": () => ModalUtils.show(`${this._prefix}ChangePasswordModal`), + "reset-password": () => ModalUtils.show(`${this._prefix}ResetPasswordModal`), + "delete": () => ModalUtils.show(`${this._prefix}DeleteModal`), + }; } update(changedProperties) { @@ -243,45 +256,17 @@ export default class UserAdminGrid extends LitElement { } async onActionClick(e, value, row) { - const action = e.currentTarget.dataset.action; - switch (action) { - /* - case "edit": - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - ModalUtils.show(`${this._prefix}UpdateModal`); - break; - */ - case "edit-details": - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - ModalUtils.show(`${this._prefix}UpdateDetailsModal`); - break; - case "change-password": - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - ModalUtils.show(`${this._prefix}ChangePasswordModal`); - break; - case "reset-password": - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - ModalUtils.show(`${this._prefix}ResetPasswordModal`); - break; - case "delete": - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - ModalUtils.show(`${this._prefix}DeleteModal`); - break; - default: - break; - } + this.action = e.currentTarget.dataset.action; + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + this._showModal[this.action](); } + onUserUpdate(e, id) { + ModalUtils.close(id); + this.renderRemoteTable(); + } _getDefaultColumns() { this._columns = [ { @@ -423,14 +408,14 @@ export default class UserAdminGrid extends LitElement { modalCyDataName: "modal-details-update", modalSize: "modal-lg" }, - render: active => { + render: () => { return html` + @userUpdate="${e => this.onUserUpdate(e, `${this._prefix}UpdateDetailsModal`)}"> `; }, @@ -445,15 +430,14 @@ export default class UserAdminGrid extends LitElement { modalCyDataName: "modal-password-change", modalSize: "modal-lg" }, - render: active => { + render: () => { return html` + @userUpdate="${e => this.onUserUpdate(e, `${this._prefix}ChangePasswordModal`)}"> `; }, @@ -468,15 +452,14 @@ export default class UserAdminGrid extends LitElement { modalCyDataName: "modal-password-reset", modalSize: "modal-lg" }, - render: active => { - debugger + render: () => { return html` + @userUpdate="${e => this.onUserUpdate(e, `${this._prefix}ResetPasswordModal`)}"> `; }, @@ -498,7 +481,7 @@ export default class UserAdminGrid extends LitElement { .active="${active}" .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" .opencgaSession="${this.opencgaSession}" - @userUpdate="${e => this.renderRemoteTable(e)}"> + @userUpdate="${e => this.onUserUpdate(e, `${this._prefix}DeleteModal`)}"> `, }); @@ -528,14 +511,7 @@ export default class UserAdminGrid extends LitElement {
- - ${this.renderModalDetailsUpdate()} - - ${this.renderModalPasswordUpdate()} - - ${this.renderModalPasswordReset()} - - ${this.renderModalDelete()} + ${this.action ? this._renderModal[this.action]() : nothing} `; } From 55ec124f33e9e433b0ca316d66b0d5a5a1926da4 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sat, 25 May 2024 08:49:46 +0200 Subject: [PATCH 038/177] wc - WiP Clean code, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 242 +++++------------- 1 file changed, 69 insertions(+), 173 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index d8a094aa5..420d92e67 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -16,17 +16,16 @@ import {LitElement, html, nothing} from "lit"; import GridCommons from "../../commons/grid-commons.js"; -import UtilsNew from "../../../core/utils-new.js"; -import ModalUtils from "../../commons/modal/modal-utils.js"; import CatalogGridFormatter from "../../commons/catalog-grid-formatter.js"; import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import ModalUtils from "../../commons/modal/modal-utils.js"; +import UtilsNew from "../../../core/utils-new.js"; import "./user-admin-create.js"; import "./user-admin-update.js"; import "./user-admin-details-update.js"; import "./user-admin-password-change.js"; import "./user-admin-password-reset.js"; -import LitUtils from "../../commons/utils/lit-utils"; export default class UserAdminGrid extends LitElement { @@ -73,20 +72,9 @@ export default class UserAdminGrid extends LitElement { this.active = true; this._config = this.getDefaultConfig(); this.action = ""; - this._renderModal = { - "edit-details": () => this.renderModalDetailsUpdate(), - "change-password": () => this.renderModalPasswordUpdate(), - "reset-password": () => this.renderModalPasswordReset(), - "delete": () => this.renderModalDelete(), - }; - this._showModal = { - "edit-details": () => ModalUtils.show(`${this._prefix}UpdateDetailsModal`), - "change-password": () => ModalUtils.show(`${this._prefix}ChangePasswordModal`), - "reset-password": () => ModalUtils.show(`${this._prefix}ResetPasswordModal`), - "delete": () => ModalUtils.show(`${this._prefix}DeleteModal`), - }; } + // --- LIFE-CYCLE METHODS update(changedProperties) { if (changedProperties.has("opencgaSession") || changedProperties.has("toolId") || @@ -99,14 +87,10 @@ export default class UserAdminGrid extends LitElement { updated(changedProperties) { if (changedProperties.size > 0 && this.active) { - this.renderTable(); + this.renderRemoteTable(); } } - studyIdPropertyObserver() { - // 1. Get users from the study - } - propertyObserver() { // With each property change we must be updated config and create the columns again. No extra checks are needed. this._config = { @@ -143,17 +127,45 @@ export default class UserAdminGrid extends LitElement { ` }, }; - } - renderTable() { - if (this.users?.length > 0) { - this.renderLocalTable(); - } else { - this.renderRemoteTable(); - } - this.requestUpdate(); + this.permissions = { + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }; + + this.manageModal = { + "edit-details": { + label: "Edit Details", + icon: "fas fa-edit", + modalId: `${this._prefix}UpdateDetailsModal`, + render: () => this.renderModalDetailsUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + "change-password": { + label: "Change Password", + icon: "fas fa-edit", + modalId: `${this._prefix}ChangePasswordModal`, + render: () => this.renderModalPasswordUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + "reset-password": { + label: "Reset Password", + icon: "fas fa-ban", + modalId: `${this._prefix}ResetPasswordModal`, + render: () => this.renderModalPasswordReset(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + "delete": { + label: "Delete", + icon: "far fa-trash-alt ", + // modalId: `${this._prefix}DeleteModal`, + // render: () => this.renderModalPasswordReset(), + permission: "disabled", + }, + }; } + // *** PRIVATE METHODS *** renderRemoteTable() { if (this.opencgaSession?.opencgaClient && this.organization.id) { this._columns = this._getDefaultColumns(); @@ -214,59 +226,6 @@ export default class UserAdminGrid extends LitElement { } } - renderLocalTable() { - this.table = $("#" + this.gridId); - this.table.bootstrapTable("destroy"); - this.table.bootstrapTable({ - theadClasses: "table-light", - buttonsClass: "light", - columns: this._getDefaultColumns(), - sidePagination: "server", - // Josemi Note 2024-01-18: we have added the ajax function for local variants also to support executing - // async calls when getting additional data from columns extensions. - ajax: params => { - const tableOptions = $(this.table).bootstrapTable("getOptions"); - const limit = params.data.limit || tableOptions.pageSize; - const skip = params.data.offset || 0; - const rows = this.users.slice(skip, skip + limit); - - // Get data for extensions - this.gridCommons.prepareDataForExtensions(this.COMPONENT_ID, this.opencgaSession, null, rows) - .then(() => params.success(rows)) - .catch(error => params.error(error)); - }, - // Josemi Note 2024-01-18: we use this method to tell bootstrap-table how many rows we have in our data - responseHandler: response => { - return { - total: this.users.length, - rows: response, - }; - }, - iconsPrefix: GridCommons.GRID_ICONS_PREFIX, - icons: GridCommons.GRID_ICONS, - - // Set table properties, these are read from config property - uniqueId: "id", - pagination: this._config.pagination, - pageSize: this._config.pageSize, - pageList: this._config.pageList, - detailView: this._config.detailView, - loadingTemplate: () => GridCommons.loadingFormatter(), - }); - } - - async onActionClick(e, value, row) { - this.action = e.currentTarget.dataset.action; - this.userId = row.id; - this.requestUpdate(); - await this.updateComplete; - this._showModal[this.action](); - } - - onUserUpdate(e, id) { - ModalUtils.close(id); - this.renderRemoteTable(); - } _getDefaultColumns() { this._columns = [ { @@ -312,58 +271,27 @@ export default class UserAdminGrid extends LitElement { id: "actions", title: "Actions", field: "actions", - formatter: (value, row) => ` - + formatter: () => ` - `, events: { "click ul>li>a": (e, value, row) => this.onActionClick(e, value, row), @@ -375,31 +303,21 @@ export default class UserAdminGrid extends LitElement { return this._columns; } - /* - renderModalUpdate() { - return ModalUtils.create(this, `${this._prefix}UpdateModal`, { - display: { - modalTitle: `User Update: User ${this.userId} in organization ${this.organization.id}`, - modalDraggable: true, - modalCyDataName: "modal-update", - modalSize: "modal-lg" - }, - render: active => { - return html` - - - `; - }, - }); + // *** EVENTS *** + async onActionClick(e, value, row) { + this.action = e.currentTarget.dataset.action; + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(this.manageModal[this.action]["modalId"]); + } + + onUserUpdate(e, id) { + ModalUtils.close(id); + this.renderRemoteTable(); } - */ + // *** RENDER METHODS *** renderModalDetailsUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateDetailsModal`, { display: { @@ -466,27 +384,6 @@ export default class UserAdminGrid extends LitElement { }); } - renderModalDelete() { - return ModalUtils.create(this, `${this._prefix}DeleteModal`, { - display: { - modalTitle: `Group Delete: ${this.groupId}`, - modalDraggable: true, - modalCyDataName: "modal-update", - modalSize: "modal-lg" - }, - render: active => html` - - - `, - }); - } - renderToolbar() { if (this._config.showToolbar) { return html ` @@ -509,13 +406,12 @@ export default class UserAdminGrid extends LitElement {
- - - ${this.action ? this._renderModal[this.action]() : nothing} - + + ${this.action ? this.manageModal[this.action]["render"](): nothing} `; } + // *** DEFAULT CONFIG *** getDefaultConfig() { return { pagination: true, From 8ba540b6c834d49e41fa06df55fe1fd051981013 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sat, 25 May 2024 09:12:26 +0200 Subject: [PATCH 039/177] wc - WiP Tiny style code, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../clients/opencga/opencga-catalog-utils.js | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/core/clients/opencga/opencga-catalog-utils.js b/src/core/clients/opencga/opencga-catalog-utils.js index 171143d87..c3b60ea46 100644 --- a/src/core/clients/opencga/opencga-catalog-utils.js +++ b/src/core/clients/opencga/opencga-catalog-utils.js @@ -89,24 +89,38 @@ export default class OpencgaCatalogUtils { return false; } + static isOrganizationAdminOwner(organization, userLogged) { + if (!organization || !userLogged) { + console.error(`No valid parameters, study: ${organization}, user: ${userLogged}`); + return false; + } + // Check if user is Organization owner + return !!(organization.admins.includes(userLogged) || organization.owner === userLogged); + } + // Check if the user has the right the permissions in the study. static isAdmin(study, userLogged) { if (!study || !userLogged) { console.error(`No valid parameters, study: ${study}, user: ${userLogged}`); return false; } - // Check if user is the Study owner - const studyOwner = study.fqn.split("@")[0]; - if (userLogged === studyOwner) { - return true; - } else { - // Check if user is a Study admin, belongs to @admins group - const admins = study.groups.find(group => group.id === "@admins"); - if (admins.userIds.includes(userLogged)) { + // CAUTION: in organizations, label before @ is now organization name, not owner + /* + // Check if user is the Study owner + const studyOwner = study.fqn.split("@")[0]; + if (userLogged === studyOwner) { return true; + } else { + // Check if user is a Study admin, belongs to @admins group + const admins = study.groups.find(group => group.id === "@admins"); + if (admins.userIds.includes(userLogged)) { + return true; + } } - } - return false; + return false; + */ + const admins = study.groups.find(group => group.id === "@admins"); + return !!admins.userIds.includes(userLogged); } // Find study object in opencgaSession From 8560cc9049be6eadca7ff7115a82f2d5804315f8 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 27 May 2024 09:25:12 +0200 Subject: [PATCH 040/177] wc - WiP Implement status change, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-grid.js | 127 ++++++++++++- .../admin/user-admin-status-update.js | 159 ++++++++++++++++ src/webcomponents/user/user-status-update.js | 176 ++++++++++++++++++ 3 files changed, 452 insertions(+), 10 deletions(-) create mode 100644 src/webcomponents/organization/admin/user-admin-status-update.js create mode 100644 src/webcomponents/user/user-status-update.js diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 420d92e67..755927abc 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -26,6 +26,7 @@ import "./user-admin-update.js"; import "./user-admin-details-update.js"; import "./user-admin-password-change.js"; import "./user-admin-password-reset.js"; +import "./user-admin-status-update.js"; export default class UserAdminGrid extends LitElement { @@ -133,7 +134,7 @@ export default class UserAdminGrid extends LitElement { "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", }; - this.manageModal = { + this.modals = { "edit-details": { label: "Edit Details", icon: "fas fa-edit", @@ -150,11 +151,18 @@ export default class UserAdminGrid extends LitElement { }, "reset-password": { label: "Reset Password", - icon: "fas fa-ban", + icon: "fas fa-edit", modalId: `${this._prefix}ResetPasswordModal`, render: () => this.renderModalPasswordReset(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", }, + "change-status": { + label: "Change status", + icon: "fas fa-edit", + modalId: `${this._prefix}ChangeStatusModal`, + render: () => this.renderModalStatusUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, "delete": { label: "Delete", icon: "far fa-trash-alt ", @@ -185,7 +193,7 @@ export default class UserAdminGrid extends LitElement { pageSize: this._config.pageSize, pageList: this._config.pageList, paginationVAlign: "both", - formatShowingRows: this.gridCommons.formatShowingRows, + // formatShowingRows: this.gridCommons.formatShowingRows, detailView: !!this.detailFormatter, loadingTemplate: () => GridCommons.loadingFormatter(), ajax: params => { @@ -202,6 +210,7 @@ export default class UserAdminGrid extends LitElement { .search(this.filters) .then(response => { result = response; + debugger return response; }) .then(() => { @@ -260,6 +269,14 @@ export default class UserAdminGrid extends LitElement { formatter: CatalogGridFormatter.dateFormatter, visible: this.gridCommons.isColumnVisible("account.expirationDate") }, + { + title: "Status", + field: "internal.status", + formatter: (value, row) => this.statusFormatter(value, row), + events: { + "click a": e => this.onActionClick(e), + }, + }, ]; if (this._config.annotations?.length > 0) { @@ -279,17 +296,17 @@ export default class UserAdminGrid extends LitElement {
`, @@ -303,13 +320,48 @@ export default class UserAdminGrid extends LitElement { return this._columns; } + // *** COLUMN FORMATTERS *** + statusFormatter(value, row) { + debugger + const _status = this._config?.userStatus || []; + const currentStatus = value.id || value.name || "-"; // Get current status + + // Dropdown button styles and classes + const btnClassName = "d-flex justify-content-between align-items-center btn btn-light dropdown-toggle w-100"; + + return ` + + `; + } + // *** EVENTS *** async onActionClick(e, value, row) { this.action = e.currentTarget.dataset.action; this.userId = row.id; this.requestUpdate(); await this.updateComplete; - ModalUtils.show(this.manageModal[this.action]["modalId"]); + ModalUtils.show(this.modals[this.action]["modalId"]); } onUserUpdate(e, id) { @@ -384,6 +436,28 @@ export default class UserAdminGrid extends LitElement { }); } + renderModalStatusUpdate() { + return ModalUtils.create(this, `${this._prefix}ChangeStatusModal`, { + display: { + modalTitle: `User Status: User ${this.userId} in organization ${this.organization.id}`, + modalDraggable: true, + modalCyDataName: "modal-user-admin-status-update", + modalSize: "modal-lg" + }, + render: () => { + return html` + + + `; + }, + }); + } + renderToolbar() { if (this._config.showToolbar) { return html ` @@ -407,13 +481,14 @@ export default class UserAdminGrid extends LitElement {
- ${this.action ? this.manageModal[this.action]["render"](): nothing} + ${this.action ? this.modals[this.action]["render"](): nothing} `; } // *** DEFAULT CONFIG *** getDefaultConfig() { return { + // Settings pagination: true, pageSize: 10, pageList: [5, 10, 25], @@ -427,6 +502,38 @@ export default class UserAdminGrid extends LitElement { showExport: false, showSettings: false, exportTabs: ["download", "link", "code"], + // Config + userStatus: { + "READY": { // The user can login + displayLabel: "ACTIVE", // Fixme: ACTIVE | ENABLED | READY? + displayColor: "#16A83D", + description: "", + isSelectable: true, // Choice selectable by org admin/owner + isEnabled: true, // Choice visible by org admin/owner + }, + "SUSPENDED": { + displayLabel: "SUSPENDED", // User can not login into the system + displayColor: "#E17F1E", + description: "", + isSelectable: true, + isEnabled: true, + }, + "BANNED": { // User locked for more than X login attemtps. The admin/owner can enable the user back. + displayLabel: "BANNED", + displayColor: "#961EE1", + description: "", + isSelectable: false, + isEnabled: true, + }, + "DELETED": { // QUESTION: is it possible remove all permissions and login, but keep him in the system? + displayLabel: "REMOVED", + displayColor: "#E1351E", + description: "", + isSelectable: false, + isEnabled: false, + }, + }, + }; } diff --git a/src/webcomponents/organization/admin/user-admin-status-update.js b/src/webcomponents/organization/admin/user-admin-status-update.js new file mode 100644 index 000000000..2bc61261a --- /dev/null +++ b/src/webcomponents/organization/admin/user-admin-status-update.js @@ -0,0 +1,159 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import "../../user/user-status-update.js"; + +export default class UserAdminStatusUpdate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + userId: { + type: String + }, + organization: { + type: Object, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.user = {}; // Original object + this._user = {}; // Updated object + this.userId = ""; + this.displayConfig = {}; + this.updatedFields = {}; + + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedFields); + }, + notificationType: "warning", + }, + }; + } + + #initOriginalObjects() { + this._user = UtilsNew.objectClone(this.user); + this.updatedFields = {}; + } + + update(changedProperties) { + if (changedProperties.has("userId")) { + this.userIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + userIdObserver() { + if (this.userId && this.opencgaSession) { + const params = { + organization: this.organization.id, + }; + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.users() + .info(this.userId, params) + .then(response => { + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userInfo", this.user, {}, error); + this.#setLoading(false); + }); + } + } + + render() { + return html` + + + `; + } + + getDefaultConfig() { + return { + title: "", + showTitle: false, + items: [ + { + id: "user-status-update", + name: "User Status Update", + active: true, + render: (user, active, opencgaSession) => { + return html` + + + `; + } + }, + ], + }; + } + +} + +customElements.define("user-admin-status-update", UserAdminStatusUpdate); diff --git a/src/webcomponents/user/user-status-update.js b/src/webcomponents/user/user-status-update.js new file mode 100644 index 000000000..4aa119578 --- /dev/null +++ b/src/webcomponents/user/user-status-update.js @@ -0,0 +1,176 @@ +import {LitElement, html, nothing} from "lit"; +import LitUtils from "../commons/utils/lit-utils.js"; +import NotificationUtils from "../commons/utils/notification-utils.js"; +import UtilsNew from "../../core/utils-new.js"; + +export default class UserStatusUpdate extends LitElement { + + constructor() { + super(); + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + user: { + type: Object, + }, + status: { + type: String, + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this._user = {}; + this._statusDisplay = { + "SUSPENDED": { + action: "SUSPEND", + result: "suspended", + effects: [ + "User will not be able to login", + ], + }, + "READY": { + action: "ACTIVATE", + result: "activated", + effects: [ + "User will be able to login", + ], + }, + }; + this._currentStatusDisplay = {}; + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + titleStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", + defaultLayout: "horizontal", + buttonOkText: "Reset password", + }; + this._config = this.getDefaultConfig(); + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initOriginalObjects() { + this._config = this.getDefaultConfig(); + this.requestUpdate(); + } + + update(changedProperties) { + if (changedProperties.has("displayConfig") || changedProperties.has("user")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + this._config = this.getDefaultConfig(); + } + if (changedProperties.has("status")) { + debugger + this._currentStatusDisplay = this._statusDisplay[this.status]; + } + super.update(changedProperties); + } + + onSubmit() { + // QUESTION: + // - TASK-1667, includeResult + // - JS client do not have argument for params, only user + const params = { + includeResult: true, + }; + const updateParams = { + status: "SUSPENDED", + }; + + let error; + this.#setLoading(true); + // Reset password + // Fixme: waiting for task: + // https://app.clickup.com/t/36631768/TASK-464 + // Check endpoint when released + this.opencgaSession.opencgaClient.organization() + .userUpdateStatus(this.user.id) + .then(response => { + this._user = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `Status user`, + message: `User ${this.userId} has been ${this._currentStatusDisplay.result} correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); + this.#setLoading(false); + }); + + } + + render() { + // TODO: check if opencgaSession has been provided + debugger + return html` + + + `; + } + + getDefaultConfig() { + return { + title: "User Status Update", + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + title: `Do you really want to ${this._currentStatusDisplay.action} user ${this.user?.id}?`, + elements: [ + { + type: "notification", + text: ` + [ ELABORATE ]${this._currentStatusDisplay.action} ${this.user?.id} will have the following effects: + ${this._currentStatusDisplay.effects} + `, + display: { + visible: true, + icon: "fas fa-exclamation-triangle", + notificationType: "warning", + }, + }, + { + title: "User ID", + field: "id", + type: "input-text", + display: { + disabled: true, + } + }, + ], + }, + ], + }; + } + + +} + +customElements.define("user-status-update", UserStatusUpdate); From 505a4489bf4adeb7061ffabf501110e865110369 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 27 May 2024 09:25:55 +0200 Subject: [PATCH 041/177] wc - WiP Minor clean code, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-details-update.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index 764a2423f..f3f04ad04 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -160,13 +160,12 @@ export default class UserAdminDetailsUpdate extends LitElement { } onSubmit() { + let error; const params = { includeResult: true, }; - const updateParams = FormUtils.getUpdateParams(this._user, this.updatedFields, this.updateCustomisation); -debugger - let error; + this.#setLoading(true); // Fixme: waiting for task: // https://app.clickup.com/t/36631768/TASK-6013 From 2e626e5e151160192b365d0f21142f7a927cad87 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 27 May 2024 09:59:41 +0200 Subject: [PATCH 042/177] wc - WiP Add group management, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 3 +- .../organization/admin/group-admin-create.js | 6 +-- .../organization/admin/group-admin-grid.js | 2 +- src/webcomponents/study/admin/study-admin.js | 54 +++++++++++-------- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js index a18903527..69e35a156 100644 --- a/src/webcomponents/organization/admin/group-admin-browser.js +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -155,7 +155,8 @@ export default class GroupAdminBrowser extends LitElement { studyObserver() { // Get all study groups this._groups = []; - this._studies = [this._study]; + debugger + this._studies = [this.opencgaSession.study]; this.study.groups?.forEach(group => { const newGroup = { studyId: this.study.id, diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index 4ea94c8c2..d428f7d79 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -61,11 +61,10 @@ export default class GroupAdminCreate extends LitElement { #initOriginalObjects() { this.group = {}; this.allowedValues = []; - if (this.studies && this.opencgaSession) { if (Array.isArray(this.studies) && this.studies.length === 1) { this.isStudyAdmin = true; - this.allowedValues = this.studies[0].fqn; + this.allowedValues = [this.studies[0]]; } else { // 1. Prepare structure for displaying studies per project in dropdown const projects = this.studies.reduce((acc, {fqn, name, projectId}) => { @@ -193,7 +192,7 @@ export default class GroupAdminCreate extends LitElement { required: true, display: { placeholder: "Add a short ID...", - helpMessage: "short group id...", + helpMessage: "Short group id...", }, }, { @@ -205,7 +204,6 @@ export default class GroupAdminCreate extends LitElement { required: true, allowedValues: this.allowedValues, display: { - disabled: this.isStudyAdmin, placeholder: "Select study or studies..." }, }, diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index 01c57a461..c2172aa43 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -296,7 +296,7 @@ export default class GroupAdminGrid extends LitElement { .settings="${this.toolbarSetting}" .config="${this.toolbarConfig}" @actionClick="${e => this.onActionClick(e)}" - @sampleCreate="${this.renderTable}"> + @groupCreate="${() => this.renderTable()}"> `; } diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index f3b4189ae..1cc1de523 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -454,6 +454,27 @@ export default class StudyAdmin extends LitElement { icon: "fas fa-sliders-h", visibility: "private", // public | private | none menu: [ + { + id: "general", + name: "General", + description: "", + icon: "", + featured: "", // true | false + visibility: "private", + submenu: [ + { + id: "audit", + name: "Audit", + icon: "fas fa-book", + visibility: "private", + render: (opencgaSession, study) => html` + + `, + }, + ], + }, { id: "configuration", name: "Configuration", @@ -474,6 +495,18 @@ export default class StudyAdmin extends LitElement { .study="${study}"> `, }, + { + id: "groups", + name: "Groups", + icon: "fas fa-vial", + visibility: "private", + render: (opencgaSession, organization) => html` + + + `, + }, { id: "Permissions", // label: "Permissions", @@ -550,27 +583,6 @@ export default class StudyAdmin extends LitElement { }, ], }, - { - id: "audit", - name: "Audit", - description: "", - icon: "", - featured: "", // true | false - visibility: "private", - submenu: [ - { - id: "Audit", - name: "Audit", - icon: "fas fa-book", - visibility: "private", - render: (opencgaSession, study) => html` - - `, - }, - ], - }, // { // id: "Operations", // name: "Operations", From 4c4fe64f00ee11a38dbe37466bb461c57ae838d3 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 10 Jun 2024 13:30:28 +0200 Subject: [PATCH 043/177] wc - WiP Change user status, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../commons/catalog-grid-formatter.js | 10 + .../admin/filters/user-status-filter.js | 85 +++++++++ .../organization/admin/user-admin-grid.js | 106 ++++------- .../admin/user-admin-status-update.js | 172 ++++++++++++++---- 4 files changed, 274 insertions(+), 99 deletions(-) create mode 100644 src/webcomponents/organization/admin/filters/user-status-filter.js diff --git a/src/webcomponents/commons/catalog-grid-formatter.js b/src/webcomponents/commons/catalog-grid-formatter.js index 248f78c35..76f9d8308 100644 --- a/src/webcomponents/commons/catalog-grid-formatter.js +++ b/src/webcomponents/commons/catalog-grid-formatter.js @@ -19,6 +19,16 @@ import BioinfoUtils from "../../core/bioinfo/bioinfo-utils.js"; export default class CatalogGridFormatter { + static userStatusFormatter(status, config) { + const _config = config || []; + const currentStatus = status.id || status.name || "UNDEFINED"; // Get current status + const displayCurrentStatus = _config.find(status => status.id === currentStatus); + return ` + + ${displayCurrentStatus.displayLabel} + + `; + } static phenotypesFormatter(phenotypes) { if (!phenotypes || phenotypes.length === 0) { return "-"; diff --git a/src/webcomponents/organization/admin/filters/user-status-filter.js b/src/webcomponents/organization/admin/filters/user-status-filter.js new file mode 100644 index 000000000..0d2086c7a --- /dev/null +++ b/src/webcomponents/organization/admin/filters/user-status-filter.js @@ -0,0 +1,85 @@ +/* + * Copyright 2015-2016 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html, nothing} from "lit"; +import "../../../commons/forms/select-field-filter.js"; +import UtilsNew from "../../../../core/utils-new.js"; +import LitUtils from "../../../commons/utils/lit-utils"; + +export default class UserStatusFilter extends LitElement { + + constructor() { + super(); + + // Set status and init private properties + this._init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + status: { + type: Object, + }, + config: { + type: Array + }, + disabled: { + type: Boolean + }, + }; + } + + _init() { + this.disabled = false; + } + + onFilterChange(e) { + LitUtils.dispatchCustomEvent(this, "filterChange", e.currentTarget.value); + } + + render() { + debugger + return html` +
+ ${this.config.map(status => html` + ${status.isSelectable ? html` + + + `: nothing} + `)} +
+ `; + } + +} + +customElements.define("user-status-filter", UserStatusFilter); diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 755927abc..529b22e9c 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -142,6 +142,9 @@ export default class UserAdminGrid extends LitElement { render: () => this.renderModalDetailsUpdate(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", }, + // ToDo 20240529 Vero: Nacho/Pedro to discuss: + // - Organization admin/owner can change usr pwd without entering current pwd + /* "change-password": { label: "Change Password", icon: "fas fa-edit", @@ -149,6 +152,7 @@ export default class UserAdminGrid extends LitElement { render: () => this.renderModalPasswordUpdate(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", }, + */ "reset-password": { label: "Reset Password", icon: "fas fa-edit", @@ -210,7 +214,6 @@ export default class UserAdminGrid extends LitElement { .search(this.filters) .then(response => { result = response; - debugger return response; }) .then(() => { @@ -272,7 +275,7 @@ export default class UserAdminGrid extends LitElement { { title: "Status", field: "internal.status", - formatter: (value, row) => this.statusFormatter(value, row), + formatter: value => CatalogGridFormatter.userStatusFormatter(value, this._config.userStatus), events: { "click a": e => this.onActionClick(e), }, @@ -301,7 +304,7 @@ export default class UserAdminGrid extends LitElement { return `
  • - ${modal.label}... + ${modal.label}...
  • `; @@ -320,41 +323,6 @@ export default class UserAdminGrid extends LitElement { return this._columns; } - // *** COLUMN FORMATTERS *** - statusFormatter(value, row) { - debugger - const _status = this._config?.userStatus || []; - const currentStatus = value.id || value.name || "-"; // Get current status - - // Dropdown button styles and classes - const btnClassName = "d-flex justify-content-between align-items-center btn btn-light dropdown-toggle w-100"; - - return ` - - `; - } - // *** EVENTS *** async onActionClick(e, value, row) { this.action = e.currentTarget.dataset.action; @@ -383,7 +351,7 @@ export default class UserAdminGrid extends LitElement { @@ -439,22 +407,20 @@ export default class UserAdminGrid extends LitElement { renderModalStatusUpdate() { return ModalUtils.create(this, `${this._prefix}ChangeStatusModal`, { display: { - modalTitle: `User Status: User ${this.userId} in organization ${this.organization.id}`, + modalTitle: `Update Status: User ${this.userId} in organization ${this.organization.id}`, modalDraggable: true, modalCyDataName: "modal-user-admin-status-update", modalSize: "modal-lg" }, - render: () => { - return html` - - - `; - }, + render: () => html` + + + `, }); } @@ -503,36 +469,42 @@ export default class UserAdminGrid extends LitElement { showSettings: false, exportTabs: ["download", "link", "code"], // Config - userStatus: { - "READY": { // The user can login + userStatus: [ + { + id: "READY", displayLabel: "ACTIVE", // Fixme: ACTIVE | ENABLED | READY? - displayColor: "#16A83D", - description: "", + displayColor: "#16A83C", + displayOutline: "btn-outline-success", + description: "The user can login", isSelectable: true, // Choice selectable by org admin/owner isEnabled: true, // Choice visible by org admin/owner }, - "SUSPENDED": { - displayLabel: "SUSPENDED", // User can not login into the system - displayColor: "#E17F1E", - description: "", + { + id: "SUSPENDED", + displayLabel: "SUSPENDED", + displayColor: "#E1351E", + displayOutline: "btn-outline-danger", + description: "The user can not login into the system", isSelectable: true, isEnabled: true, }, - "BANNED": { // User locked for more than X login attemtps. The admin/owner can enable the user back. + { + id: "BANNED", displayLabel: "BANNED", - displayColor: "#961EE1", - description: "", + displayColor: "#E17F1E", + description: "User locked for more than allowed login attemtps. The admin/owner can enable the user back.", isSelectable: false, isEnabled: true, }, - "DELETED": { // QUESTION: is it possible remove all permissions and login, but keep him in the system? - displayLabel: "REMOVED", - displayColor: "#E1351E", - description: "", + { + id: "UNDEFINED", + displayLabel: "-", + displayColor: "#E1E2E5", + description: "The user status is unknown", isSelectable: false, isEnabled: false, }, - }, + ], }; } diff --git a/src/webcomponents/organization/admin/user-admin-status-update.js b/src/webcomponents/organization/admin/user-admin-status-update.js index 2bc61261a..68f78e64d 100644 --- a/src/webcomponents/organization/admin/user-admin-status-update.js +++ b/src/webcomponents/organization/admin/user-admin-status-update.js @@ -18,7 +18,8 @@ import {html, LitElement} from "lit"; import UtilsNew from "../../../core/utils-new.js"; import LitUtils from "../../commons/utils/lit-utils.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; -import "../../user/user-status-update.js"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter.js"; +import "./filters/user-status-filter.js"; export default class UserAdminStatusUpdate extends LitElement { @@ -54,9 +55,14 @@ export default class UserAdminStatusUpdate extends LitElement { this._user = {}; // Updated object this.userId = ""; this.displayConfig = {}; - this.updatedFields = {}; - - this._config = this.getDefaultConfig(); + this.displayConfigDefault = { + style: "margin: 10px", + titleWidth: 3, + titleStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", + defaultLayout: "horizontal", + buttonOkText: "Update Status", + }; + this.updatedParam = ""; } #setLoading(value) { @@ -71,7 +77,7 @@ export default class UserAdminStatusUpdate extends LitElement { type: "notification", display: { visible: () => { - return UtilsNew.isNotEmpty(this.updatedFields); + return UtilsNew.isNotEmpty(this.updatedParam); }, notificationType: "warning", }, @@ -80,19 +86,18 @@ export default class UserAdminStatusUpdate extends LitElement { #initOriginalObjects() { this._user = UtilsNew.objectClone(this.user); - this.updatedFields = {}; + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + this.updatedParam = ""; + this.requestUpdate(); } update(changedProperties) { if (changedProperties.has("userId")) { this.userIdObserver(); } - if (changedProperties.has("displayConfig")) { - this._config = this.getDefaultConfig(); - if (!this._config?.notification) { - this.#initConfigNotification(); - } - } super.update(changedProperties); } @@ -120,35 +125,138 @@ export default class UserAdminStatusUpdate extends LitElement { } } + onFieldChange(e) { + this.updatedParam = e.detail.value; + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Discard changes", + message: "Are you sure you want to discard the changes made?", + ok: () => { + this.#initOriginalObjects(); + // We need to dispatch a component clear event + LitUtils.dispatchCustomEvent(this, "userClear", null, { + user: this.user, + }); + }, + }); + } + + onSubmit() { + let error; + const params = { + includeResult: true, + }; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + .userUpdateStatus(this.user.id, this.updatedParam, params) + .then(response => { + this.user = UtilsNew.objectClone(response.responses[0].results[0]); + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: `User Status Update`, + message: `User ${this.userId} status has been updated correctly`, + }); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "userUpdate", this.user, {}, error); + this.#setLoading(false); + }); + + } + render() { + if (this.isLoading) { + return html``; + } + + if (!this.user.internal?.status?.id) { + return html ` +
    + + The ${this.user.id} does not have an status ID. +
    + `; + } + return html` - - + .config="${this._config}" + @fieldChange="${e => this.onFieldChange(e)}" + @submit="${this.onSubmit}" + @clear="${this.onClear}"> + `; } getDefaultConfig() { return { - title: "", - showTitle: false, - items: [ + icon: "fas fa-edit", + buttons: { + clearText: "Discard Changes", + okText: "Update", + }, + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + elements: [ + { + title: "User ID", + field: "id", + type: "input-text", + display: { + disabled: true, + } + }, + { + title: "Current Status", + type: "complex", + display: { + containerClassName: "d-flex align-items-center", + template: "${internal.status}", + format: { + // FIXME: Displaying original data this.user.internal.status. Should not be a complex element + "internal.status": () => CatalogGridFormatter.userStatusFormatter(this.user?.internal?.status, this._config.display?.userStatus), + }, + }, + }, + ], + }, { - id: "user-status-update", - name: "User Status Update", - active: true, - render: (user, active, opencgaSession) => { - return html` - - - `; - } + // title: "Change Status", + // description: "You can change the status of the user here", + display: { + // titleHeader: "h4", + // titleClassName: "d-block text-secondary" + // titleStyle: "", + // descriptionClassName: "d-block text-secondary", + // descriptionStyle: "", + // visible: () => + }, + elements: [ + { + title: "New Status", + field: "internal.status.id", + type: "custom", + display: { + render: (status, dataFormFilterChange) => html ` + + + `, + }, + }, + ], }, ], }; From 41c0204ef8cae04babeb1cbf908d20fa1553f6cd Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 10 Jun 2024 13:31:59 +0200 Subject: [PATCH 044/177] wc - WiP Minor clean, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/user-admin-details-update.js | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index f3f04ad04..699cd8276 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -19,7 +19,6 @@ import UtilsNew from "../../../core/utils-new.js"; import LitUtils from "../../commons/utils/lit-utils.js"; import FormUtils from "../../commons/forms/form-utils.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; -import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; export default class UserAdminDetailsUpdate extends LitElement { @@ -139,8 +138,6 @@ export default class UserAdminDetailsUpdate extends LitElement { e.detail.value, e.detail.action); - debugger - // this.updatedFields = e.detail?.data || {}; this.requestUpdate(); } @@ -176,7 +173,7 @@ export default class UserAdminDetailsUpdate extends LitElement { this.user = UtilsNew.objectClone(response.responses[0].results[0]); this.#initOriginalObjects(); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { - title: `User Update`, + title: `User Details Update`, message: `User ${this.userId} updated correctly`, }); }) @@ -198,8 +195,8 @@ export default class UserAdminDetailsUpdate extends LitElement { .config="${this._config}" .updateParams="${e => this.updatedFields(e)}" @fieldChange="${e => this.onFieldChange(e)}" - @clear="${this.onClear}" - @submit="${this.onSubmit}"> + @submit="${this.onSubmit}" + @clear="${this.onClear}"> `; } @@ -235,16 +232,6 @@ export default class UserAdminDetailsUpdate extends LitElement { helpMessage: "Edit the user email...", }, }, - { - title: "Enable user", - field: "enabled", - type: "toggle-switch", - display: { - disabled: true, - helpMessage: "Coming soon: Enable/Disable a user in an organization", - }, - }, - ], }, { From 6cf1254348768c73229f72f4df203bf33347c404 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 10 Jun 2024 13:39:29 +0200 Subject: [PATCH 045/177] wc - Refactor code, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/user/user-status-update.js | 176 ------------------- 1 file changed, 176 deletions(-) delete mode 100644 src/webcomponents/user/user-status-update.js diff --git a/src/webcomponents/user/user-status-update.js b/src/webcomponents/user/user-status-update.js deleted file mode 100644 index 4aa119578..000000000 --- a/src/webcomponents/user/user-status-update.js +++ /dev/null @@ -1,176 +0,0 @@ -import {LitElement, html, nothing} from "lit"; -import LitUtils from "../commons/utils/lit-utils.js"; -import NotificationUtils from "../commons/utils/notification-utils.js"; -import UtilsNew from "../../core/utils-new.js"; - -export default class UserStatusUpdate extends LitElement { - - constructor() { - super(); - this.#init(); - } - - createRenderRoot() { - return this; - } - - static get properties() { - return { - user: { - type: Object, - }, - status: { - type: String, - }, - opencgaSession: { - type: Object - }, - displayConfig: { - type: Object - }, - }; - } - - #init() { - this._user = {}; - this._statusDisplay = { - "SUSPENDED": { - action: "SUSPEND", - result: "suspended", - effects: [ - "User will not be able to login", - ], - }, - "READY": { - action: "ACTIVATE", - result: "activated", - effects: [ - "User will be able to login", - ], - }, - }; - this._currentStatusDisplay = {}; - this.displayConfigDefault = { - style: "margin: 10px", - titleWidth: 3, - titleStyle: "color: var(--main-bg-color);margin-bottom:16px;font-weight:bold;", - defaultLayout: "horizontal", - buttonOkText: "Reset password", - }; - this._config = this.getDefaultConfig(); - } - - #setLoading(value) { - this.isLoading = value; - this.requestUpdate(); - } - - #initOriginalObjects() { - this._config = this.getDefaultConfig(); - this.requestUpdate(); - } - - update(changedProperties) { - if (changedProperties.has("displayConfig") || changedProperties.has("user")) { - this.displayConfig = { - ...this.displayConfigDefault, - ...this.displayConfig - }; - this._config = this.getDefaultConfig(); - } - if (changedProperties.has("status")) { - debugger - this._currentStatusDisplay = this._statusDisplay[this.status]; - } - super.update(changedProperties); - } - - onSubmit() { - // QUESTION: - // - TASK-1667, includeResult - // - JS client do not have argument for params, only user - const params = { - includeResult: true, - }; - const updateParams = { - status: "SUSPENDED", - }; - - let error; - this.#setLoading(true); - // Reset password - // Fixme: waiting for task: - // https://app.clickup.com/t/36631768/TASK-464 - // Check endpoint when released - this.opencgaSession.opencgaClient.organization() - .userUpdateStatus(this.user.id) - .then(response => { - this._user = UtilsNew.objectClone(response.responses[0].results[0]); - this.#initOriginalObjects(); - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { - title: `Status user`, - message: `User ${this.userId} has been ${this._currentStatusDisplay.result} correctly`, - }); - }) - .catch(reason => { - error = reason; - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); - }) - .finally(() => { - LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); - this.#setLoading(false); - }); - - } - - render() { - // TODO: check if opencgaSession has been provided - debugger - return html` - - - `; - } - - getDefaultConfig() { - return { - title: "User Status Update", - display: this.displayConfig || this.displayConfigDefault, - sections: [ - { - title: `Do you really want to ${this._currentStatusDisplay.action} user ${this.user?.id}?`, - elements: [ - { - type: "notification", - text: ` - [ ELABORATE ]${this._currentStatusDisplay.action} ${this.user?.id} will have the following effects: - ${this._currentStatusDisplay.effects} - `, - display: { - visible: true, - icon: "fas fa-exclamation-triangle", - notificationType: "warning", - }, - }, - { - title: "User ID", - field: "id", - type: "input-text", - display: { - disabled: true, - } - }, - ], - }, - ], - }; - } - - -} - -customElements.define("user-status-update", UserStatusUpdate); From 183a0fe72faab4d87ea95ceb07d648f44e04f9e6 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 13 Jun 2024 20:38:04 +0200 Subject: [PATCH 046/177] wc - WiP Add Projects/Studies, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/organization-admin.js | 20 +- .../admin/project-admin-browser.js | 245 +++++++++++ .../organization/admin/study-admin-grid.js | 387 ++++++++++++++++++ src/webcomponents/project/project-update.js | 8 +- 4 files changed, 653 insertions(+), 7 deletions(-) create mode 100644 src/webcomponents/organization/admin/project-admin-browser.js create mode 100644 src/webcomponents/organization/admin/study-admin-grid.js diff --git a/src/webcomponents/organization/admin/organization-admin.js b/src/webcomponents/organization/admin/organization-admin.js index f4518ab31..3a92c32cc 100644 --- a/src/webcomponents/organization/admin/organization-admin.js +++ b/src/webcomponents/organization/admin/organization-admin.js @@ -16,9 +16,10 @@ import {LitElement, html} from "lit"; import UtilsNew from "../../../core/utils-new"; import LitUtils from "../../commons/utils/lit-utils"; -import "../../project/projects-admin.js"; import "./group-admin-browser.js"; import "./user-admin-browser.js"; +import "../../project/projects-admin.js"; +import "./project-admin-browser.js"; // FIXME VERY IMPORTANT: // ******************************************** @@ -66,8 +67,6 @@ export default class OrganizationAdmin extends LitElement { super.update(changedProperties); } - - organizationIdObserver() { // FIXME Vero: on creating a new group, for instance, // the session is updated but the org id does not change. @@ -126,7 +125,7 @@ export default class OrganizationAdmin extends LitElement { // TODO { id: "dashboard", - name: "Dashboard", + name: "Dashboard (Coming soon)", icon: "fas fa-vial", visibility: "private", render: (opencgaSession, study) => html``, @@ -134,7 +133,7 @@ export default class OrganizationAdmin extends LitElement { // TODO { id: "audit", - name: "Audit", + name: "Audit (Coming soon)", type: "category", icon: "fas fa-vial", visibility: "private", @@ -179,7 +178,8 @@ export default class OrganizationAdmin extends LitElement { name: "Projects/Studies", icon: "fas fa-vial", visibility: "private", - render: (opencgaSession, study) => { + render: (opencgaSession, organization) => { + /* return html`
    `; + */ + debugger + return html` + + + `; }, }, ], diff --git a/src/webcomponents/organization/admin/project-admin-browser.js b/src/webcomponents/organization/admin/project-admin-browser.js new file mode 100644 index 000000000..2939a5570 --- /dev/null +++ b/src/webcomponents/organization/admin/project-admin-browser.js @@ -0,0 +1,245 @@ +/** + * Copyright 2015-2024 OpenCB * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import {LitElement, html, nothing} from "lit"; +import UtilsNew from "../../../core/utils-new.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import ModalUtils from "../../commons/modal/modal-utils.js"; +import "../../project/project-create.js"; +import "../../project/project-update.js"; +import "./study-admin-grid.js"; + +export default class ProjectAdminBrowser extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + organization: { + type: Object, + }, + opencgaSession: { + type: Object, + }, + config: { + type: Object + }, + }; + } + + #init() { + this.COMPONENT_ID = "project-admin-browser"; + this._prefix = UtilsNew.randomString(8); + this.gridId = this._prefix + this.COMPONENT_ID; + this.projects = []; + this._config = this.getDefaultConfig(); + } + + update(changedProperties) { + if (changedProperties.has("opencgaSession") || + changedProperties.has("organization") || + changedProperties.has("config")) { + this.propertyObserver(); + } + super.update(changedProperties); + } + + propertyObserver() { + // With each property change we must be updated config and create the columns again. No extra checks are needed. + this._config = { + ...this.getDefaultConfig(), + ...this.config, + }; + + // Config for the grid toolbar + this.toolbarSetting = { + ...this._config, + }; + + this.toolbarConfig = { + toolId: this.toolId, + resource: "PROJECTS", + create: { + display: { + modalTitle: "Project Create", + modalDraggable: true, + modalCyDataName: "modal-create", + modalSize: "modal-lg" + // disabled: true, + // disabledTooltip: "...", + }, + render: () => html ` + + ` + }, + }; + + this.modals = { + "project-update": { + label: "Edit Project", + icon: "fas fa-edit", + modalId: `${this._prefix}UpdateProjectModal`, + render: () => this.renderProjectUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + }; + } + + // *** EVENTS *** + async onActionClick(e, project) { + this.action = e.currentTarget.dataset.action; + this.projectId = project.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(this.modals[this.action]["modalId"]); + } + + // *** RENDER *** + renderProjectUpdate() { + debugger + return ModalUtils.create(this, `${this._prefix}UpdateProjectModal`, { + display: { + modalTitle: `Update Project: Project ${this.projectId} in organization ${this.organization.id}`, + modalDraggable: true, + modalCyDataName: "modal-project-update", + modalSize: "modal-lg" + }, + // @projectUpdate="${e => this.onProjectUpdate(e, `${this._prefix}UpdateDetailsModal`)}" + render: () => { + debugger + return html` + + + `; + }, + }); + } + + renderProjectsToolbar() { + if (this._config.showToolbar) { + return html ` + + + `; + } + } + + renderProject(project) { + debugger + return html ` +
    + +
    + +
    +

    +
    +
    + ${project.name || project.id} +
    +
    + ${project.organism?.scientificName.toUpperCase() || "-"} (${project.organism?.assembly || "-"}) +
    +
    + + Cellbase: ${project.cellbase?.version || "-"}, + + DR. ${project.cellbase?.dataRelease || "-"} +
    +
    +

    +
    + +
    + ${ + Object.keys(this.modals).map(modalKey => { + const modal = this.modals[modalKey]; + return html` + + `; + }) + } +
    +
    + +
    + [${project.fqn}] +
    +
    + ${project.description} + +
    + + + + + ${this.action ? this.modals[this.action]["render"](): nothing} +
    + `; + } + + render() { + return html` + + ${this.renderProjectsToolbar()} + + ${this.organization.projects.map(project => this.renderProject(project))} + `; + } + + // *** CONFIG *** + getDefaultConfig() { + return { + showToolbar: true, + showExport: false, + showSettings: false, + showCreate: true, + showGraphicFilters: false, + showProjectToolbar: true, + }; + } + +} + +customElements.define("project-admin-browser", ProjectAdminBrowser); diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js new file mode 100644 index 000000000..ffc547f90 --- /dev/null +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -0,0 +1,387 @@ +/** + * Copyright 2015-2024 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html, nothing} from "lit"; +import GridCommons from "../../commons/grid-commons.js"; +import CatalogGridFormatter from "../../commons/catalog-grid-formatter.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import ModalUtils from "../../commons/modal/modal-utils.js"; +import UtilsNew from "../../../core/utils-new.js"; + +// import "./study-admin-create.js"; +// import "./study-admin-update.js"; +import "../../study/study-create.js"; +// import "../../study/study-update.js"; + +export default class StudyAdminGrid extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + toolId: { + type: String, + }, + project: { + type: Object, + }, + opencgaSession: { + type: Object + }, + active: { + type: Boolean + }, + config: { + type: Object + }, + }; + } + + #init() { + this.COMPONENT_ID = "study-grid"; + this._prefix = UtilsNew.randomString(8); + this.gridId = this._prefix + this.COMPONENT_ID; + this.active = true; + this._config = this.getDefaultConfig(); + this.action = ""; + } + + // --- LIFE-CYCLE METHODS + update(changedProperties) { + if (changedProperties.has("opencgaSession") || + changedProperties.has("toolId") || + changedProperties.has("project") || + changedProperties.has("config")) { + this.propertyObserver(); + } + super.update(changedProperties); + } + + updated(changedProperties) { + if (changedProperties.size > 0 && this.active) { + this.renderRemoteTable(); + } + } + + propertyObserver() { + // With each property change we must be updated config and create the columns again. No extra checks are needed. + this._config = { + ...this.getDefaultConfig(), + ...this.config, + }; + + this.gridCommons = new GridCommons(this.gridId, this, this._config); + + // Config for the grid toolbar + this.toolbarSetting = { + ...this._config, + }; + + this.toolbarConfig = { + toolId: this.toolId, + resource: "STUDIES", + columns: this._getDefaultColumns(), + create: { + display: { + modalTitle: "Study Create", + modalDraggable: true, + modalCyDataName: "modal-create", + modalSize: "modal-lg" + // disabled: true, + // disabledTooltip: "...", + }, + // + // + render: () => html ` + + + `, + }, + }; + + this.permissions = { + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }; + + this.modals = { + "edit-study": { + label: "Edit Study", + icon: "fas fa-edit", + modalId: `${this._prefix}UpdateStudyModal`, + render: () => this.renderStudyUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + "delete": { + label: "Delete", + icon: "far fa-trash-alt ", + // modalId: `${this._prefix}DeleteModal`, + // render: () => this.renderModalPasswordReset(), + permission: "disabled", + }, + }; + } + + // *** PRIVATE METHODS *** + renderRemoteTable() { + if (this.opencgaSession?.opencgaClient && this.project.id) { + this._columns = this._getDefaultColumns(); + this.table = $("#" + this.gridId); + this.table.bootstrapTable("destroy"); + this.table.bootstrapTable({ + theadClasses: "table-light", + buttonsClass: "light", + columns: this._columns, + method: "get", + sidePagination: "server", + iconsPrefix: GridCommons.GRID_ICONS_PREFIX, + icons: GridCommons.GRID_ICONS, + uniqueId: "id", + // Table properties + pagination: this._config.pagination, + pageSize: this._config.pageSize, + pageList: this._config.pageList, + detailView: !!this.detailFormatter, + loadingTemplate: () => GridCommons.loadingFormatter(), + ajax: params => { + let result = null; + this.filters = { + limit: params.data.limit, + skip: params.data.offset || 0, + count: !this.table.bootstrapTable("getOptions").pageNumber || this.table.bootstrapTable("getOptions").pageNumber === 1, + }; + + // Store the current filters + this.opencgaSession.opencgaClient.projects() + .studies(this.project.id, this.filters) + .then(response => { + result = response; + debugger + return response; + }) + .then(() => { + // Prepare data for columns extensions + const rows = result.responses?.[0]?.results || []; + return this.gridCommons.prepareDataForExtensions(this.COMPONENT_ID, this.opencgaSession, this.filters, rows); + }) + .then(() => params.success(result)) + .catch(error => { + debugger + console.error(error); + params.error(error); + }); + }, + responseHandler: response => { + const result = this.gridCommons.responseHandler(response, $(this.table).bootstrapTable("getOptions")); + return result.response; + }, + onClickRow: (row, selectedElement) => this.gridCommons.onClickRow(row.id, row, selectedElement), + // onLoadSuccess: data => this.gridCommons.onLoadSuccess(data, 1), + onLoadError: (e, restResponse) => this.gridCommons.onLoadError(e, restResponse), + }); + } + } + + _getDefaultColumns() { + debugger + this._columns = [ + { + title: "Study ID", + field: "id", + visible: this.gridCommons.isColumnVisible("id") + }, + { + title: "Name", + field: "name", + visible: this.gridCommons.isColumnVisible("name") + }, + { + title: "Creation Date", + field: "creationDate", + formatter: CatalogGridFormatter.dateFormatter, + visible: this.gridCommons.isColumnVisible("creationDate") + }, + { + title: "Modification Date", + field: "modificationDate", + formatter: CatalogGridFormatter.dateFormatter, + visible: this.gridCommons.isColumnVisible("modificationDate") + }, + { + title: "Groups", + field: "groups", + formatter: (groups, study) => this.groupsFormatter(groups, study), + visible: this.gridCommons.isColumnVisible("modificationDate") + } + ]; + + if (this._config.annotations?.length > 0) { + this.gridCommons.addColumnsFromAnnotations(this._columns, CatalogGridFormatter.customAnnotationFormatter, this._config); + } + + if (this.opencgaSession && this._config.showActions) { + this._columns.push({ + id: "actions", + title: "Actions", + field: "actions", + formatter: () => ` + + `, + events: { + "click ul>li>a": (e, value, row) => this.onActionClick(e, value, row), + }, + }); + } + + this._columns = this.gridCommons.addColumnsFromExtensions(this._columns, this.COMPONENT_ID); + return this._columns; + } + // *** FORMATTERS *** + groupsFormatter(groups, study) { + debugger + const groupsBadges = groups.map(group => ` + + ${group.id} [${group.userIds.length}] + + `).join(""); + return ` +
    + ${groupsBadges} +
    + `; + } + + // *** EVENTS *** + async onActionClick(e, value, row) { + this.action = e.currentTarget.dataset.action; + this.userId = row.id; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(this.modals[this.action]["modalId"]); + } + + onStudyUpdate(e, id) { + ModalUtils.close(id); + this.renderRemoteTable(); + } + + // *** RENDER METHODS *** + renderStudyUpdate() { + return ModalUtils.create(this, `${this._prefix}UpdateStudyModal`, { + display: { + modalTitle: `Update Study: `, + modalDraggable: true, + modalCyDataName: "modal-study-create", + modalSize: "modal-lg" + }, + render: () => html` + + + `, + }); + } + + renderToolbar() { + if (this._config.showToolbar) { + return html ` + + + `; + } + } + + render() { + return html` + + ${this.renderToolbar()} + +
    +
    +
    + + ${this.action ? this.modals[this.action]["render"](): nothing} + `; + } + + // *** DEFAULT CONFIG *** + getDefaultConfig() { + return { + // Settings + pagination: true, + pageSize: 10, + pageList: [5, 10, 25], + pageInfoShort: true, + multiSelection: false, + showSelectCheckbox: false, + + showToolbar: true, + showActions: true, + + showCreate: true, + showExport: false, + showSettings: false, + exportTabs: ["download", "link", "code"], + }; + } + +} + +customElements.define("study-admin-grid", StudyAdminGrid); diff --git a/src/webcomponents/project/project-update.js b/src/webcomponents/project/project-update.js index fcae97496..77ab55107 100644 --- a/src/webcomponents/project/project-update.js +++ b/src/webcomponents/project/project-update.js @@ -51,6 +51,7 @@ export default class ProjectUpdate extends LitElement { } #init() { + debugger this.project = {}; this.updateParams = {}; this.isLoading = false; @@ -76,11 +77,15 @@ export default class ProjectUpdate extends LitElement { } update(changedProperties) { + debugger if (changedProperties.has("projectId")) { this.projectIdObserver(); } if (changedProperties.has("displayConfig")) { - this.displayConfig = {...this.displayConfigDefault, ...this.displayConfig}; + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; this._config = this.getDefaultConfig(); } super.update(changedProperties); @@ -191,6 +196,7 @@ export default class ProjectUpdate extends LitElement { } render() { + debugger if (this.isLoading) { return html``; } From 54578646466dcbbfde8b370d63f2a47c05af6aee Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 13 Jun 2024 20:39:00 +0200 Subject: [PATCH 047/177] wc - Minor clean, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/user-admin-browser.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-browser.js b/src/webcomponents/organization/admin/user-admin-browser.js index 7fdc2028d..94fbe9efd 100644 --- a/src/webcomponents/organization/admin/user-admin-browser.js +++ b/src/webcomponents/organization/admin/user-admin-browser.js @@ -18,9 +18,8 @@ import {LitElement, html} from "lit"; import LitUtils from "../../commons/utils/lit-utils.js"; import UtilsNew from "../../../core/utils-new.js"; -import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; import "./user-admin-grid.js"; -import NotificationUtils from "../../commons/utils/notification-utils"; export default class UserAdminBrowser extends LitElement { From c8fe1a910e0b476d8c2903b04745c50d47ced7bd Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 14 Jun 2024 23:54:34 +0200 Subject: [PATCH 048/177] wc - WiP groups code refactored and clean, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/sites/iva/iva-app.js | 2 +- .../organization/admin/group-admin-create.js | 16 +- .../organization/admin/group-admin-delete.js | 39 +++- .../organization/admin/group-admin-grid.js | 175 +++++++++++++----- 4 files changed, 169 insertions(+), 63 deletions(-) diff --git a/src/sites/iva/iva-app.js b/src/sites/iva/iva-app.js index 8be74727e..e1d53f24a 100644 --- a/src/sites/iva/iva-app.js +++ b/src/sites/iva/iva-app.js @@ -2018,7 +2018,7 @@ class IvaApp extends LitElement { + @studyUpdateRequest="${this.onStudyUpdateRequest}"> ` : null} diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index d428f7d79..45841e659 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -18,6 +18,7 @@ import {LitElement, html} from "lit"; import LitUtils from "../../commons/utils/lit-utils.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; +import UtilsNew from "../../../core/utils-new"; export default class GroupAdminCreate extends LitElement { @@ -131,12 +132,16 @@ export default class GroupAdminCreate extends LitElement { } onSubmit() { + const params = { + includeResult: true, + action: "ADD", + }; this.#setLoading(true); const groupPromises = this.group.listStudies .map(study => { let error; return this.opencgaSession.opencgaClient.studies() - .updateGroups(study, {id: this.group.id}, {action: "ADD"}) + .updateGroups(study, {id: this.group.id}, params) .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `Group Create`, @@ -149,8 +154,8 @@ export default class GroupAdminCreate extends LitElement { }) .finally(() => { LitUtils.dispatchCustomEvent(this, "groupCreate", {}, { - id: this.group.id, - study: study, + group: this.group, + studyFqn: study, }, error); }); }); @@ -159,7 +164,8 @@ export default class GroupAdminCreate extends LitElement { .finally(() => { this.#setLoading(false); this.#initOriginalObjects(); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, null); + // CAUTION Vero: Why is not working sessionUpdateRequest + LitUtils.dispatchCustomEvent(this, "studyUpdateRequest", {}); }); } @@ -183,7 +189,7 @@ export default class GroupAdminCreate extends LitElement { display: this.displayConfig || this.displayConfigDefault, sections: [ { - title: "General Information", + // title: "General Information", elements: [ { title: "Group ID", diff --git a/src/webcomponents/organization/admin/group-admin-delete.js b/src/webcomponents/organization/admin/group-admin-delete.js index 570b32790..7d38022ad 100644 --- a/src/webcomponents/organization/admin/group-admin-delete.js +++ b/src/webcomponents/organization/admin/group-admin-delete.js @@ -58,7 +58,7 @@ export default class GroupAdminDelete extends LitElement { style: "margin: 10px", titleWidth: 3, defaultLayout: "horizontal", - buttonOkText: "I understand. Let's delete this group" + buttonOkText: "Delete", }; this._config = this.getDefaultConfig(); } @@ -72,8 +72,9 @@ export default class GroupAdminDelete extends LitElement { if (changedProperties.has("displayConfig")) { this.displayConfig = { ...this.displayConfigDefault, - ...this.displayConfig + ...this.displayConfig, }; + this._config = this.getDefaultConfig(); } super.update(changedProperties); } @@ -95,11 +96,12 @@ export default class GroupAdminDelete extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { + this.#setLoading(false); LitUtils.dispatchCustomEvent(this, "groupDelete", {}, { - id: this.group.id, - study: this.studyFqn, + group: this.group, + studyFqn: this.studyFqn, }, error); - this.#setLoading(false); + LitUtils.dispatchCustomEvent(this, "studyUpdateRequest", {}); }); } @@ -111,6 +113,7 @@ export default class GroupAdminDelete extends LitElement { return html` `; @@ -121,7 +124,7 @@ export default class GroupAdminDelete extends LitElement { display: this.displayConfig || this.displayConfigDefault, sections: [ { - title: "Do you really want to delete this group?", + // title: `Are you sure you want to remove group '${this.group?.id}'?`, elements: [ { type: "notification", @@ -129,14 +132,32 @@ export default class GroupAdminDelete extends LitElement { display: { visible: true, icon: "fas fa-exclamation-triangle", - notificationType: "error", + notificationType: "warning", }, }, { + // name: "UserIds", + field: "userIds", type: "list", display: { - contentLayout: "vertical", - getData: group => group.ids || ["This group does not have users"], + separator: " ", + contentLayout: "bullets", + transform: userIds => userIds.map(userId => ({userId})), + template: "${userId}", + /* FIXME: why is not working? + className: { + "userId": "badge badge-pill badge-primary", + }, + */ + // style: { + // "userId": { + // "color": "white", + // "background-color": "blue" + // }, + // } + + // contentLayout: "bullets", + // getData: group => group.userIds || ["This group does not have users"], }, }, ], diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index c2172aa43..a5a4aab15 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -20,8 +20,9 @@ import UtilsNew from "../../../core/utils-new"; import ModalUtils from "../../commons/modal/modal-utils"; import CatalogGridFormatter from "../../commons/catalog-grid-formatter"; import "./group-admin-create.js"; -import "./group-admin-update.js"; +import "./group-admin-permissions-update.js"; import "./group-admin-delete.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; export default class GroupAdminGrid extends LitElement { @@ -64,13 +65,15 @@ export default class GroupAdminGrid extends LitElement { this.gridId = this._prefix + this.COMPONENT_ID; this.active = true; this._config = this.getDefaultConfig(); + this.action = ""; + this.studyFqn = ""; } update(changedProperties) { if (changedProperties.has("opencgaSession") || changedProperties.has("toolId") || - changedProperties.has("config") || - changedProperties.has("studies")) { + changedProperties.has("studies") || + changedProperties.has("config")) { this.propertyObserver(); } super.update(changedProperties); @@ -106,8 +109,6 @@ export default class GroupAdminGrid extends LitElement { modalDraggable: true, modalCyDataName: "modal-create", modalSize: "modal-lg" - // disabled: true, - // disabledTooltip: "...", }, render: () => { return html ` @@ -120,13 +121,43 @@ export default class GroupAdminGrid extends LitElement { } }, }; + + this.permissions = { + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }; + + this.modals = { + /* + "edit-details": { + label: "Edit Details", + icon: "fas fa-edit", + modalId: `${this._prefix}UpdateDetailsModal`, + render: () => this.renderModalDetailsUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + */ + "edit-permissions": { + label: "Edit Permissions", + icon: "fas fa-edit", + modalId: `${this._prefix}UpdatePermissionsModal`, + render: () => this.renderModalPermissionsUpdate(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + "delete": { + label: "Delete", + icon: "far fa-trash-alt ", + modalId: `${this._prefix}DeleteModal`, + render: () => this.renderModalDelete(), + permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + }, + }; + } renderTable() { if (this.groups?.length > 0) { this.renderLocalTable(); - } else { - this.renderRemoteTable(); } this.requestUpdate(); } @@ -172,24 +203,6 @@ export default class GroupAdminGrid extends LitElement { }); } - async onActionClick(e, value, row) { - const action = e.currentTarget.dataset.action; - this.group = row.group; - this.studyFqn = row.fqn; - this.requestUpdate(); - await this.updateComplete; - switch (action) { - case "edit": - ModalUtils.show(`${this._prefix}UpdateModal`); - break; - case "delete": - ModalUtils.show(`${this._prefix}DeleteModal`); - break; - default: - break; - } - } - _getDefaultColumns() { this._columns = [ { @@ -225,20 +238,30 @@ export default class GroupAdminGrid extends LitElement { id: "actions", title: "Actions", field: "actions", - formatter: (value, row) => ` -
    - - - -
    `, + + + `, events: { - "click button": (e, value, row) => this.onActionClick(e, value, row), + "click ul>li>a": (e, value, row) => this.onActionClick(e, value, row), }, }); } @@ -247,6 +270,63 @@ export default class GroupAdminGrid extends LitElement { return this._columns; } + // *** EVENTS *** + /* + async onActionClick(e, value, row) { + const action = e.currentTarget.dataset.action; + this.group = row.group; + this.studyFqn = row.fqn; + this.requestUpdate(); + await this.updateComplete; + switch (action) { + case "edit": + ModalUtils.show(`${this._prefix}UpdateModal`); + break; + case "delete": + ModalUtils.show(`${this._prefix}DeleteModal`); + break; + default: + break; + } + } + */ + async onActionClick(e, value, row) { + this.action = e.currentTarget.dataset.action; + this.group = row.group; + this.studyFqn = row.fqn; + this.requestUpdate(); + await this.updateComplete; + ModalUtils.show(this.modals[this.action]["modalId"]); + } + + onGroupEvent(e, id) { + this.studyFqn = e.detail.studyFqn; + ModalUtils.close(id); + } + + // *** RENDER METHODS *** + renderModalPermissionsUpdate() { + return ModalUtils.create(this, `${this._prefix}UpdatePermissionsModal`, { + display: { + modalTitle: `Group Permissions Update: group ${this.group?.id} in study ${this.studyFqn}`, + modalDraggable: true, + modalCyDataName: "modal-update", + modalSize: "modal-lg" + }, + render: active => html` + + + `, + }); + } + + /* renderModalUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateModal`, { display: { @@ -266,11 +346,13 @@ export default class GroupAdminGrid extends LitElement { `, }); } + */ renderModalDelete() { return ModalUtils.create(this, `${this._prefix}DeleteModal`, { display: { - modalTitle: `Group Delete: ${this.group?.id} in study ${this.studyFqn}`, + // modalTitle: `Group Delete: ${this.group?.id} in study ${this.studyFqn}`, + modalTitle: `Are you sure you want to remove group '${this.group?.id}' in study '${this.studyFqn}'?`, modalDraggable: true, modalCyDataName: "modal-update", modalSize: "modal-lg" @@ -280,8 +362,9 @@ export default class GroupAdminGrid extends LitElement { .group="${this.group}" .studyFqn="${this.studyFqn}" .active="${active}" - .displayConfig="${{mode: "page", type: "tabs", buttonsLayout: "upper"}}" - .opencgaSession="${this.opencgaSession}"> + .displayConfig="${{mode: "page", type: "form", buttonsLayout: "bottom"}}" + .opencgaSession="${this.opencgaSession}" + @groupDelete="${e => this.onGroupEvent(e, `${this._prefix}DeleteModal`)}"> `, }); @@ -289,14 +372,12 @@ export default class GroupAdminGrid extends LitElement { renderToolbar() { if (this._config.showToolbar) { + // @groupCreate="${e => this.onGroupEvent(e, `${this._prefix}Modal`)}" return html ` + .config="${this.toolbarConfig}"> `; } @@ -310,10 +391,8 @@ export default class GroupAdminGrid extends LitElement {
    - - ${this.renderModalDelete()} - - ${this.renderModalUpdate()} + + ${this.action ? this.modals[this.action]["render"](): nothing} `; } From 1c483ef9503192b0674f81bb519a91040a1c54f4 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 14 Jun 2024 23:54:52 +0200 Subject: [PATCH 049/177] wc - WiP groups code refactored and clean, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- ...e.js => group-admin-permissions-update.js} | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) rename src/webcomponents/organization/admin/{group-admin-update.js => group-admin-permissions-update.js} (93%) diff --git a/src/webcomponents/organization/admin/group-admin-update.js b/src/webcomponents/organization/admin/group-admin-permissions-update.js similarity index 93% rename from src/webcomponents/organization/admin/group-admin-update.js rename to src/webcomponents/organization/admin/group-admin-permissions-update.js index 5f81c1cf9..05d52975c 100644 --- a/src/webcomponents/organization/admin/group-admin-update.js +++ b/src/webcomponents/organization/admin/group-admin-permissions-update.js @@ -20,7 +20,7 @@ import LitUtils from "../../commons/utils/lit-utils.js"; import FormUtils from "../../commons/forms/form-utils"; import NotificationUtils from "../../commons/utils/notification-utils"; -export default class GroupAdminUpdate extends LitElement { +export default class GroupAdminPermissionsUpdate extends LitElement { constructor() { super(); @@ -208,7 +208,10 @@ export default class GroupAdminUpdate extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "updateGroup", this.group, {}, error); + LitUtils.dispatchCustomEvent(this, "groupUpdate", { + group: this.group, + studyFqn: this.studyFqn, + }, error); this.#setLoading(false); }); } @@ -235,6 +238,7 @@ export default class GroupAdminUpdate extends LitElement { }, display: this.displayConfig, sections: [ + /* { title: "Details", elements: [ @@ -250,8 +254,12 @@ export default class GroupAdminUpdate extends LitElement { }, ], }, + */ { title: "Permissions", + display: { + titleVisible: false, + }, elements: [ { title: "Templates", @@ -267,6 +275,7 @@ export default class GroupAdminUpdate extends LitElement { // }, ], }, + /* { title: "Users", elements: [ @@ -286,9 +295,9 @@ export default class GroupAdminUpdate extends LitElement { }; return html` + .studyId="${this.studyId}" + .users="${this.users}" + .opencgaSession="${this.opencgaSession}"> `; } @@ -297,10 +306,11 @@ export default class GroupAdminUpdate extends LitElement { } ], }, + */ ], }; } } -customElements.define("group-admin-update", GroupAdminUpdate); +customElements.define("group-admin-permissions-update", GroupAdminPermissionsUpdate); From 381fcbca9e186b8c947200d81c49eb2ce841a14c Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 14 Jun 2024 23:55:39 +0200 Subject: [PATCH 050/177] wc - Fix add usr to study, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/study/admin/study-admin-users.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/webcomponents/study/admin/study-admin-users.js b/src/webcomponents/study/admin/study-admin-users.js index b91f7f408..32dedf56a 100644 --- a/src/webcomponents/study/admin/study-admin-users.js +++ b/src/webcomponents/study/admin/study-admin-users.js @@ -334,8 +334,15 @@ export default class StudyAdminUsers extends LitElement { console.log("User already exists in the study"); return; } + const params = { + study: this.study.fqn, + template: "", + permissions: "", + }; - this.opencgaSession.opencgaClient.studies().updateUsers(this.study.fqn, "@members", {users: [this.addUserId]}, {action: "ADD"}) + this.opencgaSession.opencgaClient.studies() + //.updateUsers(this.study.fqn, "@members", {users: [this.addUserId]}, {action: "ADD"}) + .updateAcl(this.addUserId, {action: "ADD"}, params) .then(res => { this.addUserId = ""; this.requestUpdate(); From eaa2f33febf514b84004f5d5c365b2726b56ea31 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 14 Jun 2024 23:59:45 +0200 Subject: [PATCH 051/177] wc - Minor fix, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/user-admin-grid.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 529b22e9c..57ce5c3a3 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -428,11 +428,10 @@ export default class UserAdminGrid extends LitElement { if (this._config.showToolbar) { return html ` + @userCreate="${e => this.renderRemoteTable(e)}"> `; } From 10c0badc1b4cc0b0cccf353a4046714805c2bdb8 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sat, 15 Jun 2024 17:06:13 +0200 Subject: [PATCH 052/177] wc - WiP Refactor and clean group #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 73 +++++++++++++++---- .../organization/admin/group-admin-grid.js | 61 +++++++++++----- 2 files changed, 102 insertions(+), 32 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js index 69e35a156..3ffab6374 100644 --- a/src/webcomponents/organization/admin/group-admin-browser.js +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -83,6 +83,25 @@ export default class GroupAdminBrowser extends LitElement { this.requestUpdate(); } + #prepareGroups(groups) { + const study = this.opencgaSession.study; + const project = this.opencgaSession.project; + + this._studies.push({ + projectId: project.id, + fqn: study.fqn, + name: study.alias, + }); + this._groups = groups.map(group => ({ + ...group, + fqn: study.fqn, + studyId: study.id, + projectId: project.id + })); + + + } + /* ----------------------------------------------------------------------------------------------------------------- LIT LIFE-CYCLE ----------------------------------------------------------------------------------------------------------------- */ @@ -114,7 +133,11 @@ export default class GroupAdminBrowser extends LitElement { this._studies = []; this.organization?.projects?.forEach(project => { project.studies?.forEach(study => { - this._studies.push({projectId: project.id, fqn: study.fqn, name: study.alias}); + this._studies.push({ + projectId: project.id, + fqn: study.fqn, + name: study.alias, + }); study.groups?.forEach(group => { const newGroup = { projectId: project.id, @@ -153,19 +176,41 @@ export default class GroupAdminBrowser extends LitElement { } studyObserver() { + /* + if (this.study) { + this._groups = []; + this._studies = [this.opencgaSession.study]; + this.study.groups?.forEach(group => { + const newGroup = { + studyId: this.study.id, + fqn: this.study.fqn, + group: group, + isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), + }; + this._groups.push(newGroup); + }); + } // Get all study groups - this._groups = []; - debugger - this._studies = [this.opencgaSession.study]; - this.study.groups?.forEach(group => { - const newGroup = { - studyId: this.study.id, - fqn: this.study.fqn, - group: group, - isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), - }; - this._groups.push(newGroup); - }); + */ + if (this.study) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .groups(this.study.fqn) + .then(response => { + const groups = response.responses[0].results; + this.#prepareGroups(groups); + }) + .catch(reason => { + this.study = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + this.#setLoading(false); + }); + } } studyIdObserver() { @@ -178,12 +223,10 @@ export default class GroupAdminBrowser extends LitElement { this.study = UtilsNew.objectClone(response.responses[0].results[0]); }) .catch(reason => { - this.study = {}; error = reason; console.error(reason); }) .finally(() => { - this._config = this.getDefaultConfig(); LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); this.#setLoading(false); }); diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index a5a4aab15..ac9e1cc2d 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -50,12 +50,12 @@ export default class GroupAdminGrid extends LitElement { studies: { type: Object, }, - active: { - type: Boolean, - }, config: { type: Object, }, + active: { + type: Boolean, + }, }; } @@ -71,6 +71,7 @@ export default class GroupAdminGrid extends LitElement { update(changedProperties) { if (changedProperties.has("opencgaSession") || + changedProperties.has("groups") || changedProperties.has("toolId") || changedProperties.has("studies") || changedProperties.has("config")) { @@ -91,7 +92,7 @@ export default class GroupAdminGrid extends LitElement { ...this.getDefaultConfig(), ...this.config, }; - +debugger this.gridCommons = new GridCommons(this.gridId, this, this._config); // Config for the grid toolbar @@ -139,14 +140,21 @@ export default class GroupAdminGrid extends LitElement { */ "edit-permissions": { label: "Edit Permissions", - icon: "fas fa-edit", + icon: "far fa-edit", + color: "text-success", modalId: `${this._prefix}UpdatePermissionsModal`, render: () => this.renderModalPermissionsUpdate(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + divider: true, + }, + "divider": { + isDivider: true, + divider: `
  • `, }, "delete": { label: "Delete", icon: "far fa-trash-alt ", + color: "text-danger", modalId: `${this._prefix}DeleteModal`, render: () => this.renderModalDelete(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", @@ -207,7 +215,7 @@ export default class GroupAdminGrid extends LitElement { this._columns = [ { title: "Group ID", - field: "group.id", + field: "id", visible: this.gridCommons.isColumnVisible("group.id") }, { @@ -221,11 +229,14 @@ export default class GroupAdminGrid extends LitElement { visible: this.gridCommons.isColumnVisible("projectId") }, { - title: "Creation Date", - field: "creationDate", - formatter: CatalogGridFormatter.dateFormatter, - sortable: true, - visible: this.gridCommons.isColumnVisible("creationDate") + title: "No.Users", + field: "users", + formatter: (value, row) => this.groupNoUsersFormatter(value, row), + }, + { + title: "Users IDs", + field: "users", + formatter: (value, row) => this.groupUsersFormatter(value, row), }, ]; @@ -241,17 +252,22 @@ export default class GroupAdminGrid extends LitElement { formatter: () => ` `; - */ - debugger + */ return html` { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + // this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "organizationInfo", this.organization, {}, error); + this.#setLoading(false); + }); + } } studyIdObserver() { @@ -102,9 +134,27 @@ export default class StudyAdminIva extends LitElement { } } + opencgaSessionObserver() { + this.study = this.opencgaSession.study; + this._config = this.getDefaultConfig(); + } + // --- RENDER METHOD --- render() { - return html` + if (this.opencgaSession.study && this.organization) { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { + return html` + +
    +

    We are sorry...

    +

    The page you are trying to access has restricted access.

    +

    Please refer to your system administrator.

    +
    + `; + } + + return html` `; + } } getDefaultConfig() { diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index 1cc1de523..227dbd23b 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -27,6 +27,8 @@ import "../../variant/operation/variant-secondary-sample-index-configure-operati import LitUtils from "../../commons/utils/lit-utils"; import "../../commons/layouts/custom-vertical-navbar.js"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; +import UtilsNew from "../../../core/utils-new"; export default class StudyAdmin extends LitElement { @@ -42,6 +44,9 @@ export default class StudyAdmin extends LitElement { static get properties() { return { + organizationId: { + type: String, + }, studyId: { type: String }, @@ -59,6 +64,10 @@ export default class StudyAdmin extends LitElement { } update(changedProperties) { + if (changedProperties.has("organizationId")) { + this.organizationIdObserver(); + } + if (changedProperties.has("studyId") || changedProperties.has("opencgaSession")) { this.studyIdObserver(); } @@ -70,6 +79,36 @@ export default class StudyAdmin extends LitElement { this.requestUpdate(); } + organizationIdObserver() { + // FIXME Vero: on creating a new group, for instance, + // the session is updated but the org id does not change. + // I need to get the organization info again to refresh the grid. + // For now, I will query org info only with property opencgaSession change. + // TO think about it. + // if (this.organizationId && this.opencgaSession) { + if (this.organizationId || this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + // FIXME Vero: To remove hardcoded organization when the following bug is fixed: + // https://app.clickup.com/t/36631768/TASK-5980 + // .info(this.organizationId) + .info("test") + .then(response => { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + // this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "organizationInfo", this.organization, {}, error); + this.#setLoading(false); + }); + } + } + studyIdObserver() { /* for (const project of this.opencgaSession?.projects) { @@ -104,346 +143,32 @@ export default class StudyAdmin extends LitElement { } } - // onSideNavClick(e) { - // e.preventDefault(); - // const tabId = e.currentTarget.dataset.id; - // - // // Set Active button - // $(".admin-side-navbar > ul > li", this).removeClass("active"); - // $(`.admin-side-navbar > ul > li > a[data-id=${tabId}]`, this)[0].parentElement.classList.add("active"); - // - // // Display the right content - // $(".admin-content-tab > div[role=tabpanel]", this).hide(); - // $("#" + this._prefix + tabId, this).show(); - // - // this.requestUpdate(); - // } - - // render() { - // return html` - // - // - //
    - //
    - // - // - //
    - // - //
    - // - //
    - //
    - //
    - // - //

    Component under construction

    - //

    (Coming Soon)

    - //
    ; - //
    - // - //
    - //

    Users And Groups

    - // - //
    - // - //
    - //

    Permissions

    - // - //
    - // - //
    - //

    Variable Sets

    - // - //
    - // - //
    - //

    Audit

    - // - //
    - // - //
    - //

    Configuration (Coming Soon)

    - // - //
    - // - //
    - //

    Sample

    - // - //
    - // - //
    - //

    Individual

    - // - //
    - // - //
    - //

    Family

    - // - //
    - // - //
    - //

    Cohort

    - // - //
    - //
    - //
    - //
    `; - // } - render() { const activeMenuItem = "UsersAndGroups"; - return html` - - - - `; + debugger + if (this.opencgaSession.study && this.organization) { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { + return html` + +
    +

    We are sorry...

    +

    The page you are trying to access has restricted access.

    +

    Please refer to your system administrator.

    +
    + `; + } + + return html ` + + + + `; + } } getDefaultConfig() { diff --git a/src/webcomponents/study/admin/variant/operations-admin.js b/src/webcomponents/study/admin/variant/operations-admin.js index d618e51ff..7a0fcdc31 100644 --- a/src/webcomponents/study/admin/variant/operations-admin.js +++ b/src/webcomponents/study/admin/variant/operations-admin.js @@ -22,6 +22,8 @@ import "../../../variant/operation/variant-annotation-index-operation.js"; import "../../../variant/operation/variant-secondary-annotation-index-operation.js"; import "../../../variant/operation/variant-secondary-sample-index-operation.js"; import "../../../commons/layouts/custom-vertical-navbar.js"; +import UtilsNew from "../../../../core/utils-new"; +import OpencgaCatalogUtils from "../../../../core/clients/opencga/opencga-catalog-utils"; export default class OperationsAdmin extends LitElement { @@ -37,6 +39,9 @@ export default class OperationsAdmin extends LitElement { static get properties() { return { + organizationId: { + type: String, + }, studyId: { type: String }, @@ -54,7 +59,16 @@ export default class OperationsAdmin extends LitElement { this._config = this.getDefaultConfig(); } + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + update(changedProperties) { + if (changedProperties.has("organizationId") || changedProperties.has("opencgaSession")) { + this.organizationIdObserver(); + } + if (changedProperties.has("studyId")) { this.studyIdObserver(); } @@ -64,9 +78,34 @@ export default class OperationsAdmin extends LitElement { super.update(changedProperties); } - #setLoading(value) { - this.isLoading = value; - this.requestUpdate(); + organizationIdObserver() { + // FIXME Vero: on creating a new group, for instance, + // the session is updated but the org id does not change. + // I need to get the organization info again to refresh the grid. + // For now, I will query org info only with property opencgaSession change. + // TO think about it. + // if (this.organizationId && this.opencgaSession) { + if (this.organizationId || this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.organization() + // FIXME Vero: To remove hardcoded organization when the following bug is fixed: + // https://app.clickup.com/t/36631768/TASK-5980 + // .info(this.organizationId) + .info("test") + .then(response => { + this.organization = UtilsNew.objectClone(response.responses[0].results[0]); + }) + .catch(reason => { + // this.organization = {}; + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "organizationInfo", this.organization, {}, error); + this.#setLoading(false); + }); + } } studyIdObserver() { @@ -96,15 +135,29 @@ export default class OperationsAdmin extends LitElement { render() { const activeMenuItem = "variant-annotation-index"; - return html` - - - - `; + if (this.opencgaSession.study && this.organization) { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { + return html` + +
    +

    We are sorry...

    +

    The page you are trying to access has restricted access.

    +

    Please refer to your system administrator.

    +
    + `; + } + return html` + + + + `; + } } getDefaultConfig() { From b1aa5c35fcb20ba14201013750dc4cf015ea5322 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 15:24:58 +0200 Subject: [PATCH 054/177] wc - Add organization id to admins #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/sites/iva/iva-app.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/sites/iva/iva-app.js b/src/sites/iva/iva-app.js index e1d53f24a..3200ac2a8 100644 --- a/src/sites/iva/iva-app.js +++ b/src/sites/iva/iva-app.js @@ -86,6 +86,7 @@ import "../../webcomponents/study/admin/study-admin.js"; import "../../webcomponents/study/admin/study-admin-iva.js"; import "../../webcomponents/study/admin/catalog-admin.js"; import "../../webcomponents/study/admin/variant/operations-admin.js"; +import "../../webcomponents/project/projects-admin.js"; import "../../webcomponents/user/user-login.js"; import "../../webcomponents/user/user-profile.js"; // import "../../webcomponents/user/user-password-reset.js"; @@ -236,6 +237,7 @@ class IvaApp extends LitElement { "operations-admin", "opencga-admin", "variants-admin", + // "projects-admin", // REST-API "rest-api", ]; @@ -1149,6 +1151,10 @@ class IvaApp extends LitElement { } onSessionUpdateRequest() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: "Refresh Session: Session Update Request", + message: "Session updated correctly", + }); this._createOpenCGASession(); } @@ -2018,7 +2024,8 @@ class IvaApp extends LitElement { + @studyUpdateRequest="${this.onStudyUpdateRequest}" + @sessionUpdateRequest="${this.onSessionUpdateRequest}"> ` : null} @@ -2033,7 +2040,7 @@ class IvaApp extends LitElement { ` : null} - ${this.config.enabledComponents["opencga-admin"] ? html` + ${this.config.enabledComponents["projects-admin"] ? html`
    @@ -2058,6 +2066,7 @@ class IvaApp extends LitElement { ${this.config.enabledComponents["study-admin-iva"] ? html`
    @@ -2068,9 +2077,10 @@ class IvaApp extends LitElement { ${this.config.enabledComponents["operations-admin"] ? html`
    + .organizationId="${this.opencgaSession?.user?.organization}" + .study="${this.opencgaSession.study}" + .opencgaSession="${this.opencgaSession}" + @studyUpdateRequest="${this.onStudyUpdateRequest}">
    ` : null} From 9973e05d24a093bc89b7e76b31ef503d5b3cb8ee Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 15:26:01 +0200 Subject: [PATCH 055/177] wc - Fix session update in projects/studies #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/project-admin-browser.js | 10 +- .../organization/admin/study-admin-grid.js | 71 ++--- src/webcomponents/project/project-create.js | 22 +- src/webcomponents/project/project-update.js | 8 +- src/webcomponents/project/projects-admin.js | 2 +- .../study/{ => admin}/study-create.js | 14 +- src/webcomponents/study/admin/study-update.js | 245 ++++++++++++++++++ 7 files changed, 304 insertions(+), 68 deletions(-) rename src/webcomponents/study/{ => admin}/study-create.js (94%) create mode 100644 src/webcomponents/study/admin/study-update.js diff --git a/src/webcomponents/organization/admin/project-admin-browser.js b/src/webcomponents/organization/admin/project-admin-browser.js index 2939a5570..5ea04312a 100644 --- a/src/webcomponents/organization/admin/project-admin-browser.js +++ b/src/webcomponents/organization/admin/project-admin-browser.js @@ -22,6 +22,7 @@ import ModalUtils from "../../commons/modal/modal-utils.js"; import "../../project/project-create.js"; import "../../project/project-update.js"; import "./study-admin-grid.js"; +import LitUtils from "../../commons/utils/lit-utils"; export default class ProjectAdminBrowser extends LitElement { @@ -93,8 +94,7 @@ export default class ProjectAdminBrowser extends LitElement { render: () => html ` + .opencgaSession="${this.opencgaSession}"> ` }, }; @@ -121,7 +121,6 @@ export default class ProjectAdminBrowser extends LitElement { // *** RENDER *** renderProjectUpdate() { - debugger return ModalUtils.create(this, `${this._prefix}UpdateProjectModal`, { display: { modalTitle: `Update Project: Project ${this.projectId} in organization ${this.organization.id}`, @@ -131,7 +130,6 @@ export default class ProjectAdminBrowser extends LitElement { }, // @projectUpdate="${e => this.onProjectUpdate(e, `${this._prefix}UpdateDetailsModal`)}" render: () => { - debugger return html` + .config="${this.toolbarConfig}"> `; } } renderProject(project) { - debugger return html `
    diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index ffc547f90..98b5c7d82 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -23,8 +23,8 @@ import UtilsNew from "../../../core/utils-new.js"; // import "./study-admin-create.js"; // import "./study-admin-update.js"; -import "../../study/study-create.js"; -// import "../../study/study-update.js"; +import "../../study/admin/study-create.js"; +import "../../study/admin/study-update.js"; export default class StudyAdminGrid extends LitElement { @@ -106,23 +106,23 @@ export default class StudyAdminGrid extends LitElement { display: { modalTitle: "Study Create", modalDraggable: true, - modalCyDataName: "modal-create", + modalCyDataName: "modal-study-create", modalSize: "modal-lg" // disabled: true, // disabledTooltip: "...", }, - // - // + // + // render: () => html ` + @studyCreate="${e => this.onStudyEvent(e)}"> `, }, @@ -136,14 +136,20 @@ export default class StudyAdminGrid extends LitElement { this.modals = { "edit-study": { label: "Edit Study", - icon: "fas fa-edit", + icon: "far fa-edit", + color: "text-success", modalId: `${this._prefix}UpdateStudyModal`, render: () => this.renderStudyUpdate(), permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", }, + "divider": { + isDivider: true, + divider: `
  • `, + }, "delete": { label: "Delete", icon: "far fa-trash-alt ", + color: "text-danger", // modalId: `${this._prefix}DeleteModal`, // render: () => this.renderModalPasswordReset(), permission: "disabled", @@ -185,7 +191,6 @@ export default class StudyAdminGrid extends LitElement { .studies(this.project.id, this.filters) .then(response => { result = response; - debugger return response; }) .then(() => { @@ -195,7 +200,6 @@ export default class StudyAdminGrid extends LitElement { }) .then(() => params.success(result)) .catch(error => { - debugger console.error(error); params.error(error); }); @@ -212,7 +216,6 @@ export default class StudyAdminGrid extends LitElement { } _getDefaultColumns() { - debugger this._columns = [ { title: "Study ID", @@ -263,10 +266,15 @@ export default class StudyAdminGrid extends LitElement { ${ Object.keys(this.modals).map(modalKey => { const modal = this.modals[modalKey]; - return ` + return modal.isDivider ? modal.divider : `
  • - - ${modal.label}... + +
    +
    +
    ${modal.label}...
    +
  • `; @@ -284,9 +292,9 @@ export default class StudyAdminGrid extends LitElement { this._columns = this.gridCommons.addColumnsFromExtensions(this._columns, this.COMPONENT_ID); return this._columns; } + // *** FORMATTERS *** groupsFormatter(groups, study) { - debugger const groupsBadges = groups.map(group => ` ${group.id} [${group.userIds.length}] @@ -302,15 +310,15 @@ export default class StudyAdminGrid extends LitElement { // *** EVENTS *** async onActionClick(e, value, row) { this.action = e.currentTarget.dataset.action; - this.userId = row.id; + this.studyId = row.id; this.requestUpdate(); await this.updateComplete; ModalUtils.show(this.modals[this.action]["modalId"]); } - onStudyUpdate(e, id) { + onStudyEvent(e, id) { + // Todo 20240616: find out a way to close modal onStudyCreate ModalUtils.close(id); - this.renderRemoteTable(); } // *** RENDER METHODS *** @@ -319,18 +327,20 @@ export default class StudyAdminGrid extends LitElement { display: { modalTitle: `Update Study: `, modalDraggable: true, - modalCyDataName: "modal-study-create", + modalCyDataName: "modal-study-update", modalSize: "modal-lg" }, - render: () => html` - { + debugger + return html` + - - `, + @studyUpdate="${e => this.onStudyEvent(e, `${this._prefix}UpdateStudyModal`)}"> + + `; + }, }); } @@ -341,8 +351,7 @@ export default class StudyAdminGrid extends LitElement { .query="${this.filters}" .opencgaSession="${this.opencgaSession}" .settings="${this.toolbarSetting}" - .config="${this.toolbarConfig}" - @studyCreate="${e => this.renderRemoteTable(e)}"> + .config="${this.toolbarConfig}"> `; } diff --git a/src/webcomponents/project/project-create.js b/src/webcomponents/project/project-create.js index 0a3715db5..bbd8ee9ae 100644 --- a/src/webcomponents/project/project-create.js +++ b/src/webcomponents/project/project-create.js @@ -53,7 +53,6 @@ export default class ProjectCreate extends LitElement { defaultLayout: "horizontal", buttonOkText: "Create" }; - this._config = this.getDefaultConfig(); } #initOriginalObject() { @@ -68,6 +67,7 @@ export default class ProjectCreate extends LitElement { } }; this._project = UtilsNew.objectClone(this.project); + this._config = this.getDefaultConfig(); } #setLoading(value) { @@ -130,28 +130,24 @@ export default class ProjectCreate extends LitElement { const params = { includeResult: true }; - let project, error; + let error; this.#setLoading(true); this.opencgaSession.opencgaClient.projects() .create(this.project, params) - .then(response => { + .then(() => { this.#initOriginalObject(); - this._config = this.getDefaultConfig(); - - project = response.responses[0].results[0]; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: "Project Create", message: "New project created correctly" }); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest"); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, error); }) .catch(reason => { - project = this.project; error = reason; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "projectCreate", project, {}, error); + // LitUtils.dispatchCustomEvent(this, "projectCreate", project, {}, error); this.#setLoading(false); }); } @@ -178,14 +174,6 @@ export default class ProjectCreate extends LitElement { sections: [ { elements: [ - { - type: "notification", - text: "Some changes have been done in the form. Not saved, changes will be lost", - display: { - visible: () => !UtilsNew.objectCompare(this.project, this._project), - notificationType: "warning", - }, - }, { name: "Project ID", field: "id", diff --git a/src/webcomponents/project/project-update.js b/src/webcomponents/project/project-update.js index 77ab55107..40acc37fa 100644 --- a/src/webcomponents/project/project-update.js +++ b/src/webcomponents/project/project-update.js @@ -170,7 +170,7 @@ export default class ProjectUpdate extends LitElement { const params = { includeResult: true }; - let project, error; + let error; this.#setLoading(true); this.opencgaSession.opencgaClient.projects() .update(this.project?.fqn, this.updateParams, params) @@ -182,21 +182,19 @@ export default class ProjectUpdate extends LitElement { title: "Project Update", message: "Project updated correctly" }); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest"); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", this._project, {}, error); }) .catch(reason => { - project = this.project; error = reason; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "projectUpdate", this.project, {}, error); + // LitUtils.dispatchCustomEvent(this, "projectUpdate", project, {}, error); this.#setLoading(false); }); } render() { - debugger if (this.isLoading) { return html``; } diff --git a/src/webcomponents/project/projects-admin.js b/src/webcomponents/project/projects-admin.js index 8f5554346..76f0b2c5a 100644 --- a/src/webcomponents/project/projects-admin.js +++ b/src/webcomponents/project/projects-admin.js @@ -20,7 +20,7 @@ import OpencgaCatalogUtils from "../../core/clients/opencga/opencga-catalog-util import {guardPage} from "../commons/html-utils.js"; import "../commons/tool-header.js"; import "../study/study-form.js"; -import "../study/study-create.js"; +import "../study/admin/study-create.js"; import "./project-create.js"; import "./project-update.js"; diff --git a/src/webcomponents/study/study-create.js b/src/webcomponents/study/admin/study-create.js similarity index 94% rename from src/webcomponents/study/study-create.js rename to src/webcomponents/study/admin/study-create.js index d2762a225..6ff3b7b48 100644 --- a/src/webcomponents/study/study-create.js +++ b/src/webcomponents/study/admin/study-create.js @@ -15,10 +15,10 @@ */ import {LitElement, html} from "lit"; -import LitUtils from "../commons/utils/lit-utils.js"; -import FormUtils from "../commons/forms/form-utils.js"; -import NotificationUtils from "../commons/utils/notification-utils.js"; -import Types from "../commons/types.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; +import FormUtils from "../../commons/forms/form-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import Types from "../../commons/types.js"; export default class StudyCreate extends LitElement { @@ -118,14 +118,15 @@ export default class StudyCreate extends LitElement { this.#setLoading(true); this.opencgaSession.opencgaClient.studies() .create(this.study, {project: this.project.fqn}) - .then(res => { + .then(() => { this.study = {}; this._config = this.getDefaultConfig(); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: "Study Create", message: "New study created correctly" }); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest"); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, error); + LitUtils.dispatchCustomEvent(this, "studyCreate", {}, {}, error); }) .catch(reason => { study = this.study; @@ -133,7 +134,6 @@ export default class StudyCreate extends LitElement { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(()=>{ - LitUtils.dispatchCustomEvent(this, "studyCreate", study, {}, error); this.#setLoading(false); }); } diff --git a/src/webcomponents/study/admin/study-update.js b/src/webcomponents/study/admin/study-update.js new file mode 100644 index 000000000..a471b007c --- /dev/null +++ b/src/webcomponents/study/admin/study-update.js @@ -0,0 +1,245 @@ +/** + * Copyright 2015-2023 OpenCB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {html, LitElement} from "lit"; +import FormUtils from "../../commons/forms/form-utils.js"; +import NotificationUtils from "../../commons/utils/notification-utils.js"; +import UtilsNew from "../../../core/utils-new.js"; +import Types from "../../commons/types.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; + +export default class StudyUpdate extends LitElement { + + constructor() { + super(); + + this.#init(); + } + + createRenderRoot() { + return this; + } + + static get properties() { + return { + studyId: { + type: String + }, + opencgaSession: { + type: Object + }, + displayConfig: { + type: Object + }, + }; + } + + #init() { + this.study = {}; // Original object + this._study = {}; // Updated object + this.updateParams = {}; + this.isLoading = false; + this.displayConfig = {}; + this.displayConfigDefault = { + style: "margin: 10px", + defaultLayout: "horizontal", + labelAlign: "right", + labelWidth: 3, + buttonOkText: "Update" + }; + this._config = this.getDefaultConfig(); + this.updatedParam = ""; + } + + #setLoading(value) { + this.isLoading = value; + this.requestUpdate(); + } + + #initConfigNotification() { + this._config.notification = { + title: "", + text: "Some changes have been done in the form. Not saved changes will be lost", + type: "notification", + display: { + visible: () => { + return UtilsNew.isNotEmpty(this.updatedParam); + }, + notificationType: "warning", + }, + }; + } + + #initOriginalObjects() { + this._study = UtilsNew.objectClone(this.study); + this.updatedFields = {}; + this.requestUpdate(); + } + + update(changedProperties) { + debugger + if (changedProperties.has("studyId")) { + this.studyIdObserver(); + } + if (changedProperties.has("displayConfig")) { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig + }; + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + super.update(changedProperties); + } + + studyIdObserver() { + if (this.studyId && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyId) + .then(response => { + this.study = UtilsNew.objectClone(response.responses[0].results[0]); + this.#initOriginalObjects(); + }) + .catch(reason => { + error = reason; + console.error(reason); + }) + .finally(() => { + this._config = this.getDefaultConfig(); + this.#setLoading(false); + }); + } + } + + onFieldChange(e, field) { + const param = field || e.detail.param; + this.updatedFields = FormUtils.getUpdatedFields( + this.study, + this.updatedFields, + param, + e.detail.value, + e.detail.action); + + this.requestUpdate(); + } + + onClear() { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Discard changes", + message: "Are you sure you want to discard the changes made?", + ok: () => { + this.#initOriginalObjects(); + // We need to dispatch a component clear event + LitUtils.dispatchCustomEvent(this, "studyClear", null, { + study: this.study, + }); + }, + }); + } + + onSubmit() { + const params = { + includeResult: true + }; + const updateParams = FormUtils.getUpdateParams(this._study, this.updatedFields, this.updateCustomisation); + + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .update(this.study?.fqn, updateParams, params) + .then(res => { + this._study = UtilsNew.objectClone(res.responses[0].results[0]); + this._config = this.getDefaultConfig(); + this.updatedFields = {}; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { + title: "Study Update", + message: "Study updated correctly" + }); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", this._study, {}, error); + LitUtils.dispatchCustomEvent(this, "studyUpdate", this._study, {}, error); + }) + .catch(reason => { + error = reason; + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); + }) + .finally(() => { + this.#setLoading(false); + }); + } + + render() { + if (this.isLoading) { + return html``; + } + return html` + + + `; + } + + getDefaultConfig() { + return Types.dataFormConfig({ + type: "form", + display: this.displayConfig || this.displayConfigDefault, + sections: [ + { + elements: [ + { + name: "Id", + field: "id", + type: "input-text", + required: true, + display: { + disabled: true, + } + }, + { + name: "Name", + field: "name", + type: "input-text", + display: { + placeholder: "Study name...", + } + }, + { + name: "Description", + field: "description", + type: "input-text", + display: { + rows: 3, + placeholder: "Study description...", + } + }, + ] + + }, + ], + }); + } + +} + +customElements.define("study-update", StudyUpdate); From 5c51199b36e831353a6e7889d2731ad582757651 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 15:27:03 +0200 Subject: [PATCH 056/177] wc - Fix tiny error #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/opencga-catalog-utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/clients/opencga/opencga-catalog-utils.js b/src/core/clients/opencga/opencga-catalog-utils.js index c3b60ea46..ee7c3f5dc 100644 --- a/src/core/clients/opencga/opencga-catalog-utils.js +++ b/src/core/clients/opencga/opencga-catalog-utils.js @@ -91,7 +91,7 @@ export default class OpencgaCatalogUtils { static isOrganizationAdminOwner(organization, userLogged) { if (!organization || !userLogged) { - console.error(`No valid parameters, study: ${organization}, user: ${userLogged}`); + console.error(`No valid parameters, organization: ${organization}, user: ${userLogged}`); return false; } // Check if user is Organization owner From 8a9f24eb342696860432bd5d5537a3cb147f4305 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 16:55:08 +0200 Subject: [PATCH 057/177] wc - Tiny clean, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/group-admin-grid.js | 21 +++++----- .../organization/admin/study-admin-grid.js | 19 +++++----- .../organization/admin/user-admin-grid.js | 38 ++++++++++++------- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index ac9e1cc2d..a1679a5d4 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -124,8 +124,8 @@ debugger }; this.permissions = { - "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", - "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) ? "" : "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) ? "" : "disabled", }; this.modals = { @@ -144,20 +144,16 @@ debugger color: "text-success", modalId: `${this._prefix}UpdatePermissionsModal`, render: () => this.renderModalPermissionsUpdate(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + permission: this.permissions["study"], divider: true, }, - "divider": { - isDivider: true, - divider: `
  • `, - }, "delete": { label: "Delete", icon: "far fa-trash-alt ", color: "text-danger", modalId: `${this._prefix}DeleteModal`, render: () => this.renderModalDelete(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + permission: this.permissions["study"], }, }; @@ -262,7 +258,7 @@ debugger return modal.isDivider ? modal.divider : `
  • @@ -320,7 +316,7 @@ debugger */ async onActionClick(e, value, row) { this.action = e.currentTarget.dataset.action; - this.group = row.group; + this.groupId = row.id; this.studyFqn = row.fqn; this.requestUpdate(); await this.updateComplete; @@ -336,14 +332,15 @@ debugger renderModalPermissionsUpdate() { return ModalUtils.create(this, `${this._prefix}UpdatePermissionsModal`, { display: { - modalTitle: `Permissions Update: Group ${this.group?.id} in Study ${this.studyFqn}`, + modalTitle: `Permissions Update: Group ${this.groupId} in Study ${this.studyFqn}`, modalDraggable: true, modalCyDataName: "modal-update", modalSize: "modal-lg" }, render: active => html` OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", - "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) ? "" : "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) ? "" : "disabled", }; this.modals = { @@ -140,11 +143,8 @@ export default class StudyAdminGrid extends LitElement { color: "text-success", modalId: `${this._prefix}UpdateStudyModal`, render: () => this.renderStudyUpdate(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", - }, - "divider": { - isDivider: true, - divider: `
  • `, + permission: this.permissions["organization"](), + divider: true, }, "delete": { label: "Delete", @@ -152,7 +152,7 @@ export default class StudyAdminGrid extends LitElement { color: "text-danger", // modalId: `${this._prefix}DeleteModal`, // render: () => this.renderModalPasswordReset(), - permission: "disabled", + permission: "disabled", // Caution: Not possible to delete studies for now. }, }; } @@ -269,7 +269,7 @@ export default class StudyAdminGrid extends LitElement { return modal.isDivider ? modal.divider : `
  • @@ -277,6 +277,7 @@ export default class StudyAdminGrid extends LitElement {
  • + ${modal.divider ? `
  • ` : ""} `; }).join("") } diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 57ce5c3a3..d146c99d1 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -51,9 +51,6 @@ export default class UserAdminGrid extends LitElement { organization: { type: Object, }, - studyId: { - type: String, - }, users: { type: Array }, @@ -130,17 +127,19 @@ export default class UserAdminGrid extends LitElement { }; this.permissions = { - "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || "disabled", - "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + "organization": () => OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) ? "" : "disabled", + "study": () => OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) ? "" : "disabled", }; this.modals = { "edit-details": { label: "Edit Details", - icon: "fas fa-edit", + icon: "far fa-edit", + color: "text-success", modalId: `${this._prefix}UpdateDetailsModal`, render: () => this.renderModalDetailsUpdate(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + permission: this.permissions["organization"](), + divider: true, }, // ToDo 20240529 Vero: Nacho/Pedro to discuss: // - Organization admin/owner can change usr pwd without entering current pwd @@ -155,24 +154,29 @@ export default class UserAdminGrid extends LitElement { */ "reset-password": { label: "Reset Password", - icon: "fas fa-edit", + icon: "fas fa-key", + color: "#646c70", modalId: `${this._prefix}ResetPasswordModal`, render: () => this.renderModalPasswordReset(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + permission: this.permissions["organization"](), + divider: true, }, "change-status": { label: "Change status", - icon: "fas fa-edit", + icon: "far fa-user", + color: "#646c70", modalId: `${this._prefix}ChangeStatusModal`, render: () => this.renderModalStatusUpdate(), - permission: OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id) || "disabled", + permission: this.permissions["organization"](), + divider: true, }, "delete": { label: "Delete", icon: "far fa-trash-alt ", + color: "text-danger", // modalId: `${this._prefix}DeleteModal`, // render: () => this.renderModalPasswordReset(), - permission: "disabled", + permission: "disabled", // CAUTION: Not possible to delete users for now }, }; } @@ -303,10 +307,16 @@ export default class UserAdminGrid extends LitElement { const modal = this.modals[modalKey]; return `
  • - - ${modal.label}... + +
    +
    +
    ${modal.label}...
    +
  • + ${modal.divider ? `
  • ` : ""} `; }).join("") } From 1ef111213e0816193a800ad051593b56c1874413 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 16:56:00 +0200 Subject: [PATCH 058/177] wc - Fix property, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-details-update.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-details-update.js b/src/webcomponents/organization/admin/user-admin-details-update.js index 699cd8276..99f85ead1 100644 --- a/src/webcomponents/organization/admin/user-admin-details-update.js +++ b/src/webcomponents/organization/admin/user-admin-details-update.js @@ -176,13 +176,13 @@ export default class UserAdminDetailsUpdate extends LitElement { title: `User Details Update`, message: `User ${this.userId} updated correctly`, }); + LitUtils.dispatchCustomEvent(this, "userUpdate", this.user, {}, error); }) .catch(reason => { error = reason; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { - LitUtils.dispatchCustomEvent(this, "userUpdate", this._user, {}, error); this.#setLoading(false); }); @@ -193,7 +193,7 @@ export default class UserAdminDetailsUpdate extends LitElement { @@ -245,7 +245,7 @@ export default class UserAdminDetailsUpdate extends LitElement { field: "account.expirationDate", type: "input-date", display: { - render: date => moment(date, "YYYYMMDDHHmmss").format("DD/MM/YYYY") + format: date => UtilsNew.dateFormatter(date) }, }, ], From c84269e9626fec2ff1c34f13cd1e6e48d11479f1 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 16:57:04 +0200 Subject: [PATCH 059/177] wc - Add organization property, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/project-admin-browser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/webcomponents/organization/admin/project-admin-browser.js b/src/webcomponents/organization/admin/project-admin-browser.js index 5ea04312a..5eadcd6d3 100644 --- a/src/webcomponents/organization/admin/project-admin-browser.js +++ b/src/webcomponents/organization/admin/project-admin-browser.js @@ -206,6 +206,7 @@ export default class ProjectAdminBrowser extends LitElement { From 445e72bd9b1c13b9738ba3638cbb43409c70e05e Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 16:57:50 +0200 Subject: [PATCH 060/177] wc - Clean code, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/user-admin-browser.js | 81 ------------------- 1 file changed, 81 deletions(-) diff --git a/src/webcomponents/organization/admin/user-admin-browser.js b/src/webcomponents/organization/admin/user-admin-browser.js index 94fbe9efd..067ff3c18 100644 --- a/src/webcomponents/organization/admin/user-admin-browser.js +++ b/src/webcomponents/organization/admin/user-admin-browser.js @@ -41,9 +41,6 @@ export default class UserAdminBrowser extends LitElement { study: { type: Object, }, - organizationId: { - type: String, - }, organization: { type: Object, }, @@ -69,61 +66,6 @@ export default class UserAdminBrowser extends LitElement { this.requestUpdate(); } - #getUsers(isSingleStudy) { - // FIXME: Big refactor when BUG 2 fixed. - if (isSingleStudy) { - // TODO - } else { - // FIXME 20240321 Vero: - // ********************************************************************************* - // [ BUG 1 ] - // The method info from the ws Organizations is returning an empty array of projects. - // The following bug has been created: - // https://app.clickup.com/t/36631768/TASK-5923. - // Meanwhile, I use the list of projects from opencgaSession. - // ********************************************************************************* - // [ BUG 2 ] - // The list of organization users: - // - Should use the endpoint: admin/users/search - // but not allowed for owner/admin organization user. - // - For listing in the user-grid a new user that still hasn't joined a group in study, - // we temporarily retrieve the users in study groups and fake a new user created. - // ********************************************************************************* - // TODO: to remove and to use enpoint admin/users/search when [ BUG 2 ] fixed - const users = this.opencgaSession?.projects - .map(project => project.studies).flat() - .map(study => study.groups).flat() - .map(group => group.userIds).flat() - .filter(user => user !=="opencga"); - // Unique users - this.allUsersIds = UtilsNew.sort([...new Set(users)]); - - let error; - this.#setLoading(true); - const params = { - organization: this.organization.id, - }; - // TODO: not needed when [ BUG 2 ] fixed - // this.opencgaSession.opencgaClient.admin() - // .searchUsers({organization: "test", limit: 25}) - this.opencgaSession.opencgaClient.users() - .info(this.allUsersIds.join(","), params) - .then(response => { - // this.users = UtilsNew.objectClone(response.responses[0]?.results); - // TODO: To remove when [ BUG 2 ] fixed - this.users.push(...UtilsNew.objectClone(response.responses[0]?.results)); - }) - .catch(reason => { - error = reason; - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, reason); - }) - .finally(() => { - LitUtils.dispatchCustomEvent(this, "usersInfo", this.component, {}, error); - this.#setLoading(false); - }); - } - } - update(changedProperties) { if (changedProperties.has("settings")) { this.settingsObserver(); @@ -162,29 +104,6 @@ export default class UserAdminBrowser extends LitElement { } } - organizationIdObserver() { - if (this.organizationId && this.opencgaSession) { - let error; - this.#setLoading(true); - this.opencgaSession.opencgaClient.organization() - .info(this.organizationId) - .then(response => { - this.organization = UtilsNew.objectClone(response.responses[0].results[0]); - }) - .catch(reason => { - this.organization = {}; - error = reason; - console.error(reason); - }) - .finally(() => { - this._config = this.getDefaultConfig(); - LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); - this.#setLoading(false); - }); - - } - } - renderFilterGraphics() { if (this._config.showGraphicFilters) { return html ` From b009837570c785576fbe748b7d786bae0ad0f98b Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 18:09:22 +0200 Subject: [PATCH 061/177] wc - Fix permissions study admin in Admin, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../study/admin/study-admin-iva.js | 2 +- src/webcomponents/study/admin/study-admin.js | 24 ++++++++++--------- .../study/admin/variant/operations-admin.js | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/webcomponents/study/admin/study-admin-iva.js b/src/webcomponents/study/admin/study-admin-iva.js index 6934759a0..5742696f6 100644 --- a/src/webcomponents/study/admin/study-admin-iva.js +++ b/src/webcomponents/study/admin/study-admin-iva.js @@ -142,7 +142,7 @@ export default class StudyAdminIva extends LitElement { // --- RENDER METHOD --- render() { if (this.opencgaSession.study && this.organization) { - if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) && !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { return html` diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index 227dbd23b..03ad3fdc2 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -147,7 +147,7 @@ export default class StudyAdmin extends LitElement { const activeMenuItem = "UsersAndGroups"; debugger if (this.opencgaSession.study && this.organization) { - if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) && !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { return html` @@ -162,10 +162,10 @@ export default class StudyAdmin extends LitElement { return html ` + .study="${this.opencgaSession.study}" + .opencgaSession="${this.opencgaSession}" + .config="${this._config}" + .activeMenuItem="${activeMenuItem}"> `; } @@ -225,12 +225,14 @@ export default class StudyAdmin extends LitElement { name: "Groups", icon: "fas fa-vial", visibility: "private", - render: (opencgaSession, organization) => html` - - - `, + render: (opencgaSession, study) => { + return html` + + + `; + } }, { id: "Permissions", diff --git a/src/webcomponents/study/admin/variant/operations-admin.js b/src/webcomponents/study/admin/variant/operations-admin.js index 7a0fcdc31..50a7c8c80 100644 --- a/src/webcomponents/study/admin/variant/operations-admin.js +++ b/src/webcomponents/study/admin/variant/operations-admin.js @@ -136,7 +136,7 @@ export default class OperationsAdmin extends LitElement { render() { const activeMenuItem = "variant-annotation-index"; if (this.opencgaSession.study && this.organization) { - if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) || + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) && !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { return html` Date: Sun, 16 Jun 2024 19:16:56 +0200 Subject: [PATCH 062/177] wc - Fix icon, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/study/admin/study-admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index 03ad3fdc2..b4219f507 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -223,7 +223,7 @@ export default class StudyAdmin extends LitElement { { id: "groups", name: "Groups", - icon: "fas fa-vial", + icon: "fas fa-user-friends", visibility: "private", render: (opencgaSession, study) => { return html` From 843127b079043b706cce28cb20f81caf9c4ff998 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Sun, 16 Jun 2024 19:17:34 +0200 Subject: [PATCH 063/177] wc - Fix permissions group, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/group-admin-browser.js | 94 ++++++++----------- .../organization/admin/group-admin-grid.js | 57 ++++++----- 2 files changed, 68 insertions(+), 83 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-browser.js b/src/webcomponents/organization/admin/group-admin-browser.js index 3ffab6374..2232f0753 100644 --- a/src/webcomponents/organization/admin/group-admin-browser.js +++ b/src/webcomponents/organization/admin/group-admin-browser.js @@ -72,8 +72,8 @@ export default class GroupAdminBrowser extends LitElement { #init() { this.COMPONENT_ID = "groups-admin-browser"; this._groups = []; - this._study = {}; this._studies = []; + this._study = {}; this._config = this.getDefaultConfig(); this.isLoading = false; } @@ -83,41 +83,56 @@ export default class GroupAdminBrowser extends LitElement { this.requestUpdate(); } - #prepareGroups(groups) { - const study = this.opencgaSession.study; - const project = this.opencgaSession.project; + #prepareGroups(groups, project, study) { + /* + if (this.study) { + this._groups = []; + this._studies = [this.opencgaSession.study]; + this.study.groups?.forEach(group => { + const newGroup = { + studyId: this.study.id, + fqn: this.study.fqn, + group: group, + isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), + }; + this._groups.push(newGroup); + }); + } + */ + // Get all study groups + const p = project || this.opencgaSession.project; + const s = study || this.opencgaSession.study; this._studies.push({ - projectId: project.id, - fqn: study.fqn, - name: study.alias, + projectId: p.id, + fqn: s.fqn, + name: s.alias, }); this._groups = groups.map(group => ({ ...group, - fqn: study.fqn, - studyId: study.id, - projectId: project.id + fqn: s.fqn, + studyId: s.id, + projectId: p.id, + isProtected: !!(group.id === "@admins" || group.id === "@members"), })); - - } /* ----------------------------------------------------------------------------------------------------------------- LIT LIFE-CYCLE ----------------------------------------------------------------------------------------------------------------- */ update(changedProperties) { - if (changedProperties.has("organization")) { - this.organizationObserver(); - } if (changedProperties.has("organizationId")) { this.organizationIdObserver(); } - if (changedProperties.has("study")) { - this.studyObserver(); + if (changedProperties.has("organization")) { + this.organizationObserver(); } if (changedProperties.has("studyId")) { this.studyIdObserver(); } + if (changedProperties.has("study")) { + this.studyObserver(); + } if (changedProperties.has("settings")) { this.settingsObserver(); } @@ -129,27 +144,15 @@ export default class GroupAdminBrowser extends LitElement { ----------------------------------------------------------------------------------------------------------------- */ organizationObserver() { // Get all organization groups - this._groups = []; - this._studies = []; - this.organization?.projects?.forEach(project => { - project.studies?.forEach(study => { - this._studies.push({ - projectId: project.id, - fqn: study.fqn, - name: study.alias, - }); - study.groups?.forEach(group => { - const newGroup = { - projectId: project.id, - studyId: study.id, - fqn: study.fqn, - group: group, - isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), - }; - this._groups.push(newGroup); + if (this.organization) { + this._groups = []; + this._studies = []; + this.organization?.projects?.forEach(project => { + project.studies?.forEach(study => { + this.#prepareGroups(study.groups, project, study); }); }); - }); + } } organizationIdObserver() { @@ -168,7 +171,7 @@ export default class GroupAdminBrowser extends LitElement { }) .finally(() => { this._config = this.getDefaultConfig(); - LitUtils.dispatchCustomEvent(this, "organizationChange", this.organization, {}, error); + LitUtils.dispatchCustomEvent(this, "organizationInfo", this.organization, {}, error); this.#setLoading(false); }); @@ -176,22 +179,6 @@ export default class GroupAdminBrowser extends LitElement { } studyObserver() { - /* - if (this.study) { - this._groups = []; - this._studies = [this.opencgaSession.study]; - this.study.groups?.forEach(group => { - const newGroup = { - studyId: this.study.id, - fqn: this.study.fqn, - group: group, - isGroupProtected: !!(group.id === "@admins" || group.id === "@members"), - }; - this._groups.push(newGroup); - }); - } - // Get all study groups - */ if (this.study) { let error; this.#setLoading(true); @@ -202,7 +189,6 @@ export default class GroupAdminBrowser extends LitElement { this.#prepareGroups(groups); }) .catch(reason => { - this.study = {}; error = reason; console.error(reason); }) diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index a1679a5d4..b7cde2a48 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -144,7 +144,7 @@ debugger color: "text-success", modalId: `${this._prefix}UpdatePermissionsModal`, render: () => this.renderModalPermissionsUpdate(), - permission: this.permissions["study"], + permission: this.permissions["study"](), divider: true, }, "delete": { @@ -153,7 +153,7 @@ debugger color: "text-danger", modalId: `${this._prefix}DeleteModal`, render: () => this.renderModalDelete(), - permission: this.permissions["study"], + permission: this.permissions["study"](), }, }; @@ -212,7 +212,8 @@ debugger { title: "Group ID", field: "id", - visible: this.gridCommons.isColumnVisible("group.id") + visible: this.gridCommons.isColumnVisible("group.id"), + formatter: (value, row) => this.groupIdFormatter(value, row), }, { title: "Study ID", @@ -245,17 +246,21 @@ debugger id: "actions", title: "Actions", field: "actions", - formatter: () => ` + formatter: (value, row) => ` `, - align: "center", events: { "click a": this.onActionClick.bind(this), }, diff --git a/src/webcomponents/organization/admin/group-admin-grid.js b/src/webcomponents/organization/admin/group-admin-grid.js index 090143cbb..bb2d1e575 100644 --- a/src/webcomponents/organization/admin/group-admin-grid.js +++ b/src/webcomponents/organization/admin/group-admin-grid.js @@ -238,6 +238,7 @@ export default class GroupAdminGrid extends LitElement { id: "actions", title: "Actions", field: "actions", + align: "center", formatter: (value, row) => ` diff --git a/src/webcomponents/project/project-create.js b/src/webcomponents/project/project-create.js index 24ca20712..d2983fbc0 100644 --- a/src/webcomponents/project/project-create.js +++ b/src/webcomponents/project/project-create.js @@ -16,10 +16,8 @@ import {LitElement, html} from "lit"; import LitUtils from "../commons/utils/lit-utils.js"; -import FormUtils from "../commons/forms/form-utils.js"; import NotificationUtils from "../commons/utils/notification-utils.js"; import UtilsNew from "../../core/utils-new.js"; -import Types from "../commons/types.js"; export default class ProjectCreate extends LitElement { @@ -63,11 +61,10 @@ export default class ProjectCreate extends LitElement { }, cellbase: { url: "https://ws.zettagenomics.com/cellbase", - version: "v5.1" + version: "v5.8" } }; this._project = UtilsNew.objectClone(this.project); - this._config = this.getDefaultConfig(); } #setLoading(value) { @@ -86,54 +83,31 @@ export default class ProjectCreate extends LitElement { super.update(changedProperties); } - onFieldChange(e, field) { - const param = field || e.detail.param; - switch (param) { - case "id": - case "name": - case "description": - case "organism.scientificName": - case "organism.assembly": - case "cellbase": - this.project = { - ...FormUtils.createObject( - this.project, - param, - e.detail.value - ) - }; - } + onFieldChange(e) { + this._project = {...e.detail.data}; // force to refresh the object-list this.requestUpdate(); } onClear() { - const resetForm = () => { - this.#initOriginalObject(); - this._config = this.getDefaultConfig(); - this.requestUpdate(); - }; - if (!this.displayConfig?.modal) { - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { - title: "Clear project", - message: "Are you sure to clear?", - ok: () => { - resetForm(); - }, - }); - } else { - LitUtils.dispatchCustomEvent(this, "clearProject"); - resetForm(); - } + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_CONFIRMATION, { + title: "Clear project", + message: "Are you sure to clear?", + ok: () => { + this.#initOriginalObject(); + this._config = this.getDefaultConfig(); + this.requestUpdate(); + }, + }); } onSubmit() { const params = { - includeResult: true + includeResult: true, }; let error; this.#setLoading(true); this.opencgaSession.opencgaClient.projects() - .create(this.project, params) + .create(this._project, params) .then(() => { this.#initOriginalObject(); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { @@ -141,13 +115,13 @@ export default class ProjectCreate extends LitElement { message: "New project created correctly" }); LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", {}, {}, error); + // LitUtils.dispatchCustomEvent(this, "projectCreate", project, {}, error); }) .catch(reason => { error = reason; NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); }) .finally(() => { - // LitUtils.dispatchCustomEvent(this, "projectCreate", project, {}, error); this.#setLoading(false); }); } @@ -159,7 +133,7 @@ export default class ProjectCreate extends LitElement { return html` Date: Fri, 12 Jul 2024 18:54:23 +0200 Subject: [PATCH 137/177] wc - Small fixes. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/study-admin-grid.js | 2 +- .../organization/admin/study-users-manage.js | 5 ++++- .../organization/admin/user-admin-create.js | 9 --------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index 40a7f5079..7ba2fb242 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -370,7 +370,7 @@ export default class StudyAdminGrid extends LitElement { diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index b9138f6fa..16574a911 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -170,7 +170,10 @@ export default class StudyUsersManage extends LitElement { .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `User in Group Update`, - message: `${update.userId} ${update.isChecked ? "ADDED" : "REMOVED"} to ${update.groupId} in study ${this.study.id} correctly`, + message: ` + ${update.userId} ${update.isChecked ? "ADDED to" : "REMOVED from"} + ${update.groupId} in study ${this.study.id} correctly. + `, }); }) .catch(reason => { diff --git a/src/webcomponents/organization/admin/user-admin-create.js b/src/webcomponents/organization/admin/user-admin-create.js index 180bc80b2..1378b1e5d 100644 --- a/src/webcomponents/organization/admin/user-admin-create.js +++ b/src/webcomponents/organization/admin/user-admin-create.js @@ -87,15 +87,6 @@ export default class UserAdminCreate extends LitElement { onFieldChange(e, field) { this._user = {...e.detail.data}; // force to refresh the object-list - debugger - - // const param = field || e.detail.param; - // // 1. Update user id - // if (param === "id") { - // // TODO 20240325 Vero: verify user id does not exist - // this.user.id = e.detail.data.id; - // } - // 2. Update the list of studies this.requestUpdate(); } From ead06fd1c64b11111bd5d0621f218b4998e85ad2 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Tue, 16 Jul 2024 13:49:47 +0200 Subject: [PATCH 138/177] wc - Add group create to studies grid. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/group-admin-create.js | 33 +++++++++++++++++-- .../organization/admin/study-admin-grid.js | 33 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index aa19404ca..baf259bcd 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -17,6 +17,7 @@ import {LitElement, html} from "lit"; import LitUtils from "../../commons/utils/lit-utils.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; +import UtilsNew from "../../../core/utils-new"; export default class GroupAdminCreate extends LitElement { @@ -32,6 +33,9 @@ export default class GroupAdminCreate extends LitElement { static get properties() { return { + studyFqn: { + type: String, + }, studies: { type: Array, }, @@ -89,6 +93,10 @@ export default class GroupAdminCreate extends LitElement { } update(changedProperties) { + if (changedProperties.has("studyFqn") || + changedProperties.has("opencgaSession")) { + this.studyFqnObserver(); + } if (changedProperties.has("studies") || changedProperties.has("opencgaSession")) { this.#initOriginalObjects(); @@ -103,6 +111,27 @@ export default class GroupAdminCreate extends LitElement { super.update(changedProperties); } + studyFqnObserver() { + if (this.studyFqn && this.opencgaSession) { + let error; + this.#setLoading(true); + this.opencgaSession.opencgaClient.studies() + .info(this.studyFqn) + .then(response => { + this.study = UtilsNew.objectClone(response.responses[0].results[0]); + this.studies = [this.study]; + }) + .catch(reason => { + error = reason; + console.error(reason); + }) + .finally(() => { + LitUtils.dispatchCustomEvent(this, "studyChange", this.study, {}, error); + this.#setLoading(false); + }); + } + } + onFieldChange(e, field) { const param = field || e.detail.param; // 1. Update group id @@ -135,7 +164,7 @@ export default class GroupAdminCreate extends LitElement { action: "ADD", }; this.#setLoading(true); - const groupPromises = this.group.listStudies + const groupPromises = (this.group.listStudies || []) .map(study => { let error; return this.opencgaSession.opencgaClient.studies() @@ -143,7 +172,7 @@ export default class GroupAdminCreate extends LitElement { .then(() => { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `Group Create`, - message: `Group ${this.group.id} in study ${study} CREATED successfully`, + message: `Group ${this.group.id} in study ${study.fqn} CREATED successfully`, }); }) .catch(reason => { diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index 7ba2fb242..c216ba694 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -142,6 +142,14 @@ export default class StudyAdminGrid extends LitElement { permission: this.permissions["organization"](), divider: true, }, + "create-group": { + label: "Create Group", + icon: "fas fa-edit", + modalId: `${this._prefix}CreateGroupModal`, + render: () => this.renderGroupCreate(), + permission: this.permissions["organization"](), + divider: false, + }, "add-users": { label: "Manage Users in Study", icon: "fas fa-user-plus", @@ -226,6 +234,11 @@ export default class StudyAdminGrid extends LitElement { field: "id", visible: this.gridCommons.isColumnVisible("id") }, + { + title: "Study Fqn", + field: "fqn", + visible: this.gridCommons.isColumnVisible("fqn") + }, { title: "Name", field: "name", @@ -328,6 +341,7 @@ export default class StudyAdminGrid extends LitElement { async onActionClick(e, value, row) { this.action = e.currentTarget.dataset.action; this.studyId = row.id; + this.studyFqn = row.fqn; this.requestUpdate(); await this.updateComplete; ModalUtils.show(this.modals[this.action]["modalId"]); @@ -339,6 +353,25 @@ export default class StudyAdminGrid extends LitElement { } // *** RENDER METHODS *** + renderGroupCreate() { + return ModalUtils.create(this, `${this._prefix}CreateGroupModal`, { + display: { + modalTitle: `Group Create`, + modalDraggable: true, + modalCyDataName: "modal-group-create", + modalSize: "modal-lg" + }, + render: () => html` + + + `, + }); + } + renderStudyUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateStudyModal`, { display: { From 3d418691b3f9d9dcb37b2bdb2162bbf0d3dc408a Mon Sep 17 00:00:00 2001 From: gpveronica Date: Tue, 16 Jul 2024 13:50:12 +0200 Subject: [PATCH 139/177] wc - Fix notification form updated and tiny clean. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/organization-admin-update.js | 42 +++++++++++-------- src/webcomponents/study/admin/study-update.js | 5 ++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/webcomponents/organization/admin/organization-admin-update.js b/src/webcomponents/organization/admin/organization-admin-update.js index 1c6aea56c..726cbe5b8 100644 --- a/src/webcomponents/organization/admin/organization-admin-update.js +++ b/src/webcomponents/organization/admin/organization-admin-update.js @@ -57,8 +57,8 @@ export default class OrganizationAdminUpdate extends LitElement { style: "margin: 10px", defaultLayout: "horizontal", labelAlign: "right", - labelWidth: 3, - buttonOkText: "Update" + buttonOkText: "Update", + buttonOkDisabled: true, }; this._config = this.getDefaultConfig(); } @@ -85,6 +85,7 @@ export default class OrganizationAdminUpdate extends LitElement { #initOriginalObjects() { this._organization = UtilsNew.objectClone(this.organization); this.updatedFields = {}; + this.displayConfigObserver(); } update(changedProperties) { @@ -94,21 +95,25 @@ export default class OrganizationAdminUpdate extends LitElement { } if (changedProperties.has("displayConfig")) { - this.displayConfig = { - ...this.displayConfigDefault, - ...this.displayConfig, - }; - this._config = this.getDefaultConfig(); - if (!this._config?.notification) { - this.#initConfigNotification(); - } + this.displayConfigObserver(); } super.update(changedProperties); } - onFieldChange(e) { - const param = e.detail.param; + displayConfigObserver() { + this.displayConfig = { + ...this.displayConfigDefault, + ...this.displayConfig, + }; + this._config = this.getDefaultConfig(); + if (!this._config?.notification) { + this.#initConfigNotification(); + } + } + + onFieldChange(e, field) { + const param = field || e.detail.param; this.updatedFields = FormUtils.getUpdatedFields( this.organization, this.updatedFields, @@ -116,6 +121,8 @@ export default class OrganizationAdminUpdate extends LitElement { e.detail.value, e.detail.action); + this._config.display.buttonOkDisabled = UtilsNew.isEmpty(this.updatedFields); + this._config = {...this._config}; this.requestUpdate(); } @@ -124,8 +131,7 @@ export default class OrganizationAdminUpdate extends LitElement { title: "Discard changes", message: "Are you sure you want to discard the changes made?", ok: () => { - this.initOriginalObjects(); - this.requestUpdate(); + this.#initOriginalObjects(); // We need to dispatch a component clear event LitUtils.dispatchCustomEvent(this, "organizationClear", null, { organization: this._organization, @@ -172,6 +178,10 @@ export default class OrganizationAdminUpdate extends LitElement { } render() { + if (this.isLoading) { + return html``; + } + return html` `; } + return html` Date: Tue, 16 Jul 2024 14:09:59 +0200 Subject: [PATCH 140/177] wc - Fix authorization for study admin in organization operations. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../study/admin/variant/operations-admin.js | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/webcomponents/study/admin/variant/operations-admin.js b/src/webcomponents/study/admin/variant/operations-admin.js index 99f3d14a6..e4591aad8 100644 --- a/src/webcomponents/study/admin/variant/operations-admin.js +++ b/src/webcomponents/study/admin/variant/operations-admin.js @@ -182,24 +182,46 @@ export default class OperationsAdmin extends LitElement { name: "Variant Annotation Index", icon: "fas fa-key", visibility: "private", - render: opencgaSession => html` - - - `, + render: opencgaSession => { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, opencgaSession.user.id)) { + return html` +
    +

    Restricted access

    +

    The page you are trying to access has restricted access.

    +

    Please refer to your system administrator.

    +
    + `; + } + return html` + + + `; + } }, { id: "variant-secondary-annotation-index", name: "Variant Secondary Annotation Index", icon: "fas fa-key", visibility: "private", - render: opencgaSession => html` - - - `, + render: opencgaSession => { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, opencgaSession.user.id)) { + return html` +
    +

    Restricted access

    +

    The page you are trying to access has restricted access.

    +

    Please refer to your system administrator.

    +
    + `; + } + return html` + + + `; + } }, ], }, From 49c820673515fae332b11af3111bdac40ebac980 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 24 Jul 2024 13:30:03 +0200 Subject: [PATCH 141/177] wc - WiP Update component to new requirement. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-admin-grid.js | 13 +- .../organization/admin/study-users-manage.js | 197 +++++++----------- 2 files changed, 86 insertions(+), 124 deletions(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index c216ba694..5452c013d 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -121,7 +121,7 @@ export default class StudyAdminGrid extends LitElement { `, @@ -342,6 +342,7 @@ export default class StudyAdminGrid extends LitElement { this.action = e.currentTarget.dataset.action; this.studyId = row.id; this.studyFqn = row.fqn; + this.studyGroups = row.groups; this.requestUpdate(); await this.updateComplete; ModalUtils.show(this.modals[this.action]["modalId"]); @@ -365,7 +366,7 @@ export default class StudyAdminGrid extends LitElement { `, @@ -383,7 +384,7 @@ export default class StudyAdminGrid extends LitElement { render: () => html` @@ -401,9 +402,9 @@ export default class StudyAdminGrid extends LitElement { }, render: () => html` diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 16574a911..74c4601ca 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -34,11 +34,11 @@ export default class StudyUsersManage extends LitElement { static get properties() { return { - studyId: { + studyFqn: { type: String, }, - organization: { - type: Object, + groups: { + type: Array, }, opencgaSession: { type: Object, @@ -50,8 +50,6 @@ export default class StudyUsersManage extends LitElement { } #init() { - this.component = {}; // Original object - this._component = {}; // Updated object this.updateParams = {}; this.isLoading = false; this.displayConfig = {}; @@ -64,18 +62,18 @@ export default class StudyUsersManage extends LitElement { }; } - #initOriginalObjects() { - // 1. Dataform variables + #initOriginalObjects(users) { + // 1. Data in data-form + // Original object this.component = { - selectedGroups: "", - selectedUsers: [], + selectedGroups: this.groups.map(group => group.id).join(",") || "", + selectedUsers: users?.map(user => user.id) || [], }; + // Modified object this._component = UtilsNew.objectClone(this.component); // 2. Query variables this._userGroupUpdates = []; - // 3. Display variables - this._groupAllowedValues = this.study.groups; - this._selectedGroups = []; + // 3. Display this._config = this.getDefaultConfig(); } @@ -86,9 +84,9 @@ export default class StudyUsersManage extends LitElement { // --- LIT LIFE CYCLE update(changedProperties) { - if (changedProperties.has("studyId") || - changedProperties.has("opencgaSession") || - changedProperties.has("organization")) { + if (changedProperties.has("studyFqn") || + changedProperties.has("groups") || + changedProperties.has("opencgaSession")) { this.propertyObserver(); } if (changedProperties.has("displayConfig")) { @@ -101,42 +99,35 @@ export default class StudyUsersManage extends LitElement { } // --- OBSERVERS --- - propertyObserver() { - if (this.studyId && this.opencgaSession && this.organization.id) { + async propertyObserver() { + if (this.opencgaSession?.organization?.id && this.groups && this.studyFqn) { + const filters = { + organization: this.opencgaSession.organization.id, + include: "id", + count: true, + limit: 1, + }; this.#setLoading(true); - this.opencgaSession.opencgaClient.studies() - .info(this.studyId) - .then(response => { - this.study = UtilsNew.objectClone(response.responses[0].results[0]); - this.#initOriginalObjects(); - }) - .catch(error => { - NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); - }) - .finally(() => { - this.#setLoading(false); - }); + try { + const responseNoUsers = await this.opencgaSession.opencgaClient.users().search(filters); + const noUsers = responseNoUsers.responses[0].numTotalResults; + if (noUsers > 0) { + filters.limit = noUsers; + const responseUsers = await this.opencgaSession.opencgaClient.users().search(filters); + const users = UtilsNew.objectClone(responseUsers.responses[0].result); + this.#initOriginalObjects(users); + } + } catch (error) { + NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); + } + this.#setLoading(false); } } // --- EVENTS --- onFieldChange(e) { const param = e.detail.param; - this.updatedFields = FormUtils.getUpdatedFields(this.variant, this.updatedFields, param, e.detail.value, e.detail.action); - - if (param === "selectedGroups") { - // Update the selectedGroups local variable. This is needed because the select-field-filter.js component is - // returning comma separated string - const selectedGroupIds = this._component.selectedGroups?.split(",") || []; - this._selectedGroups = selectedGroupIds - .map(selectedGroupId => this._groupAllowedValues.find(group => group.id === selectedGroupId)); - // If a group has been removed, remove possible updates stored in the array of changes - this._userGroupUpdates = this._userGroupUpdates.filter((update => selectedGroupIds.includes(update.groupId))); - } - if (param === "selectedUsers") { - // If a user has been removed, remove possible updates stored in the array of changes - this._userGroupUpdates = this._userGroupUpdates.filter((update => this._component.selectedUsers.includes(update.userId))); - } + this.updatedFields = FormUtils.getUpdatedFields(this.component, this.updatedFields, param, e.detail.value, e.detail.action); this._config = this.getDefaultConfig(); this.requestUpdate(); } @@ -146,7 +137,7 @@ export default class StudyUsersManage extends LitElement { title: "Discard changes", message: "Are you sure you want to discard the changes made?", ok: () => { - this.#initOriginalObjects(); + this.#initOriginalObjects({}); this.requestUpdate(); }, }); @@ -166,13 +157,14 @@ export default class StudyUsersManage extends LitElement { users: [update.userId], }; this.opencgaSession.opencgaClient.studies() - .updateGroupsUsers(this.study.fqn, update.groupId, data, params) + .updateGroupsUsers(this.studyFqn, update.groupId, data, params) .then(() => { + const studyId = this.studyFqn.split(":").pop(); NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_SUCCESS, { title: `User in Group Update`, message: ` ${update.userId} ${update.isChecked ? "ADDED to" : "REMOVED from"} - ${update.groupId} in study ${this.study.id} correctly. + ${update.groupId} in study ${studyId} correctly. `, }); }) @@ -217,93 +209,62 @@ export default class StudyUsersManage extends LitElement { // Double-check if the user is undoing a previous change on a specific user / group. _findChangePosition(userId, groupId) { // pos will equal -1 if a previous changes has been undone - return this._userGroupUpdates - .findIndex(update => update.userId === userId && update.groupId === groupId); + return this._userGroupUpdates.findIndex(update => update.userId === userId && update.groupId === groupId); } _findCurrentValue(userId, groupId) { - // 1. Check if this user has been added/removed from this group - const change = this._userGroupUpdates - .find(update => update.userId === userId && update.groupId === groupId); + // Check if this user has been added/removed from this group + const change = this._userGroupUpdates.find(update => update.userId === userId && update.groupId === groupId); if (change) { + // 2. If added/removed, return value return change.isChecked; + } else { + // 2. If not, check if the user was initially on this group + const group = this.groups.find(group => group.id === groupId); + return group.userIds.includes(userId); } - // 2. If not, check if the user was initially on this group - const group = this._selectedGroups.find(group => group.id === groupId); - return group.userIds.includes(userId); + } + + renderStyle() { + // Note 20240724 Vero: This css class enables vertical scroll on tbody + return html ` + + `; } // --- RENDER --- render() { - if (!this.study) { + if (!this.component) { return nothing; } return html` - - + ${this.renderStyle()} + + `; } getDefaultConfig() { const sections = [ - { - description: `This interface allows you to simultaneously manage multiple users in multiple groups within the selected study. - Please note that adding a user to the special group @members will only grant them access to the metadata of the study. - However, once users are in the @members group, Study Administrators can grant them additional permissions - at the study level or within specific groups.`, - display: { - descriptionClassName: "d-block text-secondary", - }, - elements: [ - { - title: "Select Group(s)", - field: "selectedGroups", - type: "select", - required: true, - multiple: true, - all: false, - allowedValues: this._groupAllowedValues, - display: { - // apply: () => , - placeholder: "Select group or groups...", - }, - }, - { - title: "Select User(s)", - field: "selectedUsers", - type: "custom", - required: true, - display: { - visible: this._selectedGroups?.length > 0, - render: (users, dataFormFilterChange, updateParams) => { - const userIds = (users || []).join(","); - const handleUsersFilterChange = e => { - // We need to convert value from a string with commas to an array of IDs - const userList = (e.detail.value?.split(",") || []); - dataFormFilterChange(userList); - }; - return html` - - - `; - }, - }, - }, - ], - }, { display: { descriptionClassName: "d-block text-secondary", @@ -311,10 +272,11 @@ export default class StudyUsersManage extends LitElement { }, elements: [ { - title: "Table", + // title: "Table", field: "selectedUsers", type: "table", display: { + className: "study-users-manage-table", width: 12, columns: [ { @@ -325,7 +287,7 @@ export default class StudyUsersManage extends LitElement { render: (value, update, params, data, row) => row, }, }, - ...this._selectedGroups?.map(group => ({ + ...this.groups?.map(group => ({ id: group.id, title: group.id, type: "custom", @@ -351,7 +313,6 @@ export default class StudyUsersManage extends LitElement { ], }, ]; - return { id: "", display: this.displayConfig, From bc951763b0c6d123d8f05dbfc6e7a9a4507c8069 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Jul 2024 12:07:10 +0200 Subject: [PATCH 142/177] wc - Small fixes. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-admin-grid.js | 50 +++++++++++-------- .../organization/admin/study-users-manage.js | 7 +-- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index 5452c013d..ad4880b15 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -66,7 +66,7 @@ export default class StudyAdminGrid extends LitElement { this.gridId = this._prefix + this.COMPONENT_ID; this.active = true; this._config = this.getDefaultConfig(); - this.action = ""; + this._action = ""; this.displayConfigDefault = { header: { horizontalAlign: "center", @@ -150,11 +150,11 @@ export default class StudyAdminGrid extends LitElement { permission: this.permissions["organization"](), divider: false, }, - "add-users": { - label: "Manage Users in Study", + "manage-users": { + label: "Manage Organization Users in Study", icon: "fas fa-user-plus", modalId: `${this._prefix}ManageUsersStudyModal`, - render: () => this.renderAddUsersStudy(), + render: () => this.renderManageUsersStudy(), permission: this.permissions["organization"](), divider: true, }, @@ -339,17 +339,21 @@ export default class StudyAdminGrid extends LitElement { // *** EVENTS *** async onActionClick(e, value, row) { - this.action = e.currentTarget.dataset.action; + this._action = e.currentTarget.dataset.action; this.studyId = row.id; this.studyFqn = row.fqn; - this.studyGroups = row.groups; + if (this._action === "manage-users") { + // Manage organization users: (a) add/remove from study, (b) set/unset as study admins + this.groups = row.groups.filter(group => ["@members", "@admins"].includes(group.id)); + } this.requestUpdate(); await this.updateComplete; - ModalUtils.show(this.modals[this.action]["modalId"]); + ModalUtils.show(this.modals[this._action]["modalId"]); } onStudyEvent(e, id) { // Fixme 20240616 Vero: find out a way to close modal creates! + this._action = ""; ModalUtils.close(id); } @@ -357,7 +361,7 @@ export default class StudyAdminGrid extends LitElement { renderGroupCreate() { return ModalUtils.create(this, `${this._prefix}CreateGroupModal`, { display: { - modalTitle: `Group Create`, + modalTitle: `Group Create in Study: ${this.studyId}`, modalDraggable: true, modalCyDataName: "modal-group-create", modalSize: "modal-lg" @@ -376,14 +380,14 @@ export default class StudyAdminGrid extends LitElement { renderStudyUpdate() { return ModalUtils.create(this, `${this._prefix}UpdateStudyModal`, { display: { - modalTitle: `Update Study`, + modalTitle: `Update Study: ${this.studyId}`, modalDraggable: true, modalCyDataName: "modal-study-update", modalSize: "modal-lg" }, render: () => html` @@ -392,23 +396,25 @@ export default class StudyAdminGrid extends LitElement { }); } - renderAddUsersStudy() { + renderManageUsersStudy() { return ModalUtils.create(this, `${this._prefix}ManageUsersStudyModal`, { display: { - modalTitle: `Manage Users in Study: ${this.studyId}`, + modalTitle: `Manage Organization Users in Study: ${this.studyId}`, modalDraggable: true, modalCyDataName: "modal-users-study-update", modalSize: "modal-lg" }, - render: () => html` - - - `, + render: () => { + return html` + + + `; + } }); } @@ -434,7 +440,7 @@ export default class StudyAdminGrid extends LitElement {
    - ${this.action ? this.modals[this.action]["render"](): nothing} + ${this._action ? this.modals[this._action]["render"](): nothing} `; } diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 74c4601ca..eeac0548d 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -137,7 +137,7 @@ export default class StudyUsersManage extends LitElement { title: "Discard changes", message: "Are you sure you want to discard the changes made?", ok: () => { - this.#initOriginalObjects({}); + this.#initOriginalObjects([]); this.requestUpdate(); }, }); @@ -156,7 +156,7 @@ export default class StudyUsersManage extends LitElement { const data = { users: [update.userId], }; - this.opencgaSession.opencgaClient.studies() + return this.opencgaSession.opencgaClient.studies() .updateGroupsUsers(this.studyFqn, update.groupId, data, params) .then(() => { const studyId = this.studyFqn.split(":").pop(); @@ -184,8 +184,9 @@ export default class StudyUsersManage extends LitElement { Promise.all(_userGroupPromises) .finally(() => { this.#setLoading(false); - this.#initOriginalObjects(); + this.#initOriginalObjects([]); LitUtils.dispatchCustomEvent(this, "studyUpdateRequest", {}); + LitUtils.dispatchCustomEvent(this, "studyUpdate", this.study, {}); }); } From 6d4ee4d3b421e00277d1e9d7b0d71f690caf4c44 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Jul 2024 12:07:53 +0200 Subject: [PATCH 143/177] wc - Use study fqn. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/study/admin/study-update.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/webcomponents/study/admin/study-update.js b/src/webcomponents/study/admin/study-update.js index fd1ff95d5..575b423f5 100644 --- a/src/webcomponents/study/admin/study-update.js +++ b/src/webcomponents/study/admin/study-update.js @@ -34,7 +34,7 @@ export default class StudyUpdate extends LitElement { static get properties() { return { - studyId: { + studyFqn: { type: String }, opencgaSession: { @@ -86,8 +86,8 @@ export default class StudyUpdate extends LitElement { } update(changedProperties) { - if (changedProperties.has("studyId")) { - this.studyIdObserver(); + if (changedProperties.has("studyFqn")) { + this.studyFqnObserver(); } if (changedProperties.has("displayConfig")) { this.displayConfigObserver(); @@ -95,12 +95,12 @@ export default class StudyUpdate extends LitElement { super.update(changedProperties); } - studyIdObserver() { - if (this.studyId && this.opencgaSession) { + studyFqnObserver() { + if (this.studyFqn && this.opencgaSession) { let error; this.#setLoading(true); this.opencgaSession.opencgaClient.studies() - .info(this.studyId) + .info(this.studyFqn) .then(response => { this.study = UtilsNew.objectClone(response.responses[0].results[0]); this.#initOriginalObjects(); @@ -172,8 +172,8 @@ export default class StudyUpdate extends LitElement { title: "Study Update", message: `Study ${this.study.id} updated correctly` }); - LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", this._study, {}, error); - LitUtils.dispatchCustomEvent(this, "studyUpdate", this._study, {}, error); + LitUtils.dispatchCustomEvent(this, "sessionUpdateRequest", this.study, {}, error); + LitUtils.dispatchCustomEvent(this, "studyUpdate", this.study, {}, error); }) .catch(reason => { error = reason; From ce0482e8b3652238ea16545bc61af0497d1c892e Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Jul 2024 12:08:14 +0200 Subject: [PATCH 144/177] wc - Small clean. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/opencga-catalog-utils.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/core/clients/opencga/opencga-catalog-utils.js b/src/core/clients/opencga/opencga-catalog-utils.js index ee7c3f5dc..d4dee96f1 100644 --- a/src/core/clients/opencga/opencga-catalog-utils.js +++ b/src/core/clients/opencga/opencga-catalog-utils.js @@ -104,21 +104,6 @@ export default class OpencgaCatalogUtils { console.error(`No valid parameters, study: ${study}, user: ${userLogged}`); return false; } - // CAUTION: in organizations, label before @ is now organization name, not owner - /* - // Check if user is the Study owner - const studyOwner = study.fqn.split("@")[0]; - if (userLogged === studyOwner) { - return true; - } else { - // Check if user is a Study admin, belongs to @admins group - const admins = study.groups.find(group => group.id === "@admins"); - if (admins.userIds.includes(userLogged)) { - return true; - } - } - return false; - */ const admins = study.groups.find(group => group.id === "@admins"); return !!admins.userIds.includes(userLogged); } From f4045d0f280a3b62943375561039898329d26652 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Jul 2024 14:36:38 +0200 Subject: [PATCH 145/177] wc - WiP Label users with role. #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-users-manage.js | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index eeac0548d..c069b8fc8 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -62,17 +62,34 @@ export default class StudyUsersManage extends LitElement { }; } - #initOriginalObjects(users) { + #initOriginalObjects() { // 1. Data in data-form // Original object + this.userRole = { + "org-owner": { + displayName: "OWNER", + check: userId => this.opencgaSession.organization.owner === userId, + }, + "org-admin": { + displayName: "ADMIN", + check: userId => this.opencgaSession.organization.admins.includes(userId), + }, + "study-admin": { + displayName: "STUDY ADMIN", + check: userId => this.groups.find(group => group.id === "@admins").userIds.includes(userId), + }, + }; + this.component = { selectedGroups: this.groups.map(group => group.id).join(",") || "", - selectedUsers: users?.map(user => user.id) || [], + selectedUsers: this.users?.map(user => user.id) || [], }; // Modified object this._component = UtilsNew.objectClone(this.component); + // 2. Query variables this._userGroupUpdates = []; + // 3. Display this._config = this.getDefaultConfig(); } @@ -114,8 +131,8 @@ export default class StudyUsersManage extends LitElement { if (noUsers > 0) { filters.limit = noUsers; const responseUsers = await this.opencgaSession.opencgaClient.users().search(filters); - const users = UtilsNew.objectClone(responseUsers.responses[0].result); - this.#initOriginalObjects(users); + this.users = UtilsNew.objectClone(responseUsers.responses[0].result); + this.#initOriginalObjects(); } } catch (error) { NotificationUtils.dispatch(this, NotificationUtils.NOTIFY_RESPONSE, error); @@ -137,7 +154,7 @@ export default class StudyUsersManage extends LitElement { title: "Discard changes", message: "Are you sure you want to discard the changes made?", ok: () => { - this.#initOriginalObjects([]); + this.#initOriginalObjects(); this.requestUpdate(); }, }); @@ -184,7 +201,6 @@ export default class StudyUsersManage extends LitElement { Promise.all(_userGroupPromises) .finally(() => { this.#setLoading(false); - this.#initOriginalObjects([]); LitUtils.dispatchCustomEvent(this, "studyUpdateRequest", {}); LitUtils.dispatchCustomEvent(this, "studyUpdate", this.study, {}); }); @@ -285,7 +301,20 @@ export default class StudyUsersManage extends LitElement { title: "User Id", type: "custom", display: { - render: (value, update, params, data, row) => row, + render: (value, update, params, data, userId) => { + const role = Object.values(this.userRole) + .find(role => role.check(userId)) || {}; + return html` +
    + ${role?.displayName ? html` +
    ${userId}
    +
    ${role.displayName}
    + ` : html` +
    ${userId}
    + `} +
    + `; + } }, }, ...this.groups?.map(group => ({ @@ -295,14 +324,16 @@ export default class StudyUsersManage extends LitElement { display: { helpMessage: "", render: (checked, dataFormFilterChange, updateParams, data, row) => { + const currentValue = this._findCurrentValue(row, group.id); + const changePosition = this._findChangePosition(row, group.id); return html`
    - ${this._findChangePosition(row, group.id) >= 0 ? html`*` : ""} + ${changePosition >= 0 ? html`*` : ""}
    `; } From 7dd6531f830db099cb45cec0a7af71b4721b37c1 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Fri, 26 Jul 2024 18:14:41 +0200 Subject: [PATCH 146/177] wc - Disable/Enable groups checkboxes on change if user is member not admin in a study, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-users-manage.js | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index c069b8fc8..1bedea4af 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -19,6 +19,7 @@ import UtilsNew from "../../../core/utils-new.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; import FormUtils from "../../commons/forms/form-utils"; import LitUtils from "../../commons/utils/lit-utils"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; export default class StudyUsersManage extends LitElement { @@ -64,7 +65,6 @@ export default class StudyUsersManage extends LitElement { #initOriginalObjects() { // 1. Data in data-form - // Original object this.userRole = { "org-owner": { displayName: "OWNER", @@ -79,7 +79,7 @@ export default class StudyUsersManage extends LitElement { check: userId => this.groups.find(group => group.id === "@admins").userIds.includes(userId), }, }; - + // Original object this.component = { selectedGroups: this.groups.map(group => group.id).join(",") || "", selectedUsers: this.users?.map(user => user.id) || [], @@ -91,6 +91,7 @@ export default class StudyUsersManage extends LitElement { this._userGroupUpdates = []; // 3. Display + this.forceDisable = []; this._config = this.getDefaultConfig(); } @@ -219,6 +220,18 @@ export default class StudyUsersManage extends LitElement { groupId: groupId, }); } + // If a user is member not admin: + // - If removed from member => disable admin + // - If added to admin => disable member + // - And enable them back if the change is undone + // To avoid undetermined user permissions on submit if contradictory changes are submitted. + if (groupId === "@admins" && this.groups.find(group => group.id === "@members" && group.userIds.includes(userId))) { + this.forceDisable[`${userId}.@members`] = e.currentTarget.checked; + } + if (groupId === "@members" && this.groups.find(group => group.id === "@admins" && !group.userIds.includes(userId))) { + this.forceDisable[`${userId}.@admins`] = !e.currentTarget.checked; + } + this._config = {...this._config}; this.requestUpdate(); } @@ -323,16 +336,20 @@ export default class StudyUsersManage extends LitElement { type: "custom", display: { helpMessage: "", - render: (checked, dataFormFilterChange, updateParams, data, row) => { - const currentValue = this._findCurrentValue(row, group.id); - const changePosition = this._findChangePosition(row, group.id); + render: (checked, dataFormFilterChange, updateParams, data, userId) => { + const currentValue = this._findCurrentValue(userId, group.id); + const changePosition = this._findChangePosition(userId, group.id); + // If the user is organization admin or owner, + // the checkboxes in members and admins need to be disabled + const userIsOrganizationAdmin = OpencgaCatalogUtils.isOrganizationAdminOwner(this.opencgaSession.organization, userId); return html`
    + .disabled="${userIsOrganizationAdmin || this.forceDisable[`${userId}.${group.id}`]}" + @click="${e => this.onUserGroupChange(e, userId, group.id)}"> ${changePosition >= 0 ? html`*` : ""}
    `; From 35f9c396e60a1c1e3ef3445453310a5b3ae4c453 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 29 Jul 2024 11:32:36 +0200 Subject: [PATCH 147/177] wc - Fix disabling on case user member and admin, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-users-manage.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 1bedea4af..24da1a008 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -17,9 +17,9 @@ import {html, LitElement, nothing} from "lit"; import UtilsNew from "../../../core/utils-new.js"; import NotificationUtils from "../../commons/utils/notification-utils.js"; -import FormUtils from "../../commons/forms/form-utils"; -import LitUtils from "../../commons/utils/lit-utils"; import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; +import FormUtils from "../../commons/forms/form-utils.js"; +import LitUtils from "../../commons/utils/lit-utils.js"; export default class StudyUsersManage extends LitElement { @@ -226,7 +226,7 @@ export default class StudyUsersManage extends LitElement { // - And enable them back if the change is undone // To avoid undetermined user permissions on submit if contradictory changes are submitted. if (groupId === "@admins" && this.groups.find(group => group.id === "@members" && group.userIds.includes(userId))) { - this.forceDisable[`${userId}.@members`] = e.currentTarget.checked; + this.forceDisable[`${userId}.@members`] = (e.currentTarget.checked && pos === -1); } if (groupId === "@members" && this.groups.find(group => group.id === "@admins" && !group.userIds.includes(userId))) { this.forceDisable[`${userId}.@admins`] = !e.currentTarget.checked; @@ -332,7 +332,7 @@ export default class StudyUsersManage extends LitElement { }, ...this.groups?.map(group => ({ id: group.id, - title: group.id, + title: group.id === "@members" ? "Study Member" : "Study Admin", type: "custom", display: { helpMessage: "", From f439232d0287e73fee09150d5d4b970433936c74 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 29 Jul 2024 11:35:28 +0200 Subject: [PATCH 148/177] wc - Add comment to the latest fix, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/study-users-manage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 24da1a008..67f2bdd81 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -224,6 +224,8 @@ export default class StudyUsersManage extends LitElement { // - If removed from member => disable admin // - If added to admin => disable member // - And enable them back if the change is undone + // If a user is member and admin: + // - If removed from admin and added back => do not disable member // To avoid undetermined user permissions on submit if contradictory changes are submitted. if (groupId === "@admins" && this.groups.find(group => group.id === "@members" && group.userIds.includes(userId))) { this.forceDisable[`${userId}.@members`] = (e.currentTarget.checked && pos === -1); From 20d6d59914ea4535714e59b804bcdc84d0c56011 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Mon, 29 Jul 2024 12:21:36 +0200 Subject: [PATCH 149/177] wc - Fix for user no member no admin, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/study-users-manage.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 67f2bdd81..1285d152c 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -226,12 +226,14 @@ export default class StudyUsersManage extends LitElement { // - And enable them back if the change is undone // If a user is member and admin: // - If removed from admin and added back => do not disable member + // If a user is not member and not admin + // - If added to member and removed back => do not disable admin // To avoid undetermined user permissions on submit if contradictory changes are submitted. if (groupId === "@admins" && this.groups.find(group => group.id === "@members" && group.userIds.includes(userId))) { this.forceDisable[`${userId}.@members`] = (e.currentTarget.checked && pos === -1); } if (groupId === "@members" && this.groups.find(group => group.id === "@admins" && !group.userIds.includes(userId))) { - this.forceDisable[`${userId}.@admins`] = !e.currentTarget.checked; + this.forceDisable[`${userId}.@admins`] = (!e.currentTarget.checked && pos === -1); } this._config = {...this._config}; From 2e9b28856d267b2d1ca8a8c5cb4405d943bb8278 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 17:35:37 +0200 Subject: [PATCH 150/177] wc: Fix one issue onClear, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/group-admin-create.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/webcomponents/organization/admin/group-admin-create.js b/src/webcomponents/organization/admin/group-admin-create.js index baf259bcd..8dbff9f05 100644 --- a/src/webcomponents/organization/admin/group-admin-create.js +++ b/src/webcomponents/organization/admin/group-admin-create.js @@ -49,7 +49,6 @@ export default class GroupAdminCreate extends LitElement { } #init() { - this.group = {}; this.isLoading = false; this.displayConfigDefault = { style: "margin: 10px", @@ -151,8 +150,7 @@ export default class GroupAdminCreate extends LitElement { title: "Clear group", message: "Are you sure to clear?", ok: () => { - this.group = {}; - this._config = this.getDefaultConfig(); + this.#initOriginalObjects(); this.requestUpdate(); }, }); From 2a7fbd7f641b1dc65d20425612cddc0a0c0a01a0 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 17:36:10 +0200 Subject: [PATCH 151/177] wc: Display buttons on top, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/project-admin-browser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webcomponents/organization/admin/project-admin-browser.js b/src/webcomponents/organization/admin/project-admin-browser.js index d3617f8a5..2acce5e56 100644 --- a/src/webcomponents/organization/admin/project-admin-browser.js +++ b/src/webcomponents/organization/admin/project-admin-browser.js @@ -92,7 +92,7 @@ export default class ProjectAdminBrowser extends LitElement { }, render: () => html ` ` }, @@ -133,7 +133,7 @@ export default class ProjectAdminBrowser extends LitElement { `; From eea4edf2cbb493268835cbcc6bf65d78194d0806 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 17:42:14 +0200 Subject: [PATCH 152/177] wc: Place dates in last columns, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../organization/admin/study-admin-grid.js | 16 +++++++-------- .../organization/admin/study-users-manage.js | 2 +- .../organization/admin/user-admin-grid.js | 20 +++++++++---------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index ad4880b15..5c98d8cc3 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -245,18 +245,18 @@ export default class StudyAdminGrid extends LitElement { visible: this.gridCommons.isColumnVisible("name") }, { - title: "Creation Date / Modification Date", + title: "Groups", + field: "groups", + formatter: (groups, row) => this.groupsFormatter(groups, row), + visible: this.gridCommons.isColumnVisible("modificationDate") + }, + { + title: "Modification / Creation Dates", field: "dates", halign: this.displayConfigDefault.header.horizontalAlign, valign: "middle", formatter: (value, row) => this.datesFormatter(value, row), }, - { - title: "Groups", - field: "groups", - formatter: (groups, row) => this.groupsFormatter(groups, row), - visible: this.gridCommons.isColumnVisible("modificationDate") - } ]; if (this._config.annotations?.length > 0) { @@ -332,8 +332,8 @@ export default class StudyAdminGrid extends LitElement { datesFormatter(value, study) { return ` -
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    ${CatalogGridFormatter.dateFormatter(study.modificationDate, study)}
    +
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    `; } diff --git a/src/webcomponents/organization/admin/study-users-manage.js b/src/webcomponents/organization/admin/study-users-manage.js index 1285d152c..fae74d864 100644 --- a/src/webcomponents/organization/admin/study-users-manage.js +++ b/src/webcomponents/organization/admin/study-users-manage.js @@ -226,7 +226,7 @@ export default class StudyUsersManage extends LitElement { // - And enable them back if the change is undone // If a user is member and admin: // - If removed from admin and added back => do not disable member - // If a user is not member and not admin + // If a user is not member and not admin: // - If added to member and removed back => do not disable admin // To avoid undetermined user permissions on submit if contradictory changes are submitted. if (groupId === "@admins" && this.groups.find(group => group.id === "@members" && group.userIds.includes(userId))) { diff --git a/src/webcomponents/organization/admin/user-admin-grid.js b/src/webcomponents/organization/admin/user-admin-grid.js index 8402030c6..534b692e9 100644 --- a/src/webcomponents/organization/admin/user-admin-grid.js +++ b/src/webcomponents/organization/admin/user-admin-grid.js @@ -286,29 +286,29 @@ export default class UserAdminGrid extends LitElement { field: "internal.failedAttempts", visible: this.gridCommons.isColumnVisible("noAttempts"), }, + { + id: "status", + title: "Status", + field: "internal.status", + formatter: value => CatalogGridFormatter.userStatusFormatter(value, this._config.userStatus), + visible: this.gridCommons.isColumnVisible("status") + }, { id: "lastModifiedDate", - title: "Last Modified date", + title: "Last Modified Date", field: "internal.lastModified", formatter: (value, row) => UtilsNew.dateFormatter(row.internal.lastModified), visible: this.gridCommons.isColumnVisible("lastModifiedDate") }, { id: "dates", - title: "Creation / Expiration dates", + title: "Expiration / Creation Dates", field: "dates", halign: this.displayConfigDefault.header.horizontalAlign, valign: "middle", formatter: (value, row) => this.datesFormatter(value, row), visible: this.gridCommons.isColumnVisible("dates") }, - { - id: "status", - title: "Status", - field: "internal.status", - formatter: value => CatalogGridFormatter.userStatusFormatter(value, this._config.userStatus), - visible: this.gridCommons.isColumnVisible("status") - }, ]; if (this._config.annotations?.length > 0) { @@ -406,8 +406,8 @@ export default class UserAdminGrid extends LitElement { expirationDateClass = "text-danger"; } return ` -
    ${UtilsNew.dateFormatter(user.account.creationDate)}
    ${expirationDateString}
    +
    ${UtilsNew.dateFormatter(user.account.creationDate)}
    `; } From 052335c3f788e0bf1f4fd3593eb2b204fec39344 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 18:25:20 +0200 Subject: [PATCH 153/177] wc: Remove unnecessary properties in study admin, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/sites/iva/iva-app.js | 2 - src/webcomponents/study/admin/study-admin.js | 73 ++------------------ 2 files changed, 6 insertions(+), 69 deletions(-) diff --git a/src/sites/iva/iva-app.js b/src/sites/iva/iva-app.js index bbf6a8ee4..d24821ccb 100644 --- a/src/sites/iva/iva-app.js +++ b/src/sites/iva/iva-app.js @@ -2057,8 +2057,6 @@ class IvaApp extends LitElement { ${this.config.enabledComponents["study-admin"] ? html`
    diff --git a/src/webcomponents/study/admin/study-admin.js b/src/webcomponents/study/admin/study-admin.js index 9769bd922..585f8e7a5 100644 --- a/src/webcomponents/study/admin/study-admin.js +++ b/src/webcomponents/study/admin/study-admin.js @@ -15,20 +15,16 @@ */ import {LitElement, html} from "lit"; - +import LitUtils from "../../commons/utils/lit-utils"; +import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils.js"; import "./study-admin-users.js"; import "./study-admin-permissions.js"; import "./study-admin-variable.js"; import "./study-admin-audit.js"; import "./study-admin-configuration.js"; - import "../../variant/operation/clinical-analysis-configuration-operation.js"; import "../../variant/operation/variant-secondary-sample-index-configure-operation.js"; - -import LitUtils from "../../commons/utils/lit-utils"; import "../../commons/layouts/custom-vertical-navbar.js"; -import OpencgaCatalogUtils from "../../../core/clients/opencga/opencga-catalog-utils"; -import UtilsNew from "../../../core/utils-new"; export default class StudyAdmin extends LitElement { @@ -44,15 +40,9 @@ export default class StudyAdmin extends LitElement { static get properties() { return { - organizationId: { - type: String, - }, studyId: { type: String }, - study: { - type: Object - }, opencgaSession: { type: Object }, @@ -60,14 +50,11 @@ export default class StudyAdmin extends LitElement { } #init() { + this.study = {}; this._config = this.getDefaultConfig(); } update(changedProperties) { - if (changedProperties.has("organizationId")) { - this.organizationIdObserver(); - } - if (changedProperties.has("studyId") || changedProperties.has("opencgaSession")) { this.studyIdObserver(); } @@ -78,48 +65,7 @@ export default class StudyAdmin extends LitElement { this.isLoading = value; this.requestUpdate(); } - - organizationIdObserver() { - // FIXME Vero: on creating a new group, for instance, - // the session is updated but the org id does not change. - // I need to get the organization info again to refresh the grid. - // For now, I will query org info only with property opencgaSession change. - // TO think about it. - // if (this.organizationId && this.opencgaSession) { - if (this.organizationId || this.opencgaSession) { - let error; - this.#setLoading(true); - this.opencgaSession.opencgaClient.organization() - // FIXME Vero: To remove hardcoded organization when the following bug is fixed: - // https://app.clickup.com/t/36631768/TASK-5980 - // .info(this.organizationId) - .info("test") - .then(response => { - this.organization = UtilsNew.objectClone(response.responses[0].results[0]); - }) - .catch(reason => { - // this.organization = {}; - error = reason; - console.error(reason); - }) - .finally(() => { - LitUtils.dispatchCustomEvent(this, "organizationInfo", this.organization, {}, error); - this.#setLoading(false); - }); - } - } - studyIdObserver() { - /* - for (const project of this.opencgaSession?.projects) { - for (const study of project.studies) { - if (study.id === this.studyId || study.fqn === this.studyId) { - this.study = study; - break; - } - } - } - */ if (this.studyId && this.opencgaSession) { let error; this.#setLoading(true); @@ -129,7 +75,6 @@ export default class StudyAdmin extends LitElement { this.study = response.responses[0].results[0]; }) .catch(reason => { - this.study = {}; error = reason; console.error(reason); }) @@ -138,15 +83,13 @@ export default class StudyAdmin extends LitElement { LitUtils.dispatchCustomEvent(this, "studySearch", this.study, {}, error); this.#setLoading(false); }); - } else { - this.study = {}; } } render() { const activeMenuItem = "UsersAndGroups"; - if (this.opencgaSession.study && this.organization) { - if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.organization, this.opencgaSession.user.id) && + if (this.opencgaSession.study && this.opencgaSession.organization) { + if (!OpencgaCatalogUtils.isOrganizationAdminOwner(this.opencgaSession.organization, this.opencgaSession.user.id) && !OpencgaCatalogUtils.isAdmin(this.opencgaSession.study, this.opencgaSession.user.id)) { return html` @@ -209,7 +152,6 @@ export default class StudyAdmin extends LitElement { submenu: [ { id: "UsersAndGroups", - // label: "Users and Groups", name: "Users and Groups", icon: "fas fa-user-friends", visibility: "private", @@ -235,7 +177,6 @@ export default class StudyAdmin extends LitElement { }, { id: "Permissions", - // label: "Permissions", name: "Permissions", icon: "fas fa-key", visibility: "private", @@ -247,7 +188,6 @@ export default class StudyAdmin extends LitElement { }, { id: "VariableSets", - // label: "Variable Sets", name: "Variable Sets", icon: "fas fa-book", visibility: "private", @@ -320,7 +260,6 @@ export default class StudyAdmin extends LitElement { // submenu: [ // // { // // id: "Solr", - // // // label: "Solr", // // name: "Solr", // // // CAUTION: icon vs. img in config.js? // // img: "/sites/iva/img/logos/Solr.png", @@ -328,7 +267,7 @@ export default class StudyAdmin extends LitElement { // // }, // // { // // id: "Rysnc", - // // label: "Rysnc", + // // name: "Rysnc", // // icon: "", // // visibility: "private", // // }, From 59f1e97f0f9b0612879babe190631210f2bcd7fa Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 18:35:44 +0200 Subject: [PATCH 154/177] wc: Remove class secondary in modification date, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/study-admin-grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index 5c98d8cc3..8ec175e37 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -333,7 +333,7 @@ export default class StudyAdminGrid extends LitElement { datesFormatter(value, study) { return `
    ${CatalogGridFormatter.dateFormatter(study.modificationDate, study)}
    -
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    +
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    `; } From a6530b2dc2b6453c6417bd0e15b2564912c07596 Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 18:36:23 +0200 Subject: [PATCH 155/177] wc: Remove class secondary in modification date, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/webcomponents/organization/admin/study-admin-grid.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webcomponents/organization/admin/study-admin-grid.js b/src/webcomponents/organization/admin/study-admin-grid.js index 8ec175e37..05d58097e 100644 --- a/src/webcomponents/organization/admin/study-admin-grid.js +++ b/src/webcomponents/organization/admin/study-admin-grid.js @@ -332,8 +332,8 @@ export default class StudyAdminGrid extends LitElement { datesFormatter(value, study) { return ` -
    ${CatalogGridFormatter.dateFormatter(study.modificationDate, study)}
    -
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    +
    ${CatalogGridFormatter.dateFormatter(study.modificationDate, study)}
    +
    ${CatalogGridFormatter.dateFormatter(study.creationDate, study)}
    `; } From d186a260a3a12a4d214ac73874ec76db424070fc Mon Sep 17 00:00:00 2001 From: gpveronica Date: Wed, 31 Jul 2024 19:58:23 +0200 Subject: [PATCH 156/177] core: Update Javascript clients from OpenCGA release-3.2.x, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- src/core/clients/opencga/api/Admin.js | 8 +- src/core/clients/opencga/api/Alignment.js | 44 ++++++- .../clients/opencga/api/ClinicalAnalysis.js | 41 ++++++- src/core/clients/opencga/api/Cohort.js | 8 +- src/core/clients/opencga/api/DiseasePanel.js | 12 +- src/core/clients/opencga/api/Family.js | 8 +- src/core/clients/opencga/api/File.js | 20 ++- src/core/clients/opencga/api/GA4GH.js | 8 +- src/core/clients/opencga/api/Individual.js | 8 +- src/core/clients/opencga/api/Job.js | 19 ++- src/core/clients/opencga/api/Meta.js | 8 +- src/core/clients/opencga/api/Organization.js | 24 +++- src/core/clients/opencga/api/Project.js | 8 +- src/core/clients/opencga/api/Sample.js | 8 +- src/core/clients/opencga/api/Study.js | 12 +- src/core/clients/opencga/api/User.js | 8 +- src/core/clients/opencga/api/Variant.js | 114 ++++++++++++++++-- .../clients/opencga/api/VariantOperation.js | 104 +++++++++++++++- 18 files changed, 399 insertions(+), 63 deletions(-) diff --git a/src/core/clients/opencga/api/Admin.js b/src/core/clients/opencga/api/Admin.js index 6d42c5646..3f6204d41 100644 --- a/src/core/clients/opencga/api/Admin.js +++ b/src/core/clients/opencga/api/Admin.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Alignment.js b/src/core/clients/opencga/api/Alignment.js index 0c5d7cfeb..fc3021778 100644 --- a/src/core/clients/opencga/api/Alignment.js +++ b/src/core/clients/opencga/api/Alignment.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -41,6 +43,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runBwa(data, params) { @@ -56,6 +62,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runCoverageIndex(data, params) { @@ -71,6 +81,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ coverageQcGeneCoverageStatsRun(data, params) { @@ -136,6 +150,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runDeeptools(data, params) { @@ -151,6 +169,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runFastqc(data, params) { @@ -166,6 +188,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runIndex(data, params) { @@ -182,6 +208,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runPicard(data, params) { @@ -198,6 +228,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runQc(data, params) { @@ -244,6 +278,10 @@ export default class Alignment extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runSamtools(data, params) { diff --git a/src/core/clients/opencga/api/ClinicalAnalysis.js b/src/core/clients/opencga/api/ClinicalAnalysis.js index 25c6cd4c4..f2e403145 100644 --- a/src/core/clients/opencga/api/ClinicalAnalysis.js +++ b/src/core/clients/opencga/api/ClinicalAnalysis.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -207,6 +209,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInterpreterCancerTiering(data, params) { @@ -222,6 +228,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInterpreterExomiser(data, params) { @@ -237,6 +247,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInterpreterTeam(data, params) { @@ -252,6 +266,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInterpreterTiering(data, params) { @@ -267,6 +285,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInterpreterZetta(data, params) { @@ -282,6 +304,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ load(data, params) { @@ -399,6 +425,10 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {Boolean} [params.auxiliarIndex = "false"] - Index auxiliar collection to improve performance assuming RGA is completely * indexed. The default value is false. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -600,8 +630,7 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * but also increase execution time. * @param {String} [params.savedFilter] - Use a saved filter at User level. * @param {String} [params.includeInterpretation] - Interpretation ID to include the fields related to this interpretation. - * @param {String} [params.id] - List of IDs, these can be rs IDs (dbSNP) or variants in the format chrom:start:ref:alt, e.g. - * rs116600158,19:7177679:C:T. + * @param {String} [params.id] - List of variant IDs in the format chrom:start:ref:alt, e.g. 19:7177679:C:T. * @param {String} [params.region] - List of regions, these can be just a single chromosome name or regions in the format chr:start-end, * e.g.: 2,3:100000-200000. * @param {String} [params.type] - List of types, accepted values are SNV, MNV, INDEL, SV, COPY_NUMBER, COPY_NUMBER_LOSS, @@ -653,7 +682,7 @@ export default class ClinicalAnalysis extends OpenCGAParentClass { * @param {String} [params.ct] - List of SO consequence types, e.g. missense_variant,stop_lost or SO:0001583,SO:0001578. Accepts aliases * 'loss_of_function' and 'protein_altering'. * @param {String} [params.xref] - List of any external reference, these can be genes, proteins or variants. Accepted IDs include HGNC, - * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, ... + * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, HGVS ... * @param {String} [params.biotype] - List of biotypes, e.g. protein_coding. * @param {String} [params.proteinSubstitution] - Protein substitution scores include SIFT and PolyPhen. You can query using the score * {protein_score}[<|>|<=|>=]{number} or the description {protein_score}[~=|=]{description} e.g. polyphen>0.1,sift=tolerant. diff --git a/src/core/clients/opencga/api/Cohort.js b/src/core/clients/opencga/api/Cohort.js index 1d9d146d8..dcd44092c 100644 --- a/src/core/clients/opencga/api/Cohort.js +++ b/src/core/clients/opencga/api/Cohort.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/DiseasePanel.js b/src/core/clients/opencga/api/DiseasePanel.js index b034b4a06..1aca2e4ef 100644 --- a/src/core/clients/opencga/api/DiseasePanel.js +++ b/src/core/clients/opencga/api/DiseasePanel.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -107,6 +109,10 @@ export default class DiseasePanel extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ importPanels(data, params) { diff --git a/src/core/clients/opencga/api/Family.js b/src/core/clients/opencga/api/Family.js index 196bb8147..55a5ac0ca 100644 --- a/src/core/clients/opencga/api/Family.js +++ b/src/core/clients/opencga/api/Family.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/File.js b/src/core/clients/opencga/api/File.js index 2c4acdbd2..3e1abab6f 100644 --- a/src/core/clients/opencga/api/File.js +++ b/src/core/clients/opencga/api/File.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -129,6 +131,10 @@ export default class File extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -164,6 +170,10 @@ export default class File extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runLink(data, params) { @@ -179,6 +189,10 @@ export default class File extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runPostlink(data, params) { diff --git a/src/core/clients/opencga/api/GA4GH.js b/src/core/clients/opencga/api/GA4GH.js index f4d6eef05..02af95b13 100644 --- a/src/core/clients/opencga/api/GA4GH.js +++ b/src/core/clients/opencga/api/GA4GH.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Individual.js b/src/core/clients/opencga/api/Individual.js index 1744c4611..fb33520e6 100644 --- a/src/core/clients/opencga/api/Individual.js +++ b/src/core/clients/opencga/api/Individual.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Job.js b/src/core/clients/opencga/api/Job.js index a6ec63d51..f0ebb6401 100644 --- a/src/core/clients/opencga/api/Job.js +++ b/src/core/clients/opencga/api/Job.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -93,6 +95,7 @@ export default class Job extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -203,6 +206,16 @@ export default class Job extends OpenCGAParentClass { return this._post("jobs", jobs, null, null, "update", data, params); } + /** Send a signal to kill a pending or running job + * @param {String} job - Job ID or UUID. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + kill(job, params) { + return this._post("jobs", job, null, null, "kill", params); + } + /** Show the first lines of a log file (up to a limit) * @param {String} job - Job ID or UUID. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Meta.js b/src/core/clients/opencga/api/Meta.js index 599d48eca..0a536de0c 100644 --- a/src/core/clients/opencga/api/Meta.js +++ b/src/core/clients/opencga/api/Meta.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Organization.js b/src/core/clients/opencga/api/Organization.js index 176753b98..1580a4a78 100644 --- a/src/core/clients/opencga/api/Organization.js +++ b/src/core/clients/opencga/api/Organization.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -133,6 +135,22 @@ export default class Organization extends OpenCGAParentClass { return this._post("organizations", null, "user", user, "update", data, params); } + /** Update the Organization configuration attributes + * @param {String} organization - Organization id. + * @param {Object} data - JSON containing the params to be updated. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. + * @param {String} [params.exclude] - Fields excluded in the response, whole JSON path must be provided. + * @param {Boolean} [params.includeResult = "false"] - Flag indicating to include the created or updated document result in the response. + * The default value is false. + * @param {"ADD SET REMOVE REPLACE"} [params.authenticationOriginsAction = "ADD"] - Action to be performed if the array of + * authenticationOrigins is being updated. The default value is ADD. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + updateConfiguration(organization, data, params) { + return this._post("organizations", organization, "configuration", null, "update", data, params); + } + /** Return the organization information * @param {String} organization - Organization id. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/src/core/clients/opencga/api/Project.js b/src/core/clients/opencga/api/Project.js index 1aa374428..524221df8 100644 --- a/src/core/clients/opencga/api/Project.js +++ b/src/core/clients/opencga/api/Project.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Sample.js b/src/core/clients/opencga/api/Sample.js index 2150b03db..48edf930f 100644 --- a/src/core/clients/opencga/api/Sample.js +++ b/src/core/clients/opencga/api/Sample.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Study.js b/src/core/clients/opencga/api/Study.js index a144ce485..9e013fef0 100644 --- a/src/core/clients/opencga/api/Study.js +++ b/src/core/clients/opencga/api/Study.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -260,6 +262,10 @@ export default class Study extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runTemplates(study, data, params) { diff --git a/src/core/clients/opencga/api/User.js b/src/core/clients/opencga/api/User.js index b4cd42455..843416dd1 100644 --- a/src/core/clients/opencga/api/User.js +++ b/src/core/clients/opencga/api/User.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. diff --git a/src/core/clients/opencga/api/Variant.js b/src/core/clients/opencga/api/Variant.js index 7d165e13c..7d8b01966 100644 --- a/src/core/clients/opencga/api/Variant.js +++ b/src/core/clients/opencga/api/Variant.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -57,7 +59,7 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.ct] - List of SO consequence types, e.g. missense_variant,stop_lost or SO:0001583,SO:0001578. Accepts aliases * 'loss_of_function' and 'protein_altering'. * @param {String} [params.xref] - List of any external reference, these can be genes, proteins or variants. Accepted IDs include HGNC, - * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, ... + * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, HGVS ... * @param {String} [params.biotype] - List of biotypes, e.g. protein_coding. * @param {String} [params.proteinSubstitution] - Protein substitution scores include SIFT and PolyPhen. You can query using the score * {protein_score}[<|>|<=|>=]{number} or the description {protein_score}[~=|=]{description} e.g. polyphen>0.1,sift=tolerant. @@ -103,8 +105,7 @@ export default class Variant extends OpenCGAParentClass { /** Query variant annotations from any saved versions * @param {Object} [params] - The Object containing the following optional parameters: - * @param {String} [params.id] - List of IDs, these can be rs IDs (dbSNP) or variants in the format chrom:start:ref:alt, e.g. - * rs116600158,19:7177679:C:T. + * @param {String} [params.id] - List of variant IDs in the format chrom:start:ref:alt, e.g. 19:7177679:C:T. * @param {String} [params.region] - List of regions, these can be just a single chromosome name or regions in the format chr:start-end, * e.g.: 2,3:100000-200000. * @param {String} [params.include] - Fields included in the response, whole JSON path must be provided. @@ -159,6 +160,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runCohortStats(data, params) { @@ -174,6 +179,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runExomiser(data, params) { @@ -192,6 +201,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runExport(data, params) { @@ -223,6 +236,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runFamilyQc(data, params) { @@ -236,6 +253,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @param {String} [params.file] - Files to remove. * @param {Boolean} [params.resume] - Resume a previously failed indexation. @@ -254,6 +275,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runGatk(data, params) { @@ -271,6 +296,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runGenomePlot(data, params) { @@ -286,6 +315,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runGwas(data, params) { @@ -301,6 +334,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runHrDetect(data, params) { @@ -316,6 +353,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runIndex(data, params) { @@ -331,6 +372,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runIndividualQc(data, params) { @@ -346,6 +391,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runInferredSex(data, params) { @@ -385,6 +434,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runKnockout(data, params) { @@ -400,6 +453,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runMendelianError(data, params) { @@ -485,6 +542,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runMutationalSignature(data, params) { @@ -500,6 +561,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runPlink(data, params) { @@ -519,8 +584,7 @@ export default class Variant extends OpenCGAParentClass { * @param {Number} [params.approximateCountSamplingSize] - Sampling size to get the approximate count. Larger values increase accuracy * but also increase execution time. * @param {String} [params.savedFilter] - Use a saved filter at User level. - * @param {String} [params.id] - List of IDs, these can be rs IDs (dbSNP) or variants in the format chrom:start:ref:alt, e.g. - * rs116600158,19:7177679:C:T. + * @param {String} [params.id] - List of variant IDs in the format chrom:start:ref:alt, e.g. 19:7177679:C:T. * @param {String} [params.region] - List of regions, these can be just a single chromosome name or regions in the format chr:start-end, * e.g.: 2,3:100000-200000. * @param {String} [params.type] - List of types, accepted values are SNV, MNV, INDEL, SV, COPY_NUMBER, COPY_NUMBER_LOSS, @@ -595,7 +659,7 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.ct] - List of SO consequence types, e.g. missense_variant,stop_lost or SO:0001583,SO:0001578. Accepts aliases * 'loss_of_function' and 'protein_altering'. * @param {String} [params.xref] - List of any external reference, these can be genes, proteins or variants. Accepted IDs include HGNC, - * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, ... + * Ensembl genes, dbSNP, ClinVar, HPO, Cosmic, HGVS ... * @param {String} [params.biotype] - List of biotypes, e.g. protein_coding. * @param {String} [params.proteinSubstitution] - Protein substitution scores include SIFT and PolyPhen. You can query using the score * {protein_score}[<|>|<=|>=]{number} or the description {protein_score}[~=|=]{description} e.g. polyphen>0.1,sift=tolerant. @@ -648,6 +712,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runRelatedness(data, params) { @@ -663,6 +731,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runRvtests(data, params) { @@ -733,6 +805,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runSampleEligibility(data, params) { @@ -751,6 +827,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runSampleQc(data, params) { @@ -779,6 +859,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runSample(data, params) { @@ -826,6 +910,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runSampleStats(data, params) { @@ -842,6 +930,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runStatsExport(data, params) { @@ -857,6 +949,10 @@ export default class Variant extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ runStats(data, params) { diff --git a/src/core/clients/opencga/api/VariantOperation.js b/src/core/clients/opencga/api/VariantOperation.js index 8a616734c..0d79024c4 100644 --- a/src/core/clients/opencga/api/VariantOperation.js +++ b/src/core/clients/opencga/api/VariantOperation.js @@ -1,9 +1,12 @@ /** - * Copyright 2015-2020 OpenCB + * Copyright 2015-2024 OpenCB + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -12,7 +15,6 @@ * WARNING: AUTOGENERATED CODE * * This code was generated by a tool. - * Autogenerated on: 2024-05-24 * * Manual changes to this file may cause unexpected behavior in your application. * Manual changes to this file will be overwritten if the code is regenerated. @@ -52,6 +54,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -66,6 +72,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - Project [organization@]project where project can be either the ID or the alias. * @param {String} [params.annotationId] - Annotation identifier. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -82,6 +92,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - Project [organization@]project where project can be either the ID or the alias. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -98,6 +112,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - Project [organization@]project where project can be either the ID or the alias. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -124,6 +142,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -139,6 +161,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -154,6 +180,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -169,6 +199,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -184,6 +218,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -199,6 +237,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - project. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -214,6 +256,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ repairVariantMetadata(data, params) { @@ -228,6 +274,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -243,6 +293,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ pruneVariant(data, params) { @@ -257,6 +311,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -272,6 +330,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -297,6 +359,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @param {String} [params.name] - Unique name of the score within the study. * @param {Boolean} [params.resume] - Resume a previously failed remove. @@ -322,6 +388,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -337,6 +407,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - Project [organization@]project where project can be either the ID or the alias. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -353,6 +427,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ @@ -379,6 +457,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.project] - Project [organization@]project where project can be either the ID or the alias. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -394,6 +476,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @param {String} [params.samples] - Samples to remove. Needs to provide all the samples in the secondary index. * @returns {Promise} Promise object in the form of RestResponse instance. @@ -411,6 +497,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ deleteVariantStats(data, params) { @@ -426,6 +516,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @returns {Promise} Promise object in the form of RestResponse instance. */ indexVariantStats(data, params) { @@ -440,6 +534,10 @@ export default class VariantOperation extends OpenCGAParentClass { * @param {String} [params.jobDescription] - Job description. * @param {String} [params.jobDependsOn] - Comma separated list of existing job IDs the job will depend on. * @param {String} [params.jobTags] - Job tags. + * @param {String} [params.jobScheduledStartTime] - Time when the job is scheduled to start. + * @param {String} [params.jobPriority] - Priority of the job. + * @param {Boolean} [params.jobDryRun] - Flag indicating that the job will be executed in dry-run mode. In this mode, OpenCGA will + * validate that all parameters and prerequisites are correctly set for successful execution, but the job will not actually run. * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. * @returns {Promise} Promise object in the form of RestResponse instance. */ From 344c2f965f717cfec452714edcfd6e8599bde62a Mon Sep 17 00:00:00 2001 From: gpveronica Date: Thu, 1 Aug 2024 13:48:59 +0200 Subject: [PATCH 157/177] wc: Comment out organization update. Some problems found, requires discussion, #TASK-5866, #TASK-5809 Signed-off-by: gpveronica --- .../admin/organization-admin-detail.js | 6 +- .../admin/organization-admin-update.js | 67 +++++++++++++------ 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/webcomponents/organization/admin/organization-admin-detail.js b/src/webcomponents/organization/admin/organization-admin-detail.js index 700a1b483..3a39a59fb 100644 --- a/src/webcomponents/organization/admin/organization-admin-detail.js +++ b/src/webcomponents/organization/admin/organization-admin-detail.js @@ -96,7 +96,7 @@ export default class OrganizationAdminDetail extends LitElement { }, */ "organization-update": { - label: "Edit Organisation", + label: "Edit Organisation (coming soon...)", icon: "far fa-edit", modalId: `${this._prefix}UpdateOrganizationModal`, render: () => this.renderOrganizationUpdate(), @@ -167,7 +167,7 @@ export default class OrganizationAdminDetail extends LitElement {
    -