From e2e26450aeba0e8bd3169d38f1b0cedcaa159640 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen <117440893+nhthinh-axonivy@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:45:36 +0700 Subject: [PATCH 01/21] =?UTF-8?q?bug/IVYPORTAL-18051-Portal-Dashboard-show?= =?UTF-8?q?s-no-permission-screen-when-=E2=80=A6=20(#1280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bug/IVYPORTAL-18051-Portal-Dashboard-shows-no-permission-screen-when-dashboards-is-empty _ adapt logic _ import default dashboard --- .../addon/portal/generic/menu/MenuView.java | 18 ++++--- .../portal/generic/bean/DashboardBean.java | 53 +++++++++++-------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/AxonIvyPortal/portal/src/ch/addon/portal/generic/menu/MenuView.java b/AxonIvyPortal/portal/src/ch/addon/portal/generic/menu/MenuView.java index 668df5c4364..25dc3cf939d 100644 --- a/AxonIvyPortal/portal/src/ch/addon/portal/generic/menu/MenuView.java +++ b/AxonIvyPortal/portal/src/ch/addon/portal/generic/menu/MenuView.java @@ -91,8 +91,6 @@ public void buildPortalLeftMenu(ITask workingTask, boolean isWorkingOnATask) { mainMenuModel = new DefaultMenuModel(); mainMenuModel.getElements().add(buildDashboardItem()); // menuIndex = 0 - - List subMenuItems = PortalMenuNavigator.callSubMenuItemsProcess(); int menuIndex = 1; for (SubMenuItem subMenu : subMenuItems) { @@ -152,13 +150,17 @@ private MenuElement buildDashboardItem() { String mainMenuDisplayName = mainMenuEntryService.getNameInCurrentLocale(); String mainMenuIcon = mainMenuEntryService.getMenuIcon(); - var subItemDashboards = getSubItemDashboards(); + List subItemDashboards = getSubItemDashboards(); if (subItemDashboards.size() > 1) { return buildDashboardGroupMenu(subItemDashboards, dashboardTitle, mainMenuDisplayName, mainMenuIcon, currentLanguage, dashboardLink); + } else if (subItemDashboards.size() == 1) { + Dashboard dashboard = subItemDashboards.getFirst(); + String localizedTitle = getLocalizedTitle(dashboard, currentLanguage, dashboardTitle); + return buildSingleDashboardMenu(localizedTitle, dashboardId, dashboardLink, dashboard.getIcon()); } - - return buildSingleDashboardMenu(dashboardTitle, dashboardId, dashboardLink); + + return buildSingleDashboardMenu(dashboardTitle, "", dashboardLink, ""); } private String determineDashboardLink() { @@ -240,9 +242,11 @@ private void setMenuExpansion(DefaultSubMenu dashboardGroupMenu) { } } - private MenuElement buildSingleDashboardMenu(String dashboardTitle, String dashboardId, String dashboardLink) { + private MenuElement buildSingleDashboardMenu(String dashboardTitle, String dashboardId, String dashboardLink, + String dashboardIcon) { var dashboardMenu = new PortalMenuBuilder(dashboardTitle, MenuKind.DASHBOARD, this.isWorkingOnATask) - .icon(PortalMenuItem.DEFAULT_DASHBOARD_ICON).url(dashboardLink).workingTaskId(this.workingTaskId).build(); + .icon(StringUtils.isNoneEmpty(dashboardIcon) ? dashboardIcon : PortalMenuItem.DEFAULT_DASHBOARD_ICON) + .url(dashboardLink).workingTaskId(this.workingTaskId).build(); if (StringUtils.isBlank(dashboardId)) { dashboardId = dashboardMenu.getId(); diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java index b573ec9dde1..d4061a3be47 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java @@ -91,33 +91,17 @@ public void init() { currentDashboardIndex = 0; dashboards = collectDashboards(); - if (isReadOnlyMode) { MenuView menuView = (MenuView) ManagedBeans.get("menuView"); menuView.updateDashboardCache(dashboards); } - if (CollectionUtils.isNotEmpty(DashboardUtils.getDashboardsWithoutMenuItem())) { + if (CollectionUtils.isNotEmpty(DashboardUtils.getDashboardsWithoutMenuItem()) + || isRequestPathForMainOrDetailModification()) { updateSelectedDashboardIdFromSessionAttribute(); - currentDashboardIndex = findIndexOfDashboardById(selectedDashboardId); - selectedDashboard = dashboards.get(currentDashboardIndex); - - String selectedDashboardName = selectedDashboard.getTitles().stream() - .filter(displayName -> displayName.getLocale().equals(Ivy.session().getContentLocale())) - .findFirst() - .orElseGet(() -> selectedDashboard.getTitles().get(0)).getValue(); - setSelectedDashboardName(selectedDashboardName); - initShareDashboardLink(selectedDashboard); - // can not find dashboard by dashboard id session in view mode - if (StringUtils.isBlank(selectedDashboardId) - || (!selectedDashboardId.equalsIgnoreCase(selectedDashboard.getId()) - && DashboardUtils.getDashboardsWithoutMenuItem().size() > 1)) { - DashboardUtils.storeDashboardInSession(selectedDashboard.getId()); - } - if (isReadOnlyMode) { - DashboardUtils.highlightDashboardMenuItem(selectedDashboard.getId()); - } - } + updateSelectedDashboard(); + storeAndHighlightDashboardIfRequired(); + } buildWidgetModels(selectedDashboard); isRunningTaskWhenClickingOnTaskInList = GlobalSettingService.getInstance() .findGlobalSettingValue(GlobalVariable.DEFAULT_BEHAVIOUR_WHEN_CLICKING_ON_LINE_IN_TASK_LIST) @@ -131,6 +115,33 @@ private void buildClientStatisticApiUri() { .getExternalContext().getRequestContextPath() + "/api/statistics/data"; } + private boolean isRequestPathForMainOrDetailModification() { + String requestPath = Ivy.request().getRequestPath(); + return requestPath.endsWith("/PortalMainDashboard.xhtml") + || requestPath.endsWith("/PortalDashboardDetailModification.xhtml"); + } + + private void updateSelectedDashboard() { + currentDashboardIndex = findIndexOfDashboardById(selectedDashboardId); + selectedDashboard = dashboards.get(currentDashboardIndex); + + String selectedDashboardName = selectedDashboard.getTitles().stream() + .filter(displayName -> displayName.getLocale().equals(Ivy.session().getContentLocale())).findFirst() + .orElseGet(() -> selectedDashboard.getTitles().get(0)).getValue(); + setSelectedDashboardName(selectedDashboardName); + initShareDashboardLink(selectedDashboard); + } + + private void storeAndHighlightDashboardIfRequired() { + if (StringUtils.isBlank(selectedDashboardId) || (!selectedDashboardId.equalsIgnoreCase(selectedDashboard.getId()) + && DashboardUtils.getDashboardsWithoutMenuItem().size() > 1)) { + DashboardUtils.storeDashboardInSession(selectedDashboard.getId()); + } + if (isReadOnlyMode) { + DashboardUtils.highlightDashboardMenuItem(selectedDashboard.getId()); + } + } + protected List collectDashboards() { return DashboardUtils.collectDashboards(); } From fe9dca1dff5aba017b7cbc069d12822ed834ea3e Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Thu, 12 Dec 2024 15:05:43 +0700 Subject: [PATCH 02/21] IVYPORTAL-18072 SPIKE: Evaluate the full screen issue with new case and task list - Implemented --- .../config/variables/Portal/Dashboard.json | 4 +- .../portal/generic/bean/DashboardBean.java | 6 ++ .../portalkit/dto/dashboard/Dashboard.java | 15 +++++ .../addon/portalkit/util/DashboardUtils.java | 9 +++ .../restricted/DashboardTemplate.xhtml | 14 +++-- .../webContent/resources/js/dashboard.js | 62 +++++++++++++++++-- .../resources/js/responsive-toolkit.js | 5 +- 7 files changed, 101 insertions(+), 14 deletions(-) diff --git a/AxonIvyPortal/portal/config/variables/Portal/Dashboard.json b/AxonIvyPortal/portal/config/variables/Portal/Dashboard.json index c222e3a9993..c3116189da4 100644 --- a/AxonIvyPortal/portal/config/variables/Portal/Dashboard.json +++ b/AxonIvyPortal/portal/config/variables/Portal/Dashboard.json @@ -377,7 +377,7 @@ ], "layout": { "w": 12, - "h": 8, + "h": 12, "x": 0, "y": 0 }, @@ -489,7 +489,7 @@ ], "layout": { "w": 12, - "h": 8, + "h": 12, "x": 0, "y": 0 }, diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java index b573ec9dde1..16d6c18d2a8 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/DashboardBean.java @@ -123,6 +123,12 @@ public void init() { .findGlobalSettingValue(GlobalVariable.DEFAULT_BEHAVIOUR_WHEN_CLICKING_ON_LINE_IN_TASK_LIST) .equals(BehaviourWhenClickingOnLineInTaskList.RUN_TASK.name()); + // Set responsive option for default task list and case list + if (DashboardUtils.isDefaultCaseListDashboard(selectedDashboard) + || DashboardUtils.isDefaultTaskListDashboard(selectedDashboard)) { + selectedDashboard.setIsResponsive(true); + } + buildClientStatisticApiUri(); } diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/dashboard/Dashboard.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/dashboard/Dashboard.java index 0896ec2dc67..234df2d8057 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/dashboard/Dashboard.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/dashboard/Dashboard.java @@ -35,9 +35,13 @@ public class Dashboard extends AbstractConfiguration implements Serializable { private String displayedPermission; private Boolean isTopMenu; + @JsonIgnore + private Boolean isResponsive; + public Dashboard() { // Set default values isTopMenu = false; + isResponsive = false; } public Dashboard(Dashboard dashboard) { @@ -54,6 +58,7 @@ public Dashboard(Dashboard dashboard) { permissionDTOs = dashboard.permissionDTOs; displayedPermission = dashboard.displayedPermission; isTopMenu = dashboard.isTopMenu; + isResponsive = dashboard.isResponsive; } public String getTitle() { @@ -146,6 +151,16 @@ public void setIsTopMenu(Boolean isTopMenu) { this.isTopMenu = isTopMenu; } + @JsonIgnore + public Boolean getIsResponsive() { + return isResponsive; + } + + @JsonIgnore + public void setIsResponsive(Boolean isResponsive) { + this.isResponsive = isResponsive; + } + @Override public int hashCode() { final int prime = 31; diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DashboardUtils.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DashboardUtils.java index f42e63ec3d2..5a66ea4269e 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DashboardUtils.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DashboardUtils.java @@ -327,4 +327,13 @@ public static void updatePropertiesToNullIfCurrentValueIsDefaultValue(List "").contentEquals(DEFAULT_TASK_LIST_DASHBOARD); + } + + public static boolean isDefaultCaseListDashboard(Dashboard dashboard) { + return Optional.ofNullable(dashboard).map(Dashboard::getId) + .orElseGet(() -> "").contentEquals(DEFAULT_CASE_LIST_DASHBOARD); + } } diff --git a/AxonIvyPortal/portal/webContent/layouts/restricted/DashboardTemplate.xhtml b/AxonIvyPortal/portal/webContent/layouts/restricted/DashboardTemplate.xhtml index 2c2a30aa326..b6e4256d46c 100644 --- a/AxonIvyPortal/portal/webContent/layouts/restricted/DashboardTemplate.xhtml +++ b/AxonIvyPortal/portal/webContent/layouts/restricted/DashboardTemplate.xhtml @@ -20,6 +20,8 @@ } $(document).ready(function () { + loadGrid(#{managedBean.selectedDashboard.isResponsive}); + updateDashboardWhenResizeWindow(#{managedBean.selectedDashboard.isResponsive}); setTimeout(() => { initStatistics(); }, 50); @@ -48,7 +50,7 @@ - + @@ -203,13 +205,13 @@ + oncomplete="PF('escalation-task-dialog').hide();loadGrid(#{managedBean.selectedDashboard.isResponsive});initStatistics();" update="grid-stack dashboard-title-container" /> + taskId="#{taskWidgetBean.selectedTaskItemId}" componentToUpdate="grid-stack dashboard-title-container" onCompletedCallback="loadGrid(#{managedBean.selectedDashboard.isResponsive}); initStatistics();"/> @@ -308,7 +310,7 @@ + onclick="PF('share-dashboard-dialog').show(); return false;" styleClass="js-share-dashboard-link" /> 0) { + dashboardModificationPageHeaderHeight = ($('.js-dashboard__header').outerHeight(true) || 0) + additionalHeightForResizeHandler; + } + + // calculate available height then divide by default number of cells to get height value for each cell + gridCellHeight = (PortalLayout.getAvailableHeight() - announcementHeight + - shareDashboardLinkHeight - dashboardModificationPageHeaderHeight) / defaultNumberOfCells; + + // If the calculated cell height is less than or equals to 0, use the default cell height instead + gridCellHeight = gridCellHeight > 0 ? gridCellHeight : defaultCellHeight; + } + grids = GridStack.initAll({ - column: 12, - cellHeight: 100, + column: defaultNumberOfCells, + cellHeight: gridCellHeight, resizable: { handles: 'e, se, s, sw, w' } @@ -534,4 +561,29 @@ function udateResizableTablesWhenResizeWidget() { } }); +} + +function updateDashboardWhenResizeWindow(isResponsiveDashboard) { + if (!isResponsiveDashboard) { + return; + } + + // resize timeout ID + let resizeTimeout; + + window.addEventListener('resize', function () { + clearTimeout(resizeTimeout); + + resizeTimeout = setTimeout(function () { + + // Check if the window height has changed + if (window.innerHeight !== windowHeight) { + + // Call the remote command 'updateDashboardWidget' + updateDashboardWidget(); + + windowHeight = window.innerHeight; + } + }, 1000); // Delay execution by 1 sec to avoid send multiple requests + }); } \ No newline at end of file diff --git a/AxonIvyPortal/portal/webContent/resources/js/responsive-toolkit.js b/AxonIvyPortal/portal/webContent/resources/js/responsive-toolkit.js index 893f3cdd016..9a26eac17fa 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/responsive-toolkit.js +++ b/AxonIvyPortal/portal/webContent/resources/js/responsive-toolkit.js @@ -87,7 +87,10 @@ var PortalLayout = { getAvailableHeight: function () { var $layoutMain = $('.js-layout-main'); - var layoutMainPadding = parseInt($layoutMain.css('padding-top') || 0) + parseInt($layoutMain.css('padding-bottom') || 0); + const roundedLayoutMainPaddingTop = parseInt(Math.round(parseFloat($layoutMain.css('padding-top') || 0)) || 0); + const roundedLayoutMainPaddingBottom = parseInt(Math.round(parseFloat($layoutMain.css('padding-bottom') || 0)) || 0); + var layoutMainPadding = roundedLayoutMainPaddingTop + roundedLayoutMainPaddingBottom; + return window.innerHeight - layoutMainPadding; }, From 955e9b90cd90159788e5736b1d69bcffa394a8c6 Mon Sep 17 00:00:00 2001 From: Luong Minh Luat <157108501+lmluat-axonivy@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:40:46 +0700 Subject: [PATCH 03/21] feature/IVYPORTAL-18028-High-Failure-to-use-HTTPS-or-SFTP-URL-in-Maven-artifact-upload-download-Two-occurrences (#1298) - Use HTTPS URL in maven artifact download --- AxonIvyPortal/portal-product/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AxonIvyPortal/portal-product/pom.xml b/AxonIvyPortal/portal-product/pom.xml index 86f1e4da881..fa802272f14 100644 --- a/AxonIvyPortal/portal-product/pom.xml +++ b/AxonIvyPortal/portal-product/pom.xml @@ -24,7 +24,7 @@ Axonivy Repo release-repo - http://repo.axonivy.com/artifactory/libs-release/ + https://repo.axonivy.com/artifactory/libs-release/ default @@ -35,7 +35,7 @@ Axonivy Repo snapshots-repo - http://repo.axonivy.com/artifactory/libs-snapshot/ + https://repo.axonivy.com/artifactory/libs-snapshot/ default From 622cb7a15f34d828c996a868dfcf7a9cbfba41da Mon Sep 17 00:00:00 2001 From: Luong Minh Luat <157108501+lmluat-axonivy@users.noreply.github.com> Date: Fri, 13 Dec 2024 13:56:51 +0700 Subject: [PATCH 04/21] feature/IVYPORTAL-18028-High-Failure-to-use-HTTPS-or-SFTP-URL-in-Maven-artifact-upload-download-Two-occurrences-12 (#1305) - Update URL with HTTPS in maven download/upload --- AxonIvyPortal/portal-product/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AxonIvyPortal/portal-product/pom.xml b/AxonIvyPortal/portal-product/pom.xml index 86f1e4da881..fa802272f14 100644 --- a/AxonIvyPortal/portal-product/pom.xml +++ b/AxonIvyPortal/portal-product/pom.xml @@ -24,7 +24,7 @@ Axonivy Repo release-repo - http://repo.axonivy.com/artifactory/libs-release/ + https://repo.axonivy.com/artifactory/libs-release/ default @@ -35,7 +35,7 @@ Axonivy Repo snapshots-repo - http://repo.axonivy.com/artifactory/libs-snapshot/ + https://repo.axonivy.com/artifactory/libs-snapshot/ default From c1f9ee57d8e1304a23cb89cf8ad9a451c30cb16d Mon Sep 17 00:00:00 2001 From: Tung Le Date: Fri, 13 Dec 2024 17:55:59 +0700 Subject: [PATCH 05/21] feature/IVYPORTAL-18068 Update test data of performance test engine - Create a a business case has 50 technical cases, each technical case has 100 tasks --- .../portalKit_test/DataCreationData.d.json | 4 + .../Start Processes/DataCreation.p.json | 314 +++++++++++++++++- 2 files changed, 308 insertions(+), 10 deletions(-) diff --git a/AxonIvyPortal/PortalKitTestHelper/dataclasses/portalKit_test/DataCreationData.d.json b/AxonIvyPortal/PortalKitTestHelper/dataclasses/portalKit_test/DataCreationData.d.json index c4840de0bb5..031f769941c 100644 --- a/AxonIvyPortal/PortalKitTestHelper/dataclasses/portalKit_test/DataCreationData.d.json +++ b/AxonIvyPortal/PortalKitTestHelper/dataclasses/portalKit_test/DataCreationData.d.json @@ -60,5 +60,9 @@ }, { "name" : "jsonKey", "type" : "String" + }, { + "name" : "persistedCounter", + "type" : "java.lang.Integer", + "modifiers" : [ "PERSISTENT" ] } ] } \ No newline at end of file diff --git a/AxonIvyPortal/PortalKitTestHelper/processes/Start Processes/DataCreation.p.json b/AxonIvyPortal/PortalKitTestHelper/processes/Start Processes/DataCreation.p.json index b948a8a66b2..1d48309753b 100644 --- a/AxonIvyPortal/PortalKitTestHelper/processes/Start Processes/DataCreation.p.json +++ b/AxonIvyPortal/PortalKitTestHelper/processes/Start Processes/DataCreation.p.json @@ -1004,11 +1004,6 @@ }, { "id" : "f112", "type" : "TaskSwitchGateway", - "config" : { - "tasks" : [ { - "id" : "TaskA" - } ] - }, "visual" : { "at" : { "x" : 1472, "y" : 192 } }, @@ -1282,11 +1277,6 @@ }, { "id" : "S10-f5", "type" : "TaskSwitchGateway", - "config" : { - "tasks" : [ { - "id" : "TaskA" - } ] - }, "visual" : { "at" : { "x" : 640, "y" : 256 } }, @@ -1914,5 +1904,309 @@ "connect" : [ { "id" : "f191", "to" : "f186", "color" : "default" } ] + }, { + "id" : "f145", + "type" : "RequestStart", + "name" : "createABusinessCaseHasLotsOfTasksCases", + "config" : { + "signature" : "createBusinessCaseHasLotsOfTasksCases", + "request" : { + "name" : "Create a business case has lots of tasks cases" + }, + "task" : { + "name" : "First task of the case" + }, + "case" : { + "name" : "Business case has lots of tasks cases" + } + }, + "visual" : { + "at" : { "x" : 64, "y" : 2144 }, + "labelOffset" : { "x" : 17, "y" : 49 } + }, + "connect" : [ + { "id" : "f147", "to" : "f146" } + ] + }, { + "id" : "f146", + "type" : "Script", + "name" : "Init", + "config" : { + "output" : { + "code" : "in.counter = 0;" + } + }, + "visual" : { + "at" : { "x" : 216, "y" : 2144 } + }, + "connect" : [ + { "id" : "f216", "to" : "f217" } + ] + }, { + "id" : "f148", + "type" : "RequestStart", + "name" : "createACaseHasLotsOfTasks", + "config" : { + "signature" : "createCaseHasLotsOfTasks", + "request" : { + "isHttpRequestable" : false + }, + "triggerable" : true, + "task" : { + "name" : "First task of the case", + "responsible" : { + "activator" : "SYSTEM" + } + }, + "case" : { + "name" : "Technical case" + } + }, + "visual" : { + "at" : { "x" : 64, "y" : 2352 } + }, + "connect" : [ + { "id" : "f192", "to" : "f149" } + ] + }, { + "id" : "f149", + "type" : "Script", + "name" : "Init", + "config" : { + "output" : { + "code" : "in.persistedCounter = 0;" + } + }, + "visual" : { + "at" : { "x" : 216, "y" : 2352 } + }, + "connect" : [ + { "id" : "f194", "to" : "f224" } + ] + }, { + "id" : "f193", + "type" : "TaskSwitchGateway", + "config" : { + "tasks" : [ { + "id" : "TaskA", + "name" : "<%= \"Task A \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskB", + "name" : "<%= \"Task B \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskC", + "name" : "<%= \"Task C \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskD", + "name" : "<%= \"Task D \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskE", + "name" : "<%= \"Task E \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskF", + "name" : "<%= \"Task F \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskG", + "name" : "<%= \"Task G \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskH", + "name" : "<%= \"Task H \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskI", + "name" : "<%= \"Task I \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>" + }, { + "id" : "TaskJ", + "name" : "<%= \"Task J \" + in1.persistedCounter + \" of case \" + ivy.case.getId() %>", + "responsible" : { + "activator" : "SYSTEM" + } + } ] + }, + "visual" : { + "at" : { "x" : 480, "y" : 2352 }, + "labelOffset" : { "x" : 14, "y" : 34 } + }, + "connect" : [ + { "id" : "f196", "to" : "f195", "condition" : "ivp==\"TaskA.ivp\"" }, + { "id" : "f198", "to" : "f197", "condition" : "ivp==\"TaskB.ivp\"" }, + { "id" : "f207", "to" : "f199", "condition" : "ivp==\"TaskC.ivp\"" }, + { "id" : "f208", "to" : "f200", "condition" : "ivp==\"TaskD.ivp\"" }, + { "id" : "f209", "to" : "f205", "condition" : "ivp==\"TaskE.ivp\"" }, + { "id" : "f210", "to" : "f206", "condition" : "ivp==\"TaskF.ivp\"" }, + { "id" : "f211", "to" : "f201", "condition" : "ivp==\"TaskG.ivp\"" }, + { "id" : "f212", "to" : "f202", "condition" : "ivp==\"TaskH.ivp\"" }, + { "id" : "f213", "to" : "f227", "condition" : "ivp==\"TaskI.ivp\"" }, + { "id" : "f228", "to" : "f204", "via" : [ { "x" : 480, "y" : 2272 } ], "condition" : "ivp==\"TaskJ.ivp\"" } + ] + }, { + "id" : "f195", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 608, "y" : 2352 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f197", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 608, "y" : 2384 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f199", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 608, "y" : 2416 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f200", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 608, "y" : 2448 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f201", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 544, "y" : 2480 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f202", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 512, "y" : 2480 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f205", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 608, "y" : 2480 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f206", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 576, "y" : 2480 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } + }, { + "id" : "f215", + "type" : "TriggerCall", + "name" : "Create a case has lots of tasks", + "config" : { + "processCall" : "Start Processes/DataCreation:createCaseHasLotsOfTasks()" + }, + "visual" : { + "at" : { "x" : 576, "y" : 2144 } + }, + "connect" : [ + { "id" : "f219", "to" : "f222" } + ] + }, { + "id" : "f217", + "type" : "Alternative", + "name" : "counter < 50", + "config" : { + "conditions" : { + "f218" : "in.counter < 50" + } + }, + "visual" : { + "at" : { "x" : 384, "y" : 2144 }, + "labelOffset" : { "x" : -24, "y" : -8 } + }, + "connect" : [ + { "id" : "f218", "to" : "f215", "label" : { + "name" : "Yes" + }, "color" : "default" }, + { "id" : "f221", "to" : "f220", "label" : { + "name" : "No" + } } + ] + }, { + "id" : "f220", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 384, "y" : 2208 } + } + }, { + "id" : "f222", + "type" : "Script", + "name" : "Increase counter", + "config" : { + "output" : { + "code" : [ + "import java.lang.Thread;", + "in.counter++;", + "Thread.sleep(1000);", + "ivy.log.warn(\"Increased counter {0} of business case {1}\", in.counter, ivy.case.getId());" + ] + } + }, + "visual" : { + "at" : { "x" : 576, "y" : 2064 } + }, + "connect" : [ + { "id" : "f223", "to" : "f217", "via" : [ { "x" : 384, "y" : 2064 } ] } + ] + }, { + "id" : "f204", + "type" : "Script", + "name" : "Increase counter", + "config" : { + "output" : { + "code" : [ + "import java.lang.Thread;", + "in.persistedCounter++;", + "Thread.sleep(100);", + "ivy.log.warn(\"Increased counter {0} of case {1}\", in.persistedCounter, ivy.case.getId());" + ] + } + }, + "visual" : { + "at" : { "x" : 384, "y" : 2272 } + }, + "connect" : [ + { "id" : "f203", "to" : "f224" } + ] + }, { + "id" : "f224", + "type" : "Alternative", + "name" : "counter < 10", + "config" : { + "conditions" : { + "f225" : "in.persistedCounter < 10" + } + }, + "visual" : { + "at" : { "x" : 384, "y" : 2352 }, + "labelOffset" : { "x" : -24, "y" : -8 } + }, + "connect" : [ + { "id" : "f225", "to" : "f193", "label" : { + "name" : "Yes" + }, "color" : "default", "var" : "in1" }, + { "id" : "f226", "to" : "f214", "label" : { + "name" : "No" + } } + ] + }, { + "id" : "f214", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 384, "y" : 2480 } + } + }, { + "id" : "f227", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 480, "y" : 2480 }, + "labelOffset" : { "x" : 13, "y" : 33 } + } } ] } \ No newline at end of file From e5754fe8579c76e1d767ca09bf8b3480cbfc8ee8 Mon Sep 17 00:00:00 2001 From: Tung Le <76459536+lttung-axonivy@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:03:00 +0700 Subject: [PATCH 06/21] Update portal_walkthrough_testplan.jmx for new test data (#1306) --- .../portal-selenium-test/jmeter/portal_walkthrough_testplan.jmx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AxonIvyPortal/portal-selenium-test/jmeter/portal_walkthrough_testplan.jmx b/AxonIvyPortal/portal-selenium-test/jmeter/portal_walkthrough_testplan.jmx index b8279fee7d0..68a9ea29895 100644 --- a/AxonIvyPortal/portal-selenium-test/jmeter/portal_walkthrough_testplan.jmx +++ b/AxonIvyPortal/portal-selenium-test/jmeter/portal_walkthrough_testplan.jmx @@ -1650,7 +1650,7 @@ true - Create test data with category attach to one business case + Business case has lots of tasks cases = true case-default_case_list_dashboard_case_1:quick-search-form:quick-search-input-0 From 6b4aa0a6b01893ad132f81c8974d54fe25ebe00d Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Mon, 16 Dec 2024 10:32:07 +0700 Subject: [PATCH 07/21] IVYPORTAL-18029 High - Client-side cross-site scripting - Fixed security check --- .../portal/webContent/resources/js/iframe-task-template.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js index 7e32a706de4..02d1c0b63f7 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js +++ b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js @@ -1,15 +1,14 @@ var invalidIFrameSrcPath = false; let taskUrl = new URLSearchParams(window.location.search).get("taskUrl"); -let updateIframeSrc = (newSrc) => { - getPortalIframe().src = newSrc; -} + if (taskUrl){ if(taskUrl.endsWith('blank')){ window.history.back(document.referrer); } - updateIframeSrc(taskUrl) + getPortalIframe().src = taskUrl; } + loadIframe(false); var recheckFrameTimer; function loadIframe(recheckIndicator) { From f4cf1709e1971d7aeaf8da62e54746eb49cd2fe8 Mon Sep 17 00:00:00 2001 From: Tung Le <76459536+lttung-axonivy@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:39:35 +0700 Subject: [PATCH 08/21] Updated all pom build.plugin.version=12.0.0, ivy.engine.version=12.0.2 (#1308) Co-authored-by: wawa-axonivy --- AxonIvyPortal/PortalKitTestHelper/pom.xml | 4 ++-- AxonIvyPortal/portal-components/pom.xml | 4 ++-- AxonIvyPortal/portal-migration/pom.xml | 4 ++-- AxonIvyPortal/portal-selenium-test/customized_pom.xml | 4 ++-- .../portal-selenium-test/document_screenshot_pom.xml | 4 ++-- AxonIvyPortal/portal-selenium-test/pom.xml | 4 ++-- AxonIvyPortal/portal/pom.xml | 4 ++-- Showcase/InternalSupport/pom.xml | 4 ++-- Showcase/portal-components-examples/pom.xml | 4 ++-- Showcase/portal-developer-examples/pom.xml | 4 ++-- Showcase/portal-user-examples/pom.xml | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/AxonIvyPortal/PortalKitTestHelper/pom.xml b/AxonIvyPortal/PortalKitTestHelper/pom.xml index 9b1856defa9..79b9a3a82a9 100644 --- a/AxonIvyPortal/PortalKitTestHelper/pom.xml +++ b/AxonIvyPortal/PortalKitTestHelper/pom.xml @@ -7,8 +7,8 @@ 9.1.0.0-SNAPSHOT iar - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/AxonIvyPortal/portal-components/pom.xml b/AxonIvyPortal/portal-components/pom.xml index 7f1813bde05..ab5abfd88c3 100644 --- a/AxonIvyPortal/portal-components/pom.xml +++ b/AxonIvyPortal/portal-components/pom.xml @@ -16,8 +16,8 @@ - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/AxonIvyPortal/portal-migration/pom.xml b/AxonIvyPortal/portal-migration/pom.xml index fab872d578f..ae3e7224111 100644 --- a/AxonIvyPortal/portal-migration/pom.xml +++ b/AxonIvyPortal/portal-migration/pom.xml @@ -6,8 +6,8 @@ 9.4.0 iar - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 diff --git a/AxonIvyPortal/portal-selenium-test/customized_pom.xml b/AxonIvyPortal/portal-selenium-test/customized_pom.xml index 09309492b2a..254cb3b2a27 100644 --- a/AxonIvyPortal/portal-selenium-test/customized_pom.xml +++ b/AxonIvyPortal/portal-selenium-test/customized_pom.xml @@ -6,8 +6,8 @@ 9.1.0.0-SNAPSHOT iar - 12.0.0-SNAPSHOT - 12.0.1 + 12.0.0 + 12.0.2 UTF-8 diff --git a/AxonIvyPortal/portal-selenium-test/document_screenshot_pom.xml b/AxonIvyPortal/portal-selenium-test/document_screenshot_pom.xml index 09bffcb6333..ce671e75e8b 100644 --- a/AxonIvyPortal/portal-selenium-test/document_screenshot_pom.xml +++ b/AxonIvyPortal/portal-selenium-test/document_screenshot_pom.xml @@ -6,8 +6,8 @@ 9.1.0.0-SNAPSHOT pom - 12.0.0-SNAPSHOT - 12.0.1 + 12.0.0 + 12.0.2 UTF-8 diff --git a/AxonIvyPortal/portal-selenium-test/pom.xml b/AxonIvyPortal/portal-selenium-test/pom.xml index 9b533775639..59acebbe3a2 100644 --- a/AxonIvyPortal/portal-selenium-test/pom.xml +++ b/AxonIvyPortal/portal-selenium-test/pom.xml @@ -7,8 +7,8 @@ 9.1.0.0-SNAPSHOT iar - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/AxonIvyPortal/portal/pom.xml b/AxonIvyPortal/portal/pom.xml index 5c7f9309e22..706213bcb9e 100644 --- a/AxonIvyPortal/portal/pom.xml +++ b/AxonIvyPortal/portal/pom.xml @@ -17,8 +17,8 @@ - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/Showcase/InternalSupport/pom.xml b/Showcase/InternalSupport/pom.xml index 6a74a3701a5..dcbc2f4958e 100644 --- a/Showcase/InternalSupport/pom.xml +++ b/Showcase/InternalSupport/pom.xml @@ -6,8 +6,8 @@ 9.1.0.0-SNAPSHOT iar - 12.0.0-SNAPSHOT - 12.0.1 + 12.0.0 + 12.0.2 UTF-8 diff --git a/Showcase/portal-components-examples/pom.xml b/Showcase/portal-components-examples/pom.xml index 076878621ed..43de80ab6a9 100644 --- a/Showcase/portal-components-examples/pom.xml +++ b/Showcase/portal-components-examples/pom.xml @@ -17,8 +17,8 @@ - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/Showcase/portal-developer-examples/pom.xml b/Showcase/portal-developer-examples/pom.xml index 470188c062f..ab5a66f5505 100644 --- a/Showcase/portal-developer-examples/pom.xml +++ b/Showcase/portal-developer-examples/pom.xml @@ -17,8 +17,8 @@ - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 diff --git a/Showcase/portal-user-examples/pom.xml b/Showcase/portal-user-examples/pom.xml index 20e8b2c6f51..f6ca58fd61a 100644 --- a/Showcase/portal-user-examples/pom.xml +++ b/Showcase/portal-user-examples/pom.xml @@ -17,8 +17,8 @@ - 12.0.1 - 12.0.0-SNAPSHOT + 12.0.2 + 12.0.0 UTF-8 From c8474f3527c145dfb73b299376350a8b955a8899 Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Mon, 16 Dec 2024 10:40:42 +0700 Subject: [PATCH 09/21] IVYPORTAL-18029 High - Client-side cross-site scripting - Try to fix Client-side cross-site scripting --- .../portal/webContent/resources/js/iframe-task-template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js index 02d1c0b63f7..6eb27d0635e 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js +++ b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js @@ -6,7 +6,7 @@ if (taskUrl){ if(taskUrl.endsWith('blank')){ window.history.back(document.referrer); } - getPortalIframe().src = taskUrl; + getPortalIframe().src = new URLSearchParams(window.location.search).get("taskUrl"); } loadIframe(false); From 960f08804fd6b55a6577517685fa9c0abc1347f6 Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Mon, 16 Dec 2024 14:02:09 +0700 Subject: [PATCH 10/21] IVYPORTAL-18029 High - Client-side cross-site scripting - Apply new approach --- .../generic/bean/IFrameTaskTemplateBean.java | 7 +++ .../restricted/IFrameTaskTemplate.xhtml | 49 ++++++++++++------- .../resources/js/iframe-task-template.js | 10 ---- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java index c7b6b99bcd2..af864d25651 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java @@ -54,6 +54,7 @@ public class IFrameTaskTemplateBean extends AbstractTaskTemplateBean implements public static final String PORTAL_GROWL_MESSGE_PARAM = "portalGrowlMessage"; private static final String DEFAULT_TASK_ICON = "si si-task-list-edit"; private static final String TASK_ICON = "taskIcon"; + private static final String TASK_URL = "taskUrl"; private int currentProcessStep; private List processSteps; @@ -74,6 +75,12 @@ public class IFrameTaskTemplateBean extends AbstractTaskTemplateBean implements private Long caseId = null; + public String getTaskUrl() { + return Optional.ofNullable(FacesContext.getCurrentInstance() + .getExternalContext().getRequestParameterMap().get(TASK_URL)) + .orElse(StringUtils.EMPTY); + } + public void useTaskInIFrame() { keepOverridePortalGrowl(); Map requestParamMap = getRequestParameterMap(); diff --git a/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml b/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml index c9cda06739d..7b521bc862c 100644 --- a/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml +++ b/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml @@ -70,24 +70,24 @@ **2. JavaScript-Based Configuration:** Example: + window.taskName = "Approve Investment"; + window.taskIcon = "si si-bulb"; + window.isHideTaskName = false; + window.caseId = "123456"; + window.isHideCaseInfo = false; + window.currentProcessStep = 0; + window.processSteps = ["Create Investment Request", "Approve Investment Request"]; + // Convert Java List of steps to JSON format if needed: + window.processSteps = #{portalComponentUtilsBean.convertToJSON(data.steps)}; + window.isShowAllSteps = true; + window.processChainDirection = "VERTICAL"; + window.processChainShape = "LINE"; + window.isHideTaskAction = false; + window.isWorkingOnATask = false; + window.announcementInvisible = false; + window.isCardFrame = true; + window.viewName = "TASK_DETAIL"; + --> @@ -113,6 +113,19 @@ + diff --git a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js index 6eb27d0635e..46a55531bc3 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js +++ b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js @@ -1,15 +1,5 @@ var invalidIFrameSrcPath = false; -let taskUrl = new URLSearchParams(window.location.search).get("taskUrl"); - -if (taskUrl){ - if(taskUrl.endsWith('blank')){ - window.history.back(document.referrer); - } - getPortalIframe().src = new URLSearchParams(window.location.search).get("taskUrl"); -} - -loadIframe(false); var recheckFrameTimer; function loadIframe(recheckIndicator) { var iframe = getPortalIframe(); From f3e17576ba1d6fbef14b120019fd4be902fe508f Mon Sep 17 00:00:00 2001 From: Nam Mai <117440763+mnhnam-axonivy@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:00:59 +0700 Subject: [PATCH 11/21] IVYPORTAL-18029: Security findings- Client-side cross-site scripting (#1310) * feature/IVYPORTAL-18028-High-Failure-to-use-HTTPS-or-SFTP-URL-in-Maven-artifact-upload-download-Two-occurrences-12 (#1305) * IVYPORTAL-18029 High - Client-side cross-site scripting - Apply new approach to load taskUrl from server --- .../generic/bean/IFrameTaskTemplateBean.java | 7 +++ .../restricted/IFrameTaskTemplate.xhtml | 49 ++++++++++++------- .../resources/js/iframe-task-template.js | 11 ----- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java index c7b6b99bcd2..af864d25651 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/IFrameTaskTemplateBean.java @@ -54,6 +54,7 @@ public class IFrameTaskTemplateBean extends AbstractTaskTemplateBean implements public static final String PORTAL_GROWL_MESSGE_PARAM = "portalGrowlMessage"; private static final String DEFAULT_TASK_ICON = "si si-task-list-edit"; private static final String TASK_ICON = "taskIcon"; + private static final String TASK_URL = "taskUrl"; private int currentProcessStep; private List processSteps; @@ -74,6 +75,12 @@ public class IFrameTaskTemplateBean extends AbstractTaskTemplateBean implements private Long caseId = null; + public String getTaskUrl() { + return Optional.ofNullable(FacesContext.getCurrentInstance() + .getExternalContext().getRequestParameterMap().get(TASK_URL)) + .orElse(StringUtils.EMPTY); + } + public void useTaskInIFrame() { keepOverridePortalGrowl(); Map requestParamMap = getRequestParameterMap(); diff --git a/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml b/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml index c9cda06739d..7b521bc862c 100644 --- a/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml +++ b/AxonIvyPortal/portal/webContent/layouts/restricted/IFrameTaskTemplate.xhtml @@ -70,24 +70,24 @@ **2. JavaScript-Based Configuration:** Example: + window.taskName = "Approve Investment"; + window.taskIcon = "si si-bulb"; + window.isHideTaskName = false; + window.caseId = "123456"; + window.isHideCaseInfo = false; + window.currentProcessStep = 0; + window.processSteps = ["Create Investment Request", "Approve Investment Request"]; + // Convert Java List of steps to JSON format if needed: + window.processSteps = #{portalComponentUtilsBean.convertToJSON(data.steps)}; + window.isShowAllSteps = true; + window.processChainDirection = "VERTICAL"; + window.processChainShape = "LINE"; + window.isHideTaskAction = false; + window.isWorkingOnATask = false; + window.announcementInvisible = false; + window.isCardFrame = true; + window.viewName = "TASK_DETAIL"; + --> @@ -113,6 +113,19 @@ + diff --git a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js index 7e32a706de4..46a55531bc3 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js +++ b/AxonIvyPortal/portal/webContent/resources/js/iframe-task-template.js @@ -1,16 +1,5 @@ var invalidIFrameSrcPath = false; -let taskUrl = new URLSearchParams(window.location.search).get("taskUrl"); -let updateIframeSrc = (newSrc) => { - getPortalIframe().src = newSrc; -} -if (taskUrl){ - if(taskUrl.endsWith('blank')){ - window.history.back(document.referrer); - } - updateIframeSrc(taskUrl) -} -loadIframe(false); var recheckFrameTimer; function loadIframe(recheckIndicator) { var iframe = getPortalIframe(); From c770f8c666c636c728627fbf42327d03f544afb0 Mon Sep 17 00:00:00 2001 From: "Nam.Chu" Date: Tue, 17 Dec 2024 09:53:17 +0700 Subject: [PATCH 12/21] IVYPORTAL-18031 Medium - DOM text reinterpreted as HTML - Implement --- AxonIvyPortal/portal/webContent/resources/js/chat.js | 11 ++++++++++- .../portal/webContent/resources/js/welcome-widget.js | 11 +++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/AxonIvyPortal/portal/webContent/resources/js/chat.js b/AxonIvyPortal/portal/webContent/resources/js/chat.js index 24291ab046c..020e46607f9 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/chat.js +++ b/AxonIvyPortal/portal/webContent/resources/js/chat.js @@ -733,7 +733,7 @@ function View(uri) } } else { var userDom = document.createElement('li'); - userDom.innerHTML = $('.js-no-users-of-role').val(); + userDom.innerHTML = escapeHtml($('.js-no-users-of-role').val()); userList.appendChild(userDom); } roleGroupDom.appendChild(userList) @@ -742,6 +742,15 @@ function View(uri) } PF('participants-list-dialog').initPosition(); } + + function escapeHtml(unsafe){ + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } function initCloneGroup(groupTemplate, groupId) { var cloneGroup = groupTemplate.cloneNode(true); diff --git a/AxonIvyPortal/portal/webContent/resources/js/welcome-widget.js b/AxonIvyPortal/portal/webContent/resources/js/welcome-widget.js index f8d858969a0..a3090dc29e7 100644 --- a/AxonIvyPortal/portal/webContent/resources/js/welcome-widget.js +++ b/AxonIvyPortal/portal/webContent/resources/js/welcome-widget.js @@ -1,3 +1,11 @@ +function escapeHtml(unsafe){ + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} WelcomeWidgetConfiguration = { oldImageStyleClass : '', @@ -11,7 +19,6 @@ WelcomeWidgetConfiguration = { this.updateStyleClasses(); this.updatePreviewImageFit(); }, - updatePreviewText : function(isGreeting) { var previewDialog = $('#new-widget-configuration-dialog'); var welcomeText = previewDialog.find('.js-welcome-text-input.language-to-preview').get(0).value; @@ -19,7 +26,7 @@ WelcomeWidgetConfiguration = { if (isGreeting == 'true' || (isGreeting == undefined && $('.js-greeting-text').length != 0)) { welcomeText = previewDialog.find('.js-greeting-text.language-to-preview').get(0).innerHTML + welcomeText; } - $('#new-widget-configuration-dialog').find('.js-preview-text').get(0).innerHTML = welcomeText; + $('#new-widget-configuration-dialog').find('.js-preview-text').get(0).innerHTML = escapeHtml(welcomeText); }, updatePreviewTextPosition : function() { From bdf9f32a60f5d95583a9abc1926749be771751d6 Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Tue, 17 Dec 2024 11:01:49 +0700 Subject: [PATCH 13/21] IVYPORTAL-18029 Security findings- Client-side cross-site scripting - Fixed GUI test --- .../com/axonivy/portal/selenium/page/TemplatePage.java | 4 ++++ .../axonivy/portal/selenium/test/LanguageSettingTest.java | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TemplatePage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TemplatePage.java index 4038d8afe67..952b993f09e 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TemplatePage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TemplatePage.java @@ -481,6 +481,10 @@ public NewDashboardPage openTaskList() { return openMainMenu().selectTaskMenu(); } + public void waitForTaskTitleAppear() { + waitForElementDisplayed(By.id("title"), true); + } + public void waitForIFrameContentVisible() { waitForIFrameScreenshotSizeGreaterThan(IFRAME_SCREENSHOT_FILE_SIZE_AT_MINIMUM); } diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/LanguageSettingTest.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/LanguageSettingTest.java index f0b988a2334..8699cc2c955 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/LanguageSettingTest.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/LanguageSettingTest.java @@ -8,6 +8,7 @@ import com.axonivy.portal.selenium.common.NavigationHelper; import com.axonivy.portal.selenium.page.MainMenuPage; import com.axonivy.portal.selenium.page.NewDashboardPage; +import com.axonivy.portal.selenium.page.TaskIFrameTemplatePage; import com.axonivy.portal.selenium.page.TopMenuTaskWidgetPage; import com.axonivy.portal.selenium.page.UserProfilePage; import com.axonivy.portal.selenium.page.WorkingTaskDialogFromUserProfilePage; @@ -26,9 +27,10 @@ public void setup() { public void testChangeLanguageWhenWorkingOnTask() { NavigationHelper.navigateToTaskList(); TopMenuTaskWidgetPage taskWidget = new TopMenuTaskWidgetPage(); - taskWidget.startTaskIFrameByIndex(0); + TaskIFrameTemplatePage taskPage = taskWidget.startTaskIFrameByIndex(0); taskWidget.switchBackToParent(); - taskWidget.clickOnMyProfile(); + taskPage.waitForTaskTitleAppear(); + taskPage.clickOnMyProfile(); WorkingTaskDialogFromUserProfilePage workingTaskDialogPage = new WorkingTaskDialogFromUserProfilePage(); workingTaskDialogPage.leaveTask(); UserProfilePage userProfilePage = new UserProfilePage(); From e2ce1b2c34855242bc5aff37a8f76c8b99342141 Mon Sep 17 00:00:00 2001 From: mnhnam-axonivy Date: Tue, 17 Dec 2024 14:45:37 +0700 Subject: [PATCH 14/21] IVYPORTAL-18072 SPIKE: Evaluate the full screen issue with new case and task list - Handled feedback: make the dashboard load from memory responsiveness --- .../ch/ivy/addon/portalkit/util/DefaultDashboardUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DefaultDashboardUtils.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DefaultDashboardUtils.java index f092c03fb23..7c996cbaee0 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DefaultDashboardUtils.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/util/DefaultDashboardUtils.java @@ -53,7 +53,7 @@ public class DefaultDashboardUtils { ], "layout": { "w": 12, - "h": 8, + "h": 12, "x": 0, "y": 0 }, @@ -168,7 +168,7 @@ public class DefaultDashboardUtils { ], "layout": { "w": 12, - "h": 8, + "h": 12, "x": 0, "y": 0 }, From 003cd3675065d7a11f9b717bf45208d515222ffc Mon Sep 17 00:00:00 2001 From: Vu Tong <129731357+tphvu-axonivy@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:11:57 +0700 Subject: [PATCH 15/21] IVYPORTAL-18063-bring-back-default-sort-for-task-case-widget-LE (#1301) - implement default sort in edit widget - update GUI tests - handle multiple ajax call in resizing mode --- .../page/CaseEditWidgetNewDashBoardPage.java | 12 ++++++++ .../page/TaskEditWidgetNewDashBoardPage.java | 17 +++++++++++ .../DashboardEditCaseWidgetTest.java | 27 +++++++++++++++++ .../DashboardEditTaskWidgetTest.java | 29 +++++++++++++++++++ .../component/CaseWidget/CaseWidget.xhtml | 6 ++-- .../component/TaskWidget/TaskWidget.xhtml | 7 +++-- .../document-screenshot-selenide/Jenkinsfile | 2 +- 7 files changed, 93 insertions(+), 7 deletions(-) diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseEditWidgetNewDashBoardPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseEditWidgetNewDashBoardPage.java index 240f8b4b48b..0ac3272b52e 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseEditWidgetNewDashBoardPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseEditWidgetNewDashBoardPage.java @@ -424,4 +424,16 @@ public void resizeColumn() { .clickAndHold(element) .perform(); } + + public void clickOnCaseNameColumn() { + $("div[id$='case-widget-preview:dashboard-cases']").shouldBe(appear, DEFAULT_TIMEOUT) + .$("th[id$='dashboard-cases-columns:1']").shouldBe(getClickableCondition()).click(); + } + + public SelenideElement getFirstCaseOfCaseWidget() { + $("div[id$='case-widget-preview:dashboard-cases']").shouldBe(appear, DEFAULT_TIMEOUT).$$("table tbody tr").get(0).shouldBe(appear, + DEFAULT_TIMEOUT); + return $("div[id$='case-widget-preview:dashboard-cases']").$$("table tbody tr").get(0); + } + } diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskEditWidgetNewDashBoardPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskEditWidgetNewDashBoardPage.java index f0c8a6497d8..efd88f36f55 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskEditWidgetNewDashBoardPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskEditWidgetNewDashBoardPage.java @@ -478,4 +478,21 @@ public SelenideElement getExpandModeCheckbox() { public void clickOnExpandModeCheckbox() { getExpandModeCheckbox().shouldBe(getClickableCondition(), DEFAULT_TIMEOUT).click(); } + + public void clickOnTaskNameColumn() { + $("div[id$='task-widget-preview:dashboard-tasks']").shouldBe(appear, DEFAULT_TIMEOUT) + .$("th[id$='dashboard-tasks-columns:3']").shouldBe(getClickableCondition()).click(); + } + + public void clickOnTaskPriorityColumn() { + $("div[id$='task-widget-preview:dashboard-tasks']").shouldBe(appear, DEFAULT_TIMEOUT) + .$("th[id$='dashboard-tasks-columns:1']").shouldBe(getClickableCondition()).click(); + } + + public SelenideElement getFirstTaskOfTaskWidget() { + $("div[id$='task-widget-preview:dashboard-tasks']").shouldBe(appear, DEFAULT_TIMEOUT).$$("table tbody tr").get(0).shouldBe(appear, + DEFAULT_TIMEOUT); + return $("div[id$='task-widget-preview:dashboard-tasks']").$$("table tbody tr").get(0); + } + } \ No newline at end of file diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditCaseWidgetTest.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditCaseWidgetTest.java index bc6f4702b75..3d55583f38e 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditCaseWidgetTest.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditCaseWidgetTest.java @@ -1,5 +1,7 @@ package com.axonivy.portal.selenium.test.dashboard; +import static com.codeborne.selenide.Condition.text; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.Dimension; @@ -12,6 +14,7 @@ import com.axonivy.portal.selenium.common.ScreenshotUtils; import com.axonivy.portal.selenium.common.TestAccount; import com.axonivy.portal.selenium.page.CaseEditWidgetNewDashBoardPage; +import com.axonivy.portal.selenium.page.CaseWidgetNewDashBoardPage; import com.axonivy.portal.selenium.page.DashboardConfigurationPage; import com.axonivy.portal.selenium.page.NewDashboardDetailsEditPage; import com.codeborne.selenide.CollectionCondition; @@ -19,6 +22,10 @@ @IvyWebTest public class DashboardEditCaseWidgetTest extends BaseTest { private static final String NAME_STR = "Name"; + private static final String YOUR_CASES_WIDGET = "Your Cases"; + + private static final String ALPHA_COMPANY = "Alpha Company"; + private static final String ORDER_PIZZA = " Order Pizza"; @Override @BeforeEach @@ -201,4 +208,24 @@ private NewDashboardDetailsEditPage gotoEditPublicDashboardPage() { return modificationPage.navigateToEditDashboardDetailsByName("Dashboard"); } + @Test + public void testDefaultSortOnCaseWidget() { + redirectToRelativeLink(createCaseWithTechnicalCaseUrl); + redirectToRelativeLink(createAlphaCompanyUrl); + + LinkNavigator.redirectToPortalDashboardConfiguration(); + var configurationPage = new DashboardConfigurationPage(); + var modificationPage = configurationPage.openEditPublicDashboardsPage(); + modificationPage.navigateToEditDashboardDetailsByName("Dashboard"); + + CaseWidgetNewDashBoardPage caseWidget = new CaseWidgetNewDashBoardPage(YOUR_CASES_WIDGET); + CaseEditWidgetNewDashBoardPage caseEditWidgetPage = caseWidget.openEditWidget(); + + caseEditWidgetPage.clickOnCaseNameColumn(); + caseEditWidgetPage.getFirstCaseOfCaseWidget().shouldHave(text(ALPHA_COMPANY), DEFAULT_TIMEOUT);; + + caseEditWidgetPage.clickOnCaseNameColumn(); + caseEditWidgetPage.getFirstCaseOfCaseWidget().shouldHave(text(ORDER_PIZZA), DEFAULT_TIMEOUT);; + + } } diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditTaskWidgetTest.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditTaskWidgetTest.java index bf56c48e4ae..1fffa4e4867 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditTaskWidgetTest.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/test/dashboard/DashboardEditTaskWidgetTest.java @@ -1,5 +1,7 @@ package com.axonivy.portal.selenium.test.dashboard; +import static com.codeborne.selenide.Condition.text; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -12,10 +14,15 @@ import com.axonivy.portal.selenium.page.DashboardConfigurationPage; import com.axonivy.portal.selenium.page.NewDashboardDetailsEditPage; import com.axonivy.portal.selenium.page.TaskEditWidgetNewDashBoardPage; +import com.axonivy.portal.selenium.page.TaskWidgetNewDashBoardPage; import com.codeborne.selenide.CollectionCondition; @IvyWebTest public class DashboardEditTaskWidgetTest extends BaseTest { + private static final String YOUR_TASKS_WIDGET = "Your Tasks"; + private static final String MATERNITY_LEAVE_REQUEST = "Maternity Leave Request"; + private static final String SICK_LEAVE_REQUEST = "Sick Leave Request"; + private NewDashboardDetailsEditPage newDashboardDetailsEditPage; @Override @@ -165,4 +172,26 @@ public void testFilterResponsible() { taskWidget.applyFilter(); taskWidget.countAllTasks().shouldHave(CollectionCondition.size(0)); } + + @Test + public void testDefaultSortOnTaskWidget() { + LinkNavigator.redirectToPortalDashboardConfiguration(); + var configurationPage = new DashboardConfigurationPage(); + var modificationPage = configurationPage.openEditPublicDashboardsPage(); + modificationPage.navigateToEditDashboardDetailsByName("Dashboard"); + + TaskWidgetNewDashBoardPage taskWidget = new TaskWidgetNewDashBoardPage(YOUR_TASKS_WIDGET); + TaskEditWidgetNewDashBoardPage taskEditWidgetPage = taskWidget.openEditTaskWidget(); + + // sort by task priority + taskEditWidgetPage.clickOnTaskPriorityColumn(); + taskEditWidgetPage.getFirstTaskOfTaskWidget(); + taskEditWidgetPage.getFirstTaskOfTaskWidget().shouldHave(text(SICK_LEAVE_REQUEST), DEFAULT_TIMEOUT); + + // sort by task name + taskEditWidgetPage.clickOnTaskNameColumn(); + taskEditWidgetPage.getFirstTaskOfTaskWidget(); + taskEditWidgetPage.getFirstTaskOfTaskWidget().shouldHave(text(MATERNITY_LEAVE_REQUEST), DEFAULT_TIMEOUT); + + } } diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/CaseWidget/CaseWidget.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/CaseWidget/CaseWidget.xhtml index a955c99272a..6d37265bc9f 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/CaseWidget/CaseWidget.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/CaseWidget/CaseWidget.xhtml @@ -52,7 +52,7 @@ - + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/TaskWidget/TaskWidget.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/TaskWidget/TaskWidget.xhtml index d3ed08f9797..ea674839278 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/TaskWidget/TaskWidget.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/TaskWidget/TaskWidget.xhtml @@ -23,7 +23,7 @@ - @@ -52,7 +52,7 @@ + diff --git a/build/document-screenshot-selenide/Jenkinsfile b/build/document-screenshot-selenide/Jenkinsfile index 7d77ac2d8b7..49823be4f78 100644 --- a/build/document-screenshot-selenide/Jenkinsfile +++ b/build/document-screenshot-selenide/Jenkinsfile @@ -4,7 +4,7 @@ pipeline { options { buildDiscarder(logRotator(numToKeepStr: '60', artifactNumToKeepStr: '60')) } - + triggers { cron('0 15 * * *') } From b310a723b1d00ea95564080f648024a9c5cac7d8 Mon Sep 17 00:00:00 2001 From: Luong Minh Luat <157108501+lmluat-axonivy@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:37:17 +0700 Subject: [PATCH 16/21] Feature/ivyportal 18032 UI facelift conflict (#1311) * feature/IVYPORTAL-18032-UI-facelift-conflict - Add border in Actions menu of Task widget * feature/IVYPORTAL-18032-UI-facelift-conflict - Add border in actions menu for case widget * feature/IVYPORTAL-18032-UI-facelift-conflict - Update Edit external link UI * feature/IVYPORTAL-18032-UI-facelift-conflict - Add error message when uploading file fail * feature/IVYPORTAL-18032-UI-facelift-conflict - Update link and button following guidelines * feature/IVYPORTAL-18032-UI-facelift-conflict - Update UI of delete button * feature/IVYPORTAL-18032-UI-facelift-conflict - Update UI of remove/delete button * feature/IVYPORTAL-18032-UI-facelift-conflict - Change icon of action menu * feature/IVYPORTAL-18032-UI-facelift-conflict - Update jenkinsfile * feature/IVYPORTAL-18032-UI-facelift-conflict - Update jenkins file * feature/IVYPORTAL-18032-UI-facelift-conflict - Update UI of destroy button in CaseItemDetails and TaskItemDetails * feature/IVYPORTAL-18032-UI-facelift-conflict - Update height of upload image in external link * feature/IVYPORTAL-18032-UI-facelift-conflict - Update GUI tests * feature/IVYPORTAL-18032-UI-facelift-conflict - Update screenshot tests * feature/IVYPORTAL-18032-UI-facelift-conflict - Update UI delete document button * feature/IVYPORTAL-18032-UI-facelift-conflict - Upload document-screenshot.js file * feature/IVYPORTAL-18032-UI-facelift-conflict - Update screenshot test * feature/IVYPORTAL-18032-UI-facelift-conflict - Update reset filter in task widget filter * feature/IVYPORTAL-18032-UI-facelift-conflict - Update document * feature/IVYPORTAL-18032-UI-facelift-conflict - Update screenshot tests * Revert "feature/IVYPORTAL-18032-UI-facelift-conflict" This reverts commit 0f4b1540fad46145c7d632d1ed45054e4d95ef6b. * Revert "feature/IVYPORTAL-18032-UI-facelift-conflict" This reverts commit 3c38c3192f676a4df03300135ec60c2572ca2ec7. * feature/IVYPORTAL-18032-UI-facelift-conflict - Update UI of process image * feature/IVYPORTAL-18032-UI-facelift-conflict - Handle feedback --- .../resources/js/document-screenshot.js | 2 +- .../screenshot/PortalCasesScreenshotTest.java | 2 +- .../PortalProcessesScreenshotTest.java | 3 +- .../portal/selenium/page/CaseDetailsPage.java | 5 ++ .../page/CaseWidgetNewDashBoardPage.java | 4 +- .../selenium/page/NewDashboardPage.java | 4 +- .../page/TaskWidgetNewDashBoardPage.java | 6 +- AxonIvyPortal/portal/cms/cms_de.yaml | 1 + AxonIvyPortal/portal/cms/cms_en.yaml | 1 + AxonIvyPortal/portal/cms/cms_es.yaml | 1 + AxonIvyPortal/portal/cms/cms_fr.yaml | 1 + .../generic/CaseDocuments/CaseDocuments.xhtml | 8 +-- .../generic/TaskDocuments/TaskDocuments.xhtml | 8 +-- .../PortalDashboardDetailModification.xhtml | 24 ++++--- .../DashboardModification.xhtml | 2 +- .../WelcomeDashboardWidget.xhtml | 2 +- .../AbsenceManagement/AbsenceManagement.xhtml | 26 +++---- .../admin/AdminSettings/AdminSettings.xhtml | 12 ++-- .../component/ActionStep/ActionStep.xhtml | 2 +- .../CaseItemDetails/CaseItemDetails.xhtml | 14 ++-- .../CaseItemDocument/CaseItemDocument.xhtml | 8 +-- .../IconSelection/IconSelection.xhtml | 4 +- .../ProcessWidget/ProcessWidgetDialogs.xhtml | 72 +++++++++---------- .../component/SideStep/SideStep.xhtml | 11 +-- .../TaskItemDetails/TaskItemDetails.xhtml | 12 ++-- .../TaskItemDocuments/TaskItemDocuments.xhtml | 6 +- .../WarningBeforeLeavingTask.xhtml | 6 +- .../ProcessItemAction/ProcessItemAction.xhtml | 2 +- .../restricted/DashboardTemplate.xhtml | 24 ++++--- .../restricted/decorator/TableWidget.xhtml | 29 ++++---- .../webContent/resources/css/module.css | 4 +- .../resources/css/portal-variables-dark.css | 3 +- .../resources/css/portal-variables-light.css | 1 + .../webContent/resources/css/portal.css | 25 ++++++- .../webContent/resources/css/utility.css | 4 ++ .../webContent/resources/js/process-widget.js | 7 ++ .../full-process-list/index.rst | 3 +- 37 files changed, 204 insertions(+), 145 deletions(-) diff --git a/AxonIvyPortal/portal-selenium-test/resources/js/document-screenshot.js b/AxonIvyPortal/portal-selenium-test/resources/js/document-screenshot.js index 72d33cbad1f..d6de1e6f34c 100644 --- a/AxonIvyPortal/portal-selenium-test/resources/js/document-screenshot.js +++ b/AxonIvyPortal/portal-selenium-test/resources/js/document-screenshot.js @@ -124,7 +124,7 @@ function highlightProcessItems() { } function highlightEditProcessIcon() { - appendStepAnnotation($("[id$='process-widget:edit-process-form:edit-process-icon:awesome-icon-selection']"), "4", -10, 100); + appendStepAnnotation($("[id$='process-widget:edit-process-form:edit-process-icon:awesome-icon-selection']"), "4", -40, 110); } function highlightEditProcessDialog() { diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalCasesScreenshotTest.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalCasesScreenshotTest.java index ffd8a3412be..8a6f125fe7f 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalCasesScreenshotTest.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalCasesScreenshotTest.java @@ -84,7 +84,7 @@ public void screenshotCaseDetails() throws IOException { ScreenshotUtils.captureElementWithMarginOptionScreenshot(detailsPage.openAddAttachmentDialog(), ScreenshotUtils.CASE_DETAIL_FOLDER + "how-to-attach-document-to-case", new ScreenshotMargin(10)); detailsPage.closeAddAttachmentDialog(); - detailsPage.uploadDocumentWithoutError(FileHelper.getAbsolutePathToTestFile("test-no-files-no-js.pdf")); + detailsPage.uploadDocument(FileHelper.getAbsolutePathToTestFile("test-no-files-no-js.pdf")); refreshPage(); detailsPage.waitForCaseDetailsDisplay(); diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalProcessesScreenshotTest.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalProcessesScreenshotTest.java index d7421a40e6a..84856693bec 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalProcessesScreenshotTest.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/document/screenshot/PortalProcessesScreenshotTest.java @@ -79,10 +79,11 @@ public void screenshotPortalFullProcessesList() throws IOException { ScreenshotUtils.captureElementWithMarginOptionScreenshot(processWidget.getProcessEditMenu(0), ScreenshotUtils.PROCESSES_WIDGET_FOLDER + "edit-process-menu-item", new ScreenshotMargin(150, 200)); processWidget.clickOnProcessEditMenu(0); + ScreenshotUtils.maximizeBrowser(); ScreenshotUtils.executeDecorateJs("highlightEditProcessDialog()"); ScreenshotUtils.executeDecorateJs("highlightEditProcessIcon()"); ScreenshotUtils.captureElementWithMarginOptionScreenshot(processWidget.getEditProcessDialog(), - ScreenshotUtils.PROCESSES_WIDGET_FOLDER + "edit-process-dialog", new ScreenshotMargin(10)); + ScreenshotUtils.PROCESSES_WIDGET_FOLDER + "edit-process-dialog", new ScreenshotMargin(5)); ScreenshotUtils.resizeBrowser(new Dimension(1366, 800)); refreshPage(); processWidget.waitUtilProcessWidgetDisplayed(); diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseDetailsPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseDetailsPage.java index cec20f12a4e..e069a25ee19 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseDetailsPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseDetailsPage.java @@ -850,6 +850,11 @@ public void uploadDocumentWithoutError(String pathToFile) { $("button[id$='document:document-upload-close-command']").shouldBe(getClickableCondition(), DEFAULT_TIMEOUT) .click(); } + + public void uploadDocument(String pathToFile) { + $("input[id$='document-upload-panel_input']").shouldBe(exist, DEFAULT_TIMEOUT) + .shouldBe(Condition.hidden, DEFAULT_TIMEOUT).sendKeys(pathToFile); + } public void openAddDocumentDialogAndUploadDocument(String pathToFile) { getAddAttachmentDialog(); diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseWidgetNewDashBoardPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseWidgetNewDashBoardPage.java index 4b2914eac2b..59a7e13f672 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseWidgetNewDashBoardPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/CaseWidgetNewDashBoardPage.java @@ -162,7 +162,7 @@ public void nextPageTable() { } public void resetFilter() { - $("div.filter-overlay-panel__footer").shouldBe(appear, DEFAULT_TIMEOUT).$$("button[id$='reset-button']") + $("div.filter-overlay-panel__footer").shouldBe(appear, DEFAULT_TIMEOUT).$$("a[id$='reset-button']") .filter(text("Reset")).first().shouldBe(getClickableCondition(), DEFAULT_TIMEOUT).click(); $("div.filter-overlay-panel__footer").shouldBe(disappear, DEFAULT_TIMEOUT); waitForElementClickable($$("div.table-widget-panel") @@ -269,7 +269,7 @@ public void removeAllFilterItems() { } public void openManageFiltersDialog() { - $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("button").shouldBe(getClickableCondition()).click(); + $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("a").shouldBe(getClickableCondition()).click(); } public void closeManageFilterDialog() { diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/NewDashboardPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/NewDashboardPage.java index aa73b4029ce..d06faa3f5f6 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/NewDashboardPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/NewDashboardPage.java @@ -545,7 +545,7 @@ public SelenideElement getCompactModeProcessFilterPanelSaveButton() { } public SelenideElement getCompactModeProcessFilterPanelResetButton() { - return getCompactModeProcessFilterPanel().$("button[id$=':reset-button']"); + return getCompactModeProcessFilterPanel().$("a[id$=':reset-button']"); } public void resetCompactModeProcessFilterPanel() { @@ -1033,7 +1033,7 @@ public NotificationCompactPage openNotificationPanel() { } public void clickOnManageFilterLink() { - $("div[class*='filter-overlay-panel__footer']").shouldBe(appear, DEFAULT_TIMEOUT).$("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("button[class*='saved-filter__manage-filter']").shouldBe(getClickableCondition(), DEFAULT_TIMEOUT).click(); + $("div[class*='filter-overlay-panel__footer']").shouldBe(appear, DEFAULT_TIMEOUT).$("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("a[class*='saved-filter__manage-filter']").shouldBe(getClickableCondition(), DEFAULT_TIMEOUT).click(); $("[id$='manage-filter-dialog']").shouldBe(appear, DEFAULT_TIMEOUT); } diff --git a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskWidgetNewDashBoardPage.java b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskWidgetNewDashBoardPage.java index b2c269d7f42..c94ce3ae09f 100644 --- a/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskWidgetNewDashBoardPage.java +++ b/AxonIvyPortal/portal-selenium-test/src_test/com/axonivy/portal/selenium/page/TaskWidgetNewDashBoardPage.java @@ -132,7 +132,7 @@ public void applyFilter() { } public void resetFilter() { - $("div.filter-overlay-panel__footer").shouldBe(appear, DEFAULT_TIMEOUT).$$("button[id$='reset-button']") + $("div.filter-overlay-panel__footer").shouldBe(appear, DEFAULT_TIMEOUT).$$("a[id$='reset-button']") .filter(text("Reset")).first().shouldBe(getClickableCondition(), DEFAULT_TIMEOUT).click(); } @@ -183,7 +183,7 @@ public boolean hasSavedFilterItem(String filterName) { } public void clickOnManageFilterLink() { - $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("button").shouldBe(getClickableCondition()).click(); + $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("a").shouldBe(getClickableCondition()).click(); $("[id$='manage-filter-dialog']").shouldBe(appear, DEFAULT_TIMEOUT); } @@ -530,7 +530,7 @@ public void saveFilter(String widgetFilterName) { } public void openManageFiltersDialog() { - $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("button").shouldBe(getClickableCondition()).click(); + $("div#manage-filter").shouldBe(appear, DEFAULT_TIMEOUT).$("a").shouldBe(getClickableCondition()).click(); } public void removeAllFilterItems() { diff --git a/AxonIvyPortal/portal/cms/cms_de.yaml b/AxonIvyPortal/portal/cms/cms_de.yaml index dd66e122eea..f7223acbf51 100644 --- a/AxonIvyPortal/portal/cms/cms_de.yaml +++ b/AxonIvyPortal/portal/cms/cms_de.yaml @@ -410,6 +410,7 @@ ch.ivy.addon.portalkit.ui.jsf: active: Aktiviert add: Hinzufügen addDocument: Dokument hinzufügen + addLink: Link hinzufügen addNote: Notiz hinzufügen allCategories: Alle Kategorien allTypes: Alle Typen diff --git a/AxonIvyPortal/portal/cms/cms_en.yaml b/AxonIvyPortal/portal/cms/cms_en.yaml index aee201428bf..73c02a2e09d 100644 --- a/AxonIvyPortal/portal/cms/cms_en.yaml +++ b/AxonIvyPortal/portal/cms/cms_en.yaml @@ -409,6 +409,7 @@ ch.ivy.addon.portalkit.ui.jsf: active: Active add: Add addDocument: Add document + addLink: Add Link addNote: Add note allCategories: All Categories allTypes: All types diff --git a/AxonIvyPortal/portal/cms/cms_es.yaml b/AxonIvyPortal/portal/cms/cms_es.yaml index f74b3738de8..cc0eeedb7d0 100644 --- a/AxonIvyPortal/portal/cms/cms_es.yaml +++ b/AxonIvyPortal/portal/cms/cms_es.yaml @@ -411,6 +411,7 @@ ch.ivy.addon.portalkit.ui.jsf: active: Activado add: Añadir addDocument: Agregar documento + addLink: Añadir enlace addNote: Agregar nota allCategories: Todas las categorias allTypes: Todos los tipos diff --git a/AxonIvyPortal/portal/cms/cms_fr.yaml b/AxonIvyPortal/portal/cms/cms_fr.yaml index 53419436396..c343a2a9a7b 100644 --- a/AxonIvyPortal/portal/cms/cms_fr.yaml +++ b/AxonIvyPortal/portal/cms/cms_fr.yaml @@ -408,6 +408,7 @@ ch.ivy.addon.portalkit.ui.jsf: active: Activé add: Ajouter addDocument: Ajouter un document + addLink: Ajouter un lien addNote: Ajouter une note allCategories: Toutes les catégories allTypes: Tous les types diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/CaseDocuments/CaseDocuments.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/CaseDocuments/CaseDocuments.xhtml index 5b3ad1a5c31..74e7f501aee 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/CaseDocuments/CaseDocuments.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/CaseDocuments/CaseDocuments.xhtml @@ -99,13 +99,13 @@ - + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/TaskDocuments/TaskDocuments.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/TaskDocuments/TaskDocuments.xhtml index 2e40333a337..b4c4e1da392 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/TaskDocuments/TaskDocuments.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/TaskDocuments/TaskDocuments.xhtml @@ -99,13 +99,13 @@ - + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/PortalDashboardDetailModification/PortalDashboardDetailModification.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/PortalDashboardDetailModification/PortalDashboardDetailModification.xhtml index 4d83a6a8f0a..e00fe4deb0b 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/PortalDashboardDetailModification/PortalDashboardDetailModification.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/PortalDashboardDetailModification/PortalDashboardDetailModification.xhtml @@ -24,11 +24,12 @@ - + update="grid-stack @this" process="@this"> + + #{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/common/back')} + @@ -102,13 +103,14 @@ - - + + + + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/DashboardModification/DashboardModification.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/DashboardModification/DashboardModification.xhtml index a90abd57fac..d3e6db1fefd 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/DashboardModification/DashboardModification.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portal/generic/dashboard/component/DashboardModification/DashboardModification.xhtml @@ -130,7 +130,7 @@ value="#{ivy.cms.co('/ch.ivy.addon.portalkit.ui.jsf/dashboard/dashboardManagement/deleteDashboardMessage',[dashboardModificationBean.selectedDashboard.title])}" />
- - @@ -253,17 +253,17 @@ - - - + + + + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/admin/AdminSettings/AdminSettings.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/admin/AdminSettings/AdminSettings.xhtml index 1accd261b13..f390f58154e 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/admin/AdminSettings/AdminSettings.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/admin/AdminSettings/AdminSettings.xhtml @@ -81,7 +81,7 @@ process="@this" />
- +
@@ -363,12 +363,14 @@ - + + + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/ActionStep/ActionStep.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/ActionStep/ActionStep.xhtml index f91f3032968..7e008bc2554 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/ActionStep/ActionStep.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/ActionStep/ActionStep.xhtml @@ -74,7 +74,7 @@ - + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDetails/CaseItemDetails.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDetails/CaseItemDetails.xhtml index a035bbc8d98..b18ad939d28 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDetails/CaseItemDetails.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDetails/CaseItemDetails.xhtml @@ -181,12 +181,14 @@ - - + + + + diff --git a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDocument/CaseItemDocument.xhtml b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDocument/CaseItemDocument.xhtml index 4c966982edf..3d073e96869 100644 --- a/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDocument/CaseItemDocument.xhtml +++ b/AxonIvyPortal/portal/src_hd/ch/ivy/addon/portalkit/component/CaseItemDocument/CaseItemDocument.xhtml @@ -167,13 +167,13 @@ - +