From 5a36241454202b036bb49b5f163d88f06ebc45e1 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Mon, 27 Nov 2023 17:54:41 +0700 Subject: [PATCH 01/14] tools atl-9 --- js/pages/main.js | 2 + js/pages/tools/const.js | 9 ++ js/pages/tools/index.js | 14 +++ js/pages/tools/routes.js | 16 +++ js/pages/tools/tool-manager.html | 70 +++++++++++++ js/pages/tools/tool-manager.js | 166 +++++++++++++++++++++++++++++++ js/services/AuthAPI.js | 5 + js/services/ToolService.js | 33 ++++++ js/settings.js | 3 +- js/styles/atlas.css | 53 ++++++++++ js/styles/switch-button.css | 47 +++++++++ 11 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 js/pages/tools/const.js create mode 100644 js/pages/tools/index.js create mode 100644 js/pages/tools/routes.js create mode 100644 js/pages/tools/tool-manager.html create mode 100644 js/pages/tools/tool-manager.js create mode 100644 js/services/ToolService.js create mode 100644 js/styles/switch-button.css diff --git a/js/pages/main.js b/js/pages/main.js index 5dffd9f6e..d53917389 100644 --- a/js/pages/main.js +++ b/js/pages/main.js @@ -16,6 +16,7 @@ define( const jobs = require('./jobs/index'); const configuration = require('./configuration/index'); const feedback = require('./feedback/index'); + const tools = require('./tools/index'); // order of nav items in left-nav will appear in the following order: return { @@ -35,6 +36,7 @@ define( jobs, configuration, feedback, + tools }; } ); \ No newline at end of file diff --git a/js/pages/tools/const.js b/js/pages/tools/const.js new file mode 100644 index 000000000..fd99a7f56 --- /dev/null +++ b/js/pages/tools/const.js @@ -0,0 +1,9 @@ +define( + (require, exports) => { + const pageTitle = 'Tools'; + + return { + pageTitle, + }; + } +); \ No newline at end of file diff --git a/js/pages/tools/index.js b/js/pages/tools/index.js new file mode 100644 index 000000000..a6e79cf80 --- /dev/null +++ b/js/pages/tools/index.js @@ -0,0 +1,14 @@ +define( + (require, exports) => { + const ko = require('knockout'); + const buildRoutes = require('./routes'); + + return { + title: ko.i18n('navigation.tools', 'Tools'), + buildRoutes, + navUrl: () => '#/tools', + icon: 'toolbox', + statusCss: () => "" + }; + } +); \ No newline at end of file diff --git a/js/pages/tools/routes.js b/js/pages/tools/routes.js new file mode 100644 index 000000000..8826ad7ce --- /dev/null +++ b/js/pages/tools/routes.js @@ -0,0 +1,16 @@ +define( + (require, factory) => { + const { AuthorizedRoute } = require('pages/Route'); + function routes(router) { + return { + '/tools': new AuthorizedRoute(() => { + require(['pages/tools/tool-manager'], function () { + router.setCurrentView('tool-manager'); + }); + }), + }; + } + + return routes; + } +); \ No newline at end of file diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html new file mode 100644 index 000000000..65a3d616b --- /dev/null +++ b/js/pages/tools/tool-manager.html @@ -0,0 +1,70 @@ + +
+
+
+ +
+
+
+

+ +
+ + + +
+
+

+ +

+ +
+ + +
+
+
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+
+
+ diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js new file mode 100644 index 000000000..690dfa828 --- /dev/null +++ b/js/pages/tools/tool-manager.js @@ -0,0 +1,166 @@ +define([ + 'knockout', + 'text!./tool-manager.html', + 'pages/Page', + 'utils/CommonUtils', + 'services/AuthAPI', + 'services/ToolService', + 'services/MomentAPI', + 'css!styles/switch-button.css', +], function ( + ko, + view, + Page, + commonUtils, + authApi, + toolService, + momentApi +) { + class ToolManage extends Page { + constructor(params) { + super(params); + this.data_tools = ko.observableArray(); + this.loading = ko.observable(); + this.showModalAddTool = ko.observable(false); + this.newName = ko.observable(null); + this.newUrl = ko.observable(null); + this.newDescription = ko.observable(null); + this.toolIsVisible = ko.observable(false); + + this.getValueUrl = this.getValueUrl.bind(this); + this.handleDataAddTool = this.handleDataAddTool.bind(this); + + this.isAdmin = ko.pureComputed(() => { + return authApi.isPermmitedAdmin(); + }); + } + + + handleIsEditing(id) { + const newData = this.data_tools().map((item) => { + if(id === item.id){ + return ({ + ...item, + isEditing: true + }) + } + return item + }) + this.data_tools(newData); + } + + async handleIsEdited(id) { + this.loading(true); + try { + const dataAdjust = this.data_tools().find(tool => tool.id === id); + const data = { + id, + name: dataAdjust.name, + url: dataAdjust.url, + description: dataAdjust.description, + enabled: dataAdjust.enabled + } + const res = await toolService.updateTool(data); + if(res.status === 200){ + this.getToolFromAllPages(); + } + }catch(error){ + console.log('update tool failed', error) + } finally { + this.loading(false); + } + } + + async handleDelete(id) { + this.loading(true); + try { + const res = await toolService.deleteTool(id); + if(res.status === 200){ + this.getToolFromAllPages(); + } + }catch(error){ + console.log('delete tool failed', error) + } finally { + this.loading(false); + this.getToolFromAllPages(); + } + } + + async toggleVisiableTool(){ + this.toolIsVisible(!this.toolIsVisible()) + } + + async handleCheckVisible(id){ + const newData = this.data_tools().map((item) => { + if(id === item.id){ + return ({ + ...item, + enabled: !item.enabled + }) + } + return item + }) + await this.data_tools(newData); + } + + getValueUrl(data, event){ + const newData = this.data_tools().map((item) => { + if(data.id === item.id){ + return ({ + ...item, + url: data.url, + description: data.description + }) + } + return item + }) + this.data_tools(newData); + } + + async handleDataAddTool(data){ + this.loading(true); + try { + const dataPayload = { + name: data.newName(), + description: data.newDescription(), + url: data.newUrl(), + enabled: data.toolIsVisible() + }; + const res = await toolService.createTool(dataPayload); + if(res.status === 200){ + this.getToolFromAllPages(); + this.showModalAddTool(false); + } + }catch(error){ + console.log('add new tool failed', error) + } finally { + this.loading(false); + } + } + + async onPageCreated() { + this.getToolFromAllPages(); + } + + async getToolFromAllPages() { + this.loading(true); + try { + this.data_tools([]); + const dataTools = await toolService.getTools(); + Array.isArray(dataTools) && dataTools.forEach((item, index) => { + const splitDate = momentApi.formatDate(item.createdDate, 'LL').split(','); + const firstFormat = splitDate[0].split(' ').reverse(); + const formatDate = ko.i18n(`common.monthsName.${[firstFormat[1].toLowerCase()]}`, firstFormat[1]); + this.data_tools.push({ + ...item, + createdDate: formatDate, + isEditing: false + })}); + } finally { + this.loading(false); + } + } + } + + return commonUtils.build('tool-manager', ToolManage, view); +}); diff --git a/js/services/AuthAPI.js b/js/services/AuthAPI.js index 6c5a8a891..f92765fbe 100644 --- a/js/services/AuthAPI.js +++ b/js/services/AuthAPI.js @@ -395,6 +395,10 @@ define(function(require, exports) { return isPermitted('cohortdefinition:' + cohortId + ':report:' + sourceKey + ':get'); } + var isPermmitedAdmin = function() { + return isPermitted('admin'); + } + var isPermittedReadJobs = function() { return isPermitted('job:execution:get'); } @@ -615,6 +619,7 @@ define(function(require, exports) { isPermittedClearServerCache, isPermittedViewDataSourceReport, isPermittedViewDataSourceReportDetails, + isPermmitedAdmin, loadUserInfo, TOKEN_HEADER, diff --git a/js/services/ToolService.js b/js/services/ToolService.js new file mode 100644 index 000000000..260360a94 --- /dev/null +++ b/js/services/ToolService.js @@ -0,0 +1,33 @@ +define([ + 'appConfig', + 'services/http'], +function( + appConfig, + httpService +) { + + const ISSUES_PAGE_SIZE = 10; + + function getTools() { + return httpService.doGet(appConfig.webAPIRoot + 'tool').then(({ data }) => data); + } + + function updateTool(tool) { + return httpService.doPut(appConfig.webAPIRoot + 'tool', tool); + } + + function createTool(tool){ + return httpService.doPost(appConfig.webAPIRoot + 'tool', tool); + } + + function deleteTool(id){ + return httpService.doDelete(appConfig.webAPIRoot + `tool/${id}`); + } + + return { + getTools, + updateTool, + createTool, + deleteTool + } +}); \ No newline at end of file diff --git a/js/settings.js b/js/settings.js index ec02fb064..123afcc28 100644 --- a/js/settings.js +++ b/js/settings.js @@ -170,7 +170,8 @@ const settingsObject = { "jquery.dataTables.colVis.css": "css!styles/jquery.dataTables.colVis.css", "jquery.datatables.tabletools.css": "css!styles/jquery.datatables.tabletools.css", "prism.css": "css!styles/prism.css", - "leaflet": "css!../node_modules/leaflet/dist/leaflet.css" + "leaflet": "css!../node_modules/leaflet/dist/leaflet.css", + "switch-button.css": "css!styles/switch-button.css" }, localRefs: { "configuration": "components/configuration", diff --git a/js/styles/atlas.css b/js/styles/atlas.css index 6e314e9ac..726aab96b 100644 --- a/js/styles/atlas.css +++ b/js/styles/atlas.css @@ -2179,3 +2179,56 @@ div.wrapper_ohdsi a { padding: 1rem; padding-bottom: 0; } + +.card-tools { + display: flex; + flex-direction: column; + flex: 1 1; + align-items: flex-end; +} + +.add-btn { + width: 180px; + margin-right: 30px; + margin-top: 10px; +} + +.bg-add { + background-color: #0070dd; +} + +.card-tool-container { + width: 100%; + display: grid; + grid-template-columns: auto auto; + justify-content: space-evenly; + row-gap: 40px; +} + +.card-tool { + border: 3px solid #000; + border-radius: 10px; + width: 400px; + padding: 20px; +} + +.card-tool h3{ + margin-top: 0px; + margin-bottom: 0px; + font-weight: 650; + color: #228BA5; + text-decoration: none; + cursor: pointer; +} + +.flex-between{ + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; +} + +.flex-end{ + display: flex; + justify-content: flex-end; +} \ No newline at end of file diff --git a/js/styles/switch-button.css b/js/styles/switch-button.css new file mode 100644 index 000000000..d9ca77661 --- /dev/null +++ b/js/styles/switch-button.css @@ -0,0 +1,47 @@ +.material-switch > input[type="checkbox"] { + display: none; +} + +.material-switch > label { + cursor: pointer; + height: 0px; + position: relative; + width: 40px; +} + +.material-switch > label::before { + background: rgb(0, 0, 0); + box-shadow: inset 0px 0px 10px rgba(0, 0, 0, 0.5); + border-radius: 8px; + content: ''; + height: 16px; + margin-top: -8px; + position:absolute; + opacity: 0.3; + transition: all 0.4s ease-in-out; + width: 40px; +} + +.material-switch > label::after { + background: rgb(255, 255, 255); + border-radius: 16px; + box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3); + content: ''; + height: 24px; + left: -4px; + margin-top: -8px; + position: absolute; + top: -4px; + transition: all 0.3s ease-in-out; + width: 24px; +} + +.material-switch > .label-witch-enable::before { + background: inherit; + opacity: 0.5; +} + +.material-switch > .label-witch-enable::after { + background: inherit; + left: 20px; +} \ No newline at end of file From d4d452b10f2f051ed86c9ef1fc611f11ce2908f3 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Tue, 28 Nov 2023 13:32:08 +0700 Subject: [PATCH 02/14] tool atl-9 update edit icon & logic when click block card --- js/pages/tools/tool-manager.html | 14 +++++++------- js/pages/tools/tool-manager.js | 8 ++++++++ js/styles/atlas.css | 1 + js/styles/switch-button.css | 4 ++-- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index 65a3d616b..f2dcaa7a1 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -4,14 +4,14 @@
-
+
-

+

- - - + + +

@@ -20,7 +20,7 @@

- +
@@ -56,7 +56,7 @@

- +
diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 690dfa828..92a362910 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -29,6 +29,7 @@ define([ this.getValueUrl = this.getValueUrl.bind(this); this.handleDataAddTool = this.handleDataAddTool.bind(this); + this.handleOpenLink = this.handleOpenLink.bind(this); this.isAdmin = ko.pureComputed(() => { return authApi.isPermmitedAdmin(); @@ -49,6 +50,12 @@ define([ this.data_tools(newData); } + handleOpenLink(data, event){ + if(data.isEditing) return; + if(["editIcon", "deleteIcon", "completeIcon"].includes(event.target.id)) return; + return window.open(data.url, '_blank'); + } + async handleIsEdited(id) { this.loading(true); try { @@ -68,6 +75,7 @@ define([ console.log('update tool failed', error) } finally { this.loading(false); + return false; } } diff --git a/js/styles/atlas.css b/js/styles/atlas.css index 726aab96b..aafae4e8e 100644 --- a/js/styles/atlas.css +++ b/js/styles/atlas.css @@ -2219,6 +2219,7 @@ div.wrapper_ohdsi a { color: #228BA5; text-decoration: none; cursor: pointer; + font-size: 26px; } .flex-between{ diff --git a/js/styles/switch-button.css b/js/styles/switch-button.css index d9ca77661..e876485fa 100644 --- a/js/styles/switch-button.css +++ b/js/styles/switch-button.css @@ -36,12 +36,12 @@ width: 24px; } -.material-switch > .label-witch-enable::before { +.material-switch > .label-switch-enable::before { background: inherit; opacity: 0.5; } -.material-switch > .label-witch-enable::after { +.material-switch > .label-switch-enable::after { background: inherit; left: 20px; } \ No newline at end of file From f3bc49a17ad7d0fba132392e5ba4f3e87abab365 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Tue, 28 Nov 2023 14:15:18 +0700 Subject: [PATCH 03/14] tool atl-9 clear form add tool when completed add tool or cancel form --- js/pages/tools/tool-manager.html | 3 ++- js/pages/tools/tool-manager.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index f2dcaa7a1..a5be0504b 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -33,6 +33,7 @@

window.open(url, '_bl

- +
diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 92a362910..19529147b 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -30,6 +30,8 @@ define([ this.getValueUrl = this.getValueUrl.bind(this); this.handleDataAddTool = this.handleDataAddTool.bind(this); this.handleOpenLink = this.handleOpenLink.bind(this); + this.handleCancelTool = this.handleCancelTool.bind(this); + this.handleClearData = this.handleClearData.bind(this); this.isAdmin = ko.pureComputed(() => { return authApi.isPermmitedAdmin(); @@ -50,6 +52,18 @@ define([ this.data_tools(newData); } + handleClearData(){ + this.newName(null); + this.newDescription(null); + this.newUrl(null); + this.toolIsVisible(false); + this.showModalAddTool(false); + } + + handleCancelTool(){ + this.handleClearData(); + } + handleOpenLink(data, event){ if(data.isEditing) return; if(["editIcon", "deleteIcon", "completeIcon"].includes(event.target.id)) return; @@ -142,6 +156,7 @@ define([ }catch(error){ console.log('add new tool failed', error) } finally { + this.handleClearData(); this.loading(false); } } From b4a6c38826850304c2667c8f92b20c06d70f6f9a Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Wed, 29 Nov 2023 18:14:11 +0700 Subject: [PATCH 04/14] tool atl-9 update multi language for loading text at tools screen --- js/pages/tools/tool-manager.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index a5be0504b..4ef6093ef 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -25,7 +25,7 @@

+
-
+

- +
-

- -

- -
+ + +

+ +
+
+
+

+ +
+
+

+ +
+
+

+ +
+
diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 19529147b..6077787dc 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -36,6 +36,9 @@ define([ this.isAdmin = ko.pureComputed(() => { return authApi.isPermmitedAdmin(); }); + this.showModalAddTool.subscribe((isShow) => { + if(!isShow) this.handleClearData(); + }) } @@ -171,13 +174,11 @@ define([ this.data_tools([]); const dataTools = await toolService.getTools(); Array.isArray(dataTools) && dataTools.forEach((item, index) => { - const splitDate = momentApi.formatDate(item.createdDate, 'LL').split(','); - const firstFormat = splitDate[0].split(' ').reverse(); - const formatDate = ko.i18n(`common.monthsName.${[firstFormat[1].toLowerCase()]}`, firstFormat[1]); this.data_tools.push({ ...item, - createdDate: formatDate, - isEditing: false + createdDate: momentApi.formatDate(item.createdDate, 'DD/MM/YYYY'), + isEditing: false, + updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY') })}); } finally { this.loading(false); diff --git a/js/services/ToolService.js b/js/services/ToolService.js index 260360a94..9285ef130 100644 --- a/js/services/ToolService.js +++ b/js/services/ToolService.js @@ -5,11 +5,14 @@ function( appConfig, httpService ) { - + const ko = require('knockout'); const ISSUES_PAGE_SIZE = 10; function getTools() { - return httpService.doGet(appConfig.webAPIRoot + 'tool').then(({ data }) => data); + return httpService.doGet(appConfig.webAPIRoot + 'tool').then(({ data }) => data) + .catch((err) => { + alert(ko.i18n('tool.error.list', 'Get list tool error, try later !')()); + }); } function updateTool(tool) { diff --git a/js/styles/atlas.css b/js/styles/atlas.css index aafae4e8e..0c3129f42 100644 --- a/js/styles/atlas.css +++ b/js/styles/atlas.css @@ -2181,16 +2181,15 @@ div.wrapper_ohdsi a { } .card-tools { - display: flex; - flex-direction: column; - flex: 1 1; - align-items: flex-end; + top: 30px; + position: relative; } .add-btn { + position: absolute; width: 180px; - margin-right: 30px; - margin-top: 10px; + top: 10px; + right: 20px; } .bg-add { @@ -2198,17 +2197,21 @@ div.wrapper_ohdsi a { } .card-tool-container { - width: 100%; - display: grid; - grid-template-columns: auto auto; - justify-content: space-evenly; - row-gap: 40px; + display: flex; + flex-wrap: wrap; + position: absolute; + margin-top: 70px; + margin-left: 20px; + margin-right: 30px; + row-gap: 12px; + column-gap: 16px; } .card-tool { - border: 3px solid #000; + border: 2.4px solid #000; border-radius: 10px; width: 400px; + max-width: 410px; padding: 20px; } @@ -2216,7 +2219,7 @@ div.wrapper_ohdsi a { margin-top: 0px; margin-bottom: 0px; font-weight: 650; - color: #228BA5; + color: #203D54; text-decoration: none; cursor: pointer; font-size: 26px; From c0587b3c93037fccb900b28238f488eec6caea1b Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Fri, 15 Dec 2023 17:17:19 +0700 Subject: [PATCH 06/14] add shadow to tool card when hover & validate add new tool form --- js/pages/tools/PermissionService.js | 16 +++++++++ js/pages/tools/tool-management.less | 16 +++++++++ js/pages/tools/tool-manager.html | 51 ++++++++++++++++++----------- js/pages/tools/tool-manager.js | 13 ++++++-- js/services/ToolService.js | 16 ++++++--- js/styles/atlas.css | 9 +++-- 6 files changed, 93 insertions(+), 28 deletions(-) create mode 100644 js/pages/tools/PermissionService.js create mode 100644 js/pages/tools/tool-management.less diff --git a/js/pages/tools/PermissionService.js b/js/pages/tools/PermissionService.js new file mode 100644 index 000000000..8adfd9f63 --- /dev/null +++ b/js/pages/tools/PermissionService.js @@ -0,0 +1,16 @@ +define([ + 'services/AuthAPI', +], function ( + AuthAPI, +) { + return class PermissionService { + + static isPermittedCreate() { + return AuthAPI.isPermitted(`admin:post`); + } + + static isPermittedList() { + return AuthAPI.isPermitted(`admin:get`); + } + } +}); diff --git a/js/pages/tools/tool-management.less b/js/pages/tools/tool-management.less new file mode 100644 index 000000000..86899d9de --- /dev/null +++ b/js/pages/tools/tool-management.less @@ -0,0 +1,16 @@ +.modal-footer { + display: table; + width: 100%; + padding: 0; + border: 0; + margin-top: 18px; + + .modal-buttons { + display: table-cell; + text-align: right; + + button + button { + margin-left: 10px !important; + } + } +} \ No newline at end of file diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index 936cbb78b..3acec771d 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -1,23 +1,30 @@ -
+
- -
+ +
+

- +
- - + +
- + +

- + +
@@ -55,28 +62,32 @@

-
- - +
+ + +
-
- - +
+ + +
-
+
- +
- +
-
- - +
diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 6077787dc..cad23f4ba 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -6,7 +6,9 @@ define([ 'services/AuthAPI', 'services/ToolService', 'services/MomentAPI', + './PermissionService', 'css!styles/switch-button.css', + 'less!./tool-management.less', ], function ( ko, view, @@ -14,7 +16,8 @@ define([ commonUtils, authApi, toolService, - momentApi + momentApi, + PermissionService ) { class ToolManage extends Page { constructor(params) { @@ -36,6 +39,9 @@ define([ this.isAdmin = ko.pureComputed(() => { return authApi.isPermmitedAdmin(); }); + this.canReadTools = PermissionService.isPermittedList; + this.canCreateTools = PermissionService.isPermittedCreate; + this.showModalAddTool.subscribe((isShow) => { if(!isShow) this.handleClearData(); }) @@ -92,6 +98,7 @@ define([ console.log('update tool failed', error) } finally { this.loading(false); + this.getToolFromAllPages(); return false; } } @@ -160,6 +167,7 @@ define([ console.log('add new tool failed', error) } finally { this.handleClearData(); + this.getToolFromAllPages(); this.loading(false); } } @@ -178,7 +186,8 @@ define([ ...item, createdDate: momentApi.formatDate(item.createdDate, 'DD/MM/YYYY'), isEditing: false, - updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY') + updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY'), + createdBy: item.createdBy ?? '' })}); } finally { this.loading(false); diff --git a/js/services/ToolService.js b/js/services/ToolService.js index 9285ef130..d73219839 100644 --- a/js/services/ToolService.js +++ b/js/services/ToolService.js @@ -6,7 +6,6 @@ function( httpService ) { const ko = require('knockout'); - const ISSUES_PAGE_SIZE = 10; function getTools() { return httpService.doGet(appConfig.webAPIRoot + 'tool').then(({ data }) => data) @@ -16,15 +15,24 @@ function( } function updateTool(tool) { - return httpService.doPut(appConfig.webAPIRoot + 'tool', tool); + return httpService.doPut(appConfig.webAPIRoot + 'tool', tool) + .catch((err) => { + alert(ko.i18n('tool.error.update', 'Update tool error, try later !')()); + }); } function createTool(tool){ - return httpService.doPost(appConfig.webAPIRoot + 'tool', tool); + return httpService.doPost(appConfig.webAPIRoot + 'tool', tool) + .catch((err) => { + alert(ko.i18n('tool.error.create', 'Create tool error, try later !')()); + }); } function deleteTool(id){ - return httpService.doDelete(appConfig.webAPIRoot + `tool/${id}`); + return httpService.doDelete(appConfig.webAPIRoot + `tool/${id}`) + .catch((err) => { + alert(ko.i18n('tool.error.delete', 'Delete tool error, try later !')()); + }); } return { diff --git a/js/styles/atlas.css b/js/styles/atlas.css index 0c3129f42..6155cb390 100644 --- a/js/styles/atlas.css +++ b/js/styles/atlas.css @@ -2203,8 +2203,7 @@ div.wrapper_ohdsi a { margin-top: 70px; margin-left: 20px; margin-right: 30px; - row-gap: 12px; - column-gap: 16px; + gap: 20px; } .card-tool { @@ -2213,6 +2212,12 @@ div.wrapper_ohdsi a { width: 400px; max-width: 410px; padding: 20px; + transition: all 0.2s ease-out; +} + +.card-tool:hover{ + box-shadow: 2px 5px 12px #bebebe, + -2px -5px 12px #bebebe; } .card-tool h3{ From 4cdff7df08225026151c169098dcbccf17cb132b Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Wed, 31 Jan 2024 14:27:01 +0700 Subject: [PATCH 07/14] check roles in the tool screen --- js/pages/tools/PermissionService.js | 16 ---------------- js/pages/tools/tool-manager.html | 16 +++++++--------- js/pages/tools/tool-manager.js | 21 ++++----------------- 3 files changed, 11 insertions(+), 42 deletions(-) delete mode 100644 js/pages/tools/PermissionService.js diff --git a/js/pages/tools/PermissionService.js b/js/pages/tools/PermissionService.js deleted file mode 100644 index 8adfd9f63..000000000 --- a/js/pages/tools/PermissionService.js +++ /dev/null @@ -1,16 +0,0 @@ -define([ - 'services/AuthAPI', -], function ( - AuthAPI, -) { - return class PermissionService { - - static isPermittedCreate() { - return AuthAPI.isPermitted(`admin:post`); - } - - static isPermittedList() { - return AuthAPI.isPermitted(`admin:get`); - } - } -}); diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index 3acec771d..a48d34733 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -1,25 +1,23 @@ -
-
+

- - + +
-

@@ -40,7 +38,8 @@

- + +

@@ -92,5 +91,4 @@

+ diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index cad23f4ba..69b4016aa 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -6,7 +6,6 @@ define([ 'services/AuthAPI', 'services/ToolService', 'services/MomentAPI', - './PermissionService', 'css!styles/switch-button.css', 'less!./tool-management.less', ], function ( @@ -17,7 +16,6 @@ define([ authApi, toolService, momentApi, - PermissionService ) { class ToolManage extends Page { constructor(params) { @@ -35,12 +33,11 @@ define([ this.handleOpenLink = this.handleOpenLink.bind(this); this.handleCancelTool = this.handleCancelTool.bind(this); this.handleClearData = this.handleClearData.bind(this); + this.isAuthenticated = authApi.isAuthenticated; this.isAdmin = ko.pureComputed(() => { return authApi.isPermmitedAdmin(); }); - this.canReadTools = PermissionService.isPermittedList; - this.canCreateTools = PermissionService.isPermittedCreate; this.showModalAddTool.subscribe((isShow) => { if(!isShow) this.handleClearData(); @@ -90,10 +87,7 @@ define([ description: dataAdjust.description, enabled: dataAdjust.enabled } - const res = await toolService.updateTool(data); - if(res.status === 200){ - this.getToolFromAllPages(); - } + await toolService.updateTool(data); }catch(error){ console.log('update tool failed', error) } finally { @@ -106,10 +100,7 @@ define([ async handleDelete(id) { this.loading(true); try { - const res = await toolService.deleteTool(id); - if(res.status === 200){ - this.getToolFromAllPages(); - } + await toolService.deleteTool(id); }catch(error){ console.log('delete tool failed', error) } finally { @@ -158,11 +149,7 @@ define([ url: data.newUrl(), enabled: data.toolIsVisible() }; - const res = await toolService.createTool(dataPayload); - if(res.status === 200){ - this.getToolFromAllPages(); - this.showModalAddTool(false); - } + await toolService.createTool(dataPayload); }catch(error){ console.log('add new tool failed', error) } finally { From 58e17f6c03cd69625cb86b9d177f7c0a830d995f Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Tue, 5 Mar 2024 13:47:01 +0700 Subject: [PATCH 08/14] Change createdDate, updatedDate data type date to data type timestamp --- js/pages/tools/tool-manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 69b4016aa..98ccbf573 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -171,9 +171,9 @@ define([ Array.isArray(dataTools) && dataTools.forEach((item, index) => { this.data_tools.push({ ...item, - createdDate: momentApi.formatDate(item.createdDate, 'DD/MM/YYYY'), + createdDate: momentApi.formatDate(item.createdDate, 'DD/MM/YYYY HH:mm:ss'), isEditing: false, - updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY'), + updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY HH:mm:ss'), createdBy: item.createdBy ?? '' })}); } finally { From 87304b2135250de66c58bcfc3075bccbff01c8d0 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Fri, 15 Mar 2024 18:04:15 +0700 Subject: [PATCH 09/14] update role functions in the tool screen --- js/pages/tools/PermissionService.js | 24 ++++++++++++++++++++++++ js/pages/tools/tool-manager.html | 16 +++++++++------- js/pages/tools/tool-manager.js | 13 +++++++++---- js/services/AuthAPI.js | 5 ----- 4 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 js/pages/tools/PermissionService.js diff --git a/js/pages/tools/PermissionService.js b/js/pages/tools/PermissionService.js new file mode 100644 index 000000000..008825f3f --- /dev/null +++ b/js/pages/tools/PermissionService.js @@ -0,0 +1,24 @@ +define([ + 'services/AuthAPI', +], function ( + AuthAPI, +) { + return class PermissionService { + + static isPermittedReadTools() { + return AuthAPI.isPermitted('tool:get'); + } + + static isPermittedCreateTool() { + return AuthAPI.isPermitted('tool:post'); + } + + static isPermittedUpdateTool() { + return AuthAPI.isPermitted('tool:put'); + } + + static isPermittedDeleteTool() { + return AuthAPI.isPermitted('tool:*:delete'); + } + } +}); \ No newline at end of file diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index a48d34733..181467bc9 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -2,19 +2,21 @@
-
+

- - + +
@@ -91,4 +93,4 @@

true"> + diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 98ccbf573..0b916f577 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -6,6 +6,7 @@ define([ 'services/AuthAPI', 'services/ToolService', 'services/MomentAPI', + './PermissionService', 'css!styles/switch-button.css', 'less!./tool-management.less', ], function ( @@ -16,6 +17,7 @@ define([ authApi, toolService, momentApi, + PermissionService ) { class ToolManage extends Page { constructor(params) { @@ -35,9 +37,10 @@ define([ this.handleClearData = this.handleClearData.bind(this); this.isAuthenticated = authApi.isAuthenticated; - this.isAdmin = ko.pureComputed(() => { - return authApi.isPermmitedAdmin(); - }); + this.canReadTools = PermissionService.isPermittedReadTools; + this.canCreateTool = PermissionService.isPermittedCreateTool; + this.canUpdateTool = PermissionService.isPermittedUpdateTool; + this.canDeleteTool = PermissionService.isPermittedDeleteTool; this.showModalAddTool.subscribe((isShow) => { if(!isShow) this.handleClearData(); @@ -160,7 +163,9 @@ define([ } async onPageCreated() { - this.getToolFromAllPages(); + if(this.canReadTools()){ + this.getToolFromAllPages(); + } } async getToolFromAllPages() { diff --git a/js/services/AuthAPI.js b/js/services/AuthAPI.js index f92765fbe..6c5a8a891 100644 --- a/js/services/AuthAPI.js +++ b/js/services/AuthAPI.js @@ -395,10 +395,6 @@ define(function(require, exports) { return isPermitted('cohortdefinition:' + cohortId + ':report:' + sourceKey + ':get'); } - var isPermmitedAdmin = function() { - return isPermitted('admin'); - } - var isPermittedReadJobs = function() { return isPermitted('job:execution:get'); } @@ -619,7 +615,6 @@ define(function(require, exports) { isPermittedClearServerCache, isPermittedViewDataSourceReport, isPermittedViewDataSourceReportDetails, - isPermmitedAdmin, loadUserInfo, TOKEN_HEADER, From 0021628ff9b38e46b40db19a3f3cfe4b3ad0cb00 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Mon, 1 Apr 2024 10:04:18 -0600 Subject: [PATCH 10/14] Show text when the author is not present --- js/pages/tools/tool-manager.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index 181467bc9..8dd6c4b20 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -41,7 +41,7 @@

- +

From 41e4cef5a819acbab903babb7b85e743abb9bef4 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Tue, 2 Apr 2024 19:32:43 +0700 Subject: [PATCH 11/14] fix update tools data property --- js/pages/tools/tool-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/pages/tools/tool-manager.js b/js/pages/tools/tool-manager.js index 0b916f577..9d499e69e 100644 --- a/js/pages/tools/tool-manager.js +++ b/js/pages/tools/tool-manager.js @@ -179,7 +179,7 @@ define([ createdDate: momentApi.formatDate(item.createdDate, 'DD/MM/YYYY HH:mm:ss'), isEditing: false, updatedDate: momentApi.formatDate(item.modifiedDate, 'DD/MM/YYYY HH:mm:ss'), - createdBy: item.createdBy ?? '' + createdBy: item.createdByName ?? '' })}); } finally { this.loading(false); From f4260fe13b8db0272f35a10c986a5aa4f2f67c83 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Tue, 9 Apr 2024 19:34:02 +0700 Subject: [PATCH 12/14] Displays an icon indicating enabled/disabled --- js/pages/tools/tool-manager.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index 8dd6c4b20..a91fecba5 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -43,6 +43,9 @@

+
+ +

From 9ad8d93d1d182aba7634bbfaa2bd099cc12958c5 Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Thu, 11 Apr 2024 15:28:42 +0700 Subject: [PATCH 13/14] Display status card tool by text for admin --- js/pages/tools/tool-manager.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index a91fecba5..e9d8481c6 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -44,7 +44,8 @@

- +

+
From cef5a30c22b876fd48d88bd3b859e96ae245ec4c Mon Sep 17 00:00:00 2001 From: Juan Carlos Namendi Pineda Date: Thu, 11 Apr 2024 11:31:17 -0600 Subject: [PATCH 14/14] -Add label to View card showing toggle icon enabled/disabled -Add label to edit tool --- js/pages/tools/tool-manager.html | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/js/pages/tools/tool-manager.html b/js/pages/tools/tool-manager.html index e9d8481c6..522818d30 100644 --- a/js/pages/tools/tool-manager.html +++ b/js/pages/tools/tool-manager.html @@ -24,10 +24,13 @@

- -
- - + +
+ +
+ + +
@@ -43,9 +46,9 @@

-
-

- +
+

+