From 1aa3e830a6e823e02e9ca20decce37fd584e77bc Mon Sep 17 00:00:00 2001 From: mnhnam Date: Wed, 3 Jul 2024 22:08:46 +0700 Subject: [PATCH 1/6] Implement partly --- .../components/enums/PortalVariable.java | 3 +- .../enums/ai/IvyToolResultType.java | 24 - .../portal/components/enums/ai/RunState.java | 5 - .../components/util/AssistantUtils.java | 43 -- AxonIvyPortal/portal/config/variables.yaml | 14 - .../config/variables/Portal/AiTool.json | 71 --- .../config/variables/Portal/Assistant.json | 7 - .../portalkit/PortalToolsData.ivyClass | 2 +- AxonIvyPortal/portal/pom.xml | 6 + .../PortalCallableTools.p.json | 10 +- .../portal/generic/bean/ChatRendererBean.java | 17 +- .../portal/generic/bean/UserMenuBean.java | 12 +- .../generic/navigation/PortalNavigator.java | 12 +- .../bean/AssistantModificationBean.java | 90 --- .../portalkit/bean/ChatDashboardBean.java | 37 -- .../ch/ivy/addon/portalkit/dto/ai/AiTool.java | 112 ---- .../ivy/addon/portalkit/dto/ai/Assistant.java | 178 ------ .../ivy/addon/portalkit/dto/ai/IvyTool.java | 133 ----- .../portalkit/dto/ai/IvyToolAttribute.java | 64 -- .../addon/portalkit/dto/ai/IvyToolStep.java | 62 -- .../portalkit/dto/ai/RetrievalQATool.java | 34 -- .../addon/portalkit/enums/PortalVariable.java | 1 - .../portalkit/service/AiProcessService.java | 24 + .../portalkit/service/AiToolService.java | 43 -- .../portalkit/service/AssistantService.java | 43 -- .../axonivy/portal/bean/ai/AssistantBean.java | 103 ---- .../bean/ai/AssistantManagementBean.java | 92 --- .../com/axonivy/portal/enums/ai/StepType.java | 5 - .../com/axonivy/portal/enums/ai/ToolType.java | 31 - .../portal/rest/AssistantRestService.java | 30 - .../ChatDashboard/ChatDashboard.rddescriptor | 7 - .../ChatDashboard/ChatDashboard.xhtml | 75 --- .../ChatDashboard/ChatDashboardData.ivyClass | 2 - .../ChatDashboard/ChatDashboardProcess.p.json | 48 -- .../component/ToolList/ToolList.rddescriptor | 7 - .../portal/component/ToolList/ToolList.xhtml | 90 --- .../component/ToolList/ToolListData.ivyClass | 2 - .../component/ToolList/ToolListProcess.p.json | 48 -- .../includes/ChatDashboardTemplate.xhtml | 125 ---- .../webContent/layouts/includes/topbar.xhtml | 2 +- .../webContent/resources/css/chatbot.css | 509 ---------------- .../webContent/resources/js/ai-assistant.js | 547 ------------------ .../webContent/resources/js/ajax-utils.js | 20 +- .../webContent/resources/js/chatbot-utils.js | 344 ----------- .../portal/webContent/resources/js/chatbot.js | 388 ------------- .../resources/js/highlightJS/highlight.min.js | 491 ---------------- .../js/highlightJS/languages/css.min.js | 31 - .../js/highlightJS/languages/java.min.js | 38 -- .../highlightJS/languages/javascript.min.js | 80 --- .../js/highlightJS/languages/json.min.js | 7 - .../js/highlightJS/languages/markdown.min.js | 31 - 51 files changed, 78 insertions(+), 4122 deletions(-) delete mode 100644 AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/IvyToolResultType.java delete mode 100644 AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/RunState.java delete mode 100644 AxonIvyPortal/portal-components/src/com/axonivy/portal/components/util/AssistantUtils.java delete mode 100644 AxonIvyPortal/portal/config/variables/Portal/AiTool.json delete mode 100644 AxonIvyPortal/portal/config/variables/Portal/Assistant.json delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/AssistantModificationBean.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/ChatDashboardBean.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/AiTool.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/Assistant.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyTool.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolAttribute.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolStep.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/RetrievalQATool.java create mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiProcessService.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiToolService.java delete mode 100644 AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AssistantService.java delete mode 100644 AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantBean.java delete mode 100644 AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantManagementBean.java delete mode 100644 AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/StepType.java delete mode 100644 AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/ToolType.java delete mode 100644 AxonIvyPortal/portal/src/com/axonivy/portal/rest/AssistantRestService.java delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.rddescriptor delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.xhtml delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardData.ivyClass delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardProcess.p.json delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.rddescriptor delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.xhtml delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListData.ivyClass delete mode 100644 AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListProcess.p.json delete mode 100644 AxonIvyPortal/portal/webContent/layouts/includes/ChatDashboardTemplate.xhtml delete mode 100644 AxonIvyPortal/portal/webContent/resources/css/chatbot.css delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/ai-assistant.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/chatbot-utils.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/chatbot.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/highlight.min.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/languages/css.min.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/languages/java.min.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/languages/javascript.min.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/languages/json.min.js delete mode 100644 AxonIvyPortal/portal/webContent/resources/js/highlightJS/languages/markdown.min.js diff --git a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/PortalVariable.java b/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/PortalVariable.java index 6432a077a7a..d3fcb1cbc05 100644 --- a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/PortalVariable.java +++ b/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/PortalVariable.java @@ -13,8 +13,7 @@ public enum PortalVariable { DASHBOARD("Portal.Dashboard"), DASHBOARD_ORDER("Portal.Dashboard.Order"), DASHBOARD_TEMPLATES("Portal.DashboardTemplates"), - USER_MENU("Portal.UserMenu"), - CHATBOT_ENDPOINT("PortalAiUrl"); + USER_MENU("Portal.UserMenu"); public String key; diff --git a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/IvyToolResultType.java b/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/IvyToolResultType.java deleted file mode 100644 index 3305caed83a..00000000000 --- a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/IvyToolResultType.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.axonivy.portal.components.enums.ai; - -public enum IvyToolResultType { - - JSON("%s"), IFRAME(""), ERROR("%s"); - - private IvyToolResultType(String resultPattern) { - this.resultPattern = resultPattern; - } - - private String resultPattern; - - public String getResultPattern() { - return resultPattern; - } - - public void setResultPattern(String resultPattern) { - this.resultPattern = resultPattern; - } - - public String format(String content) { - return String.format(this.resultPattern, content); - } -} diff --git a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/RunState.java b/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/RunState.java deleted file mode 100644 index 977dfa9f835..00000000000 --- a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/enums/ai/RunState.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.axonivy.portal.components.enums.ai; - -public enum RunState { - OPEN, IN_PROGRESS, DONE, ERROR; -} diff --git a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/util/AssistantUtils.java b/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/util/AssistantUtils.java deleted file mode 100644 index 8ef6372a50d..00000000000 --- a/AxonIvyPortal/portal-components/src/com/axonivy/portal/components/util/AssistantUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.axonivy.portal.components.util; - -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; - -import com.axonivy.portal.components.enums.ai.IvyToolResultType; -import com.axonivy.portal.components.service.impl.ProcessService; - -import ch.ivyteam.ivy.environment.Ivy; -import ch.ivyteam.ivy.workflow.start.IWebStartable; - -public class AssistantUtils { - - public static String generateLinkToIvyProcess(String link, - Map params) { - try { - IWebStartable process = initWebStartable(link); - return IvyToolResultType.IFRAME - .format(process.getLink().queryParams(params).getRelative()); - } catch (Exception e) { - return IvyToolResultType.ERROR - .format(Ivy.cms().co("/Labels/AI/Error/ErrorWhenProceedRequest")); - } - } - - private static IWebStartable initWebStartable(String processPath) { - if (StringUtils.isBlank(processPath)) { - return null; - } - - return ProcessService.getInstance().findAllProcesses().stream() - .filter(process -> process.getId().contentEquals(processPath)) - .findFirst().orElse(null); - } - - public static String generateErrorResult(String error) { - if (StringUtils.isBlank(error)) { - return ""; - } - return IvyToolResultType.ERROR.format(error); - } -} diff --git a/AxonIvyPortal/portal/config/variables.yaml b/AxonIvyPortal/portal/config/variables.yaml index 761ab858505..3a9daf0e468 100644 --- a/AxonIvyPortal/portal/config/variables.yaml +++ b/AxonIvyPortal/portal/config/variables.yaml @@ -193,9 +193,6 @@ Variables: # [enum: 1, 2, 3, 4, 5] MaxConnection: 3 - # Endpoint URL for the RESTful service of Portal chatbot - ChatBotEndpoint: localhost:8018 - Histories: # If true, case note does not display any system tasks for non-administrator users. HideSystemTasks: true @@ -295,17 +292,6 @@ Variables: # Set this property to true to enable the DeepL translation support Enable: false - # You can define AI assistants here - # [file: json] - Assistant: - - # You can define AI Tools - # [file: json] - AiTool: - - #URL to the REST service endpoint of Portal AI - PortalAiUrl: 'http://localhost:8018' - # If set to true, the cron job runs daily (at 6.AM as default) will clean all finished hidden cases in engine. # Otherwise, just hidden cases which were generated by Portal will be deleted. PortalDeleteAllFinishedHiddenCases: false diff --git a/AxonIvyPortal/portal/config/variables/Portal/AiTool.json b/AxonIvyPortal/portal/config/variables/Portal/AiTool.json deleted file mode 100644 index 47ebb9892cb..00000000000 --- a/AxonIvyPortal/portal/config/variables/Portal/AiTool.json +++ /dev/null @@ -1,71 +0,0 @@ -[ - { - "id" : "find-tasks", - "name" : "Find tasks", - "type" : "IVY", - "signature" : "findTasks(String,String,String,String)", - "permissions" : ["Everybody"], - "description" : "This tool is helpful when user want to find tasks by attributes. ONLY useful for task", - "attributes" : [ - { - "name" : "taskName", - "description" : "Name of the task" - } , { - "name" : "taskDescription", - "description" : "Description of the task" - } , { - "name" : "taskPriority", - "description" : "Priority of a task. Valid values for this attribute: low, normal, high, exception" - } , { - "name" : "taskState", - "description" : "State of the task. Valid values for this attribute: open, in progress, done" - } - - ] - } , { - "id" : "find-cases", - "name" : "Find cases", - "type" : "IVY", - "signature" : "findCases(String,String,String)", - "permissions" : ["Everybody"], - "description" : "This tool is helpful when user want to find cases by attributes. ONLY useful for case", - "attributes" : [ - { - "name" : "caseName", - "description" : "Name of the case" - } , { - "name" : "caseDescription", - "description" : "Description of the case" - } , { - "name" : "caseState", - "description" : "State of the case. Valid values for this attribute: open, done, destroyed" - } - - ] - } , { - "id" : "portal-support", - "name" : "Portal support", - "type" : "RETRIEVAL_QA", - "default" : true, - "description" : "Helpful when user ask questions.", - "permissions" : ["Everybody"], - "collection" : "portal-user-guide" - } , { - "id" : "find-users", - "name" : "Find users", - "type" : "IVY", - "signature" : "findUsers(String,String)", - "permissions" : ["Everybody"], - "description" : "This is a tool to find information of users.", - "attributes" : [ - { - "name" : "username", - "description" : "Name of user" - } , { - "name" : "role", - "description" : "Role of user" - } - ], - "postAction" : "ONLY use data from the from the result, show as list these informations: name, display name, email, status (field enabled), if any field is null or empty, show blank space instead. Format: \nName: name\nDisplay Name: displayname\n Email: email\n... and so on" - } -] \ No newline at end of file diff --git a/AxonIvyPortal/portal/config/variables/Portal/Assistant.json b/AxonIvyPortal/portal/config/variables/Portal/Assistant.json deleted file mode 100644 index 803275bb37f..00000000000 --- a/AxonIvyPortal/portal/config/variables/Portal/Assistant.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "id" : "assistant-1", - "name" : "Portal Assistant", - "tools" : ["find-tasks", "portal-support"] - } -] \ No newline at end of file diff --git a/AxonIvyPortal/portal/dataclasses/portalkit/PortalToolsData.ivyClass b/AxonIvyPortal/portal/dataclasses/portalkit/PortalToolsData.ivyClass index db9943cc304..401ff6983cf 100644 --- a/AxonIvyPortal/portal/dataclasses/portalkit/PortalToolsData.ivyClass +++ b/AxonIvyPortal/portal/dataclasses/portalkit/PortalToolsData.ivyClass @@ -1,6 +1,6 @@ PortalToolsData #class portalkit #namespace -tool ch.ivy.addon.portalkit.dto.ai.IvyTool #field +tool com.axonivy.portal.ai.dto.IvyTool #field taskDashboardWidget ch.ivy.addon.portalkit.dto.dashboard.TaskDashboardWidget #field name String #field description String #field diff --git a/AxonIvyPortal/portal/pom.xml b/AxonIvyPortal/portal/pom.xml index f90c9eda121..1c4daabc581 100644 --- a/AxonIvyPortal/portal/pom.xml +++ b/AxonIvyPortal/portal/pom.xml @@ -27,6 +27,12 @@ 9.1.0.0-SNAPSHOT iar + + portal.ai + portal-ai + 1.0.0-SNAPSHOT + iar + diff --git a/AxonIvyPortal/portal/processes/AI Tool Processes/PortalCallableTools.p.json b/AxonIvyPortal/portal/processes/AI Tool Processes/PortalCallableTools.p.json index 23851d582fa..8e7cccf73f6 100644 --- a/AxonIvyPortal/portal/processes/AI Tool Processes/PortalCallableTools.p.json +++ b/AxonIvyPortal/portal/processes/AI Tool Processes/PortalCallableTools.p.json @@ -49,7 +49,7 @@ "config" : { "output" : { "code" : [ - "import com.axonivy.portal.components.util.AssistantUtils;", + "import com.axonivy.portal.ai.utils.AssistantUtils;", "import org.apache.commons.collections4.CollectionUtils;", "import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter;", "import org.apache.commons.lang3.StringUtils;", @@ -127,7 +127,7 @@ "output" : { "code" : [ "import ch.ivyteam.ivy.application.IApplication;", - "import com.axonivy.portal.components.util.AssistantUtils;", + "import com.axonivy.portal.ai.utils.AssistantUtils;", "import java.util.HashMap;", "import java.util.Map;", "", @@ -155,7 +155,7 @@ "output" : { "code" : [ "import org.apache.commons.lang3.StringUtils;", - "import com.axonivy.portal.components.util.AssistantUtils;", + "import com.axonivy.portal.ai.utils.AssistantUtils;", "import com.axonivy.portal.util.AiToolUtils;", "", "in.validationError = AiToolUtils.validateTaskState(in.taskState);", @@ -249,7 +249,7 @@ "code" : [ "import org.apache.commons.lang3.StringUtils;", "import com.axonivy.portal.util.AiToolUtils;", - "import com.axonivy.portal.components.util.AssistantUtils;", + "import com.axonivy.portal.ai.utils.AssistantUtils;", "", "in.validationError = AiToolUtils.validateCaseState(in.taskState);", "if(StringUtils.isNotBlank(in.validationError)) {", @@ -294,7 +294,7 @@ "output" : { "code" : [ "import ch.ivyteam.ivy.application.IApplication;", - "import com.axonivy.portal.components.util.AssistantUtils;", + "import com.axonivy.portal.ai.utils.AssistantUtils;", "import java.util.HashMap;", "import java.util.Map;", "", diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/ChatRendererBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/ChatRendererBean.java index 944b83c4161..b276595f8d2 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/ChatRendererBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/ChatRendererBean.java @@ -2,6 +2,7 @@ import java.io.Serializable; import java.util.Map; +import java.util.Optional; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @@ -12,9 +13,11 @@ import com.axonivy.portal.components.service.IvyAdapterService; import ch.ivy.addon.portalkit.enums.GlobalVariable; -import ch.ivy.addon.portalkit.enums.PortalVariable; +import ch.ivy.addon.portalkit.service.AiProcessService; import ch.ivy.addon.portalkit.service.GlobalSettingService; import ch.ivyteam.ivy.environment.Ivy; +import ch.ivyteam.ivy.model.value.WebLink; +import ch.ivyteam.ivy.workflow.IProcessStart; @ManagedBean @ViewScoped @@ -25,6 +28,7 @@ public class ChatRendererBean implements Serializable { private Boolean isGroupChatRendered; private Boolean isPrivateChatRendered; + private IProcessStart assistantDashboardProcess; public boolean getIsChatRendered() { return getIsGroupChatRendered() || getIsPrivateChatRendered(); @@ -62,7 +66,14 @@ public boolean isExpressCreationTask() { return Ivy.wfTask().customFields().stringField(EXPRESS_CREATION_TASK).get().isPresent(); } - public boolean getIsChatbotRendered() { - return !StringUtils.isBlank(Ivy.var().get(PortalVariable.CHATBOT_ENDPOINT.key)); + public boolean getIsAssistantDashboardRendered() { + if (this.assistantDashboardProcess == null) { + this.assistantDashboardProcess = AiProcessService.getInstance() + .findAssistantDashboardProcess(); + } + return StringUtils.isNotBlank(Optional.ofNullable(assistantDashboardProcess) + .map(IProcessStart::getLinkEmbedded).map(WebLink::getRelative) + .orElse("")); } + } diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/UserMenuBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/UserMenuBean.java index fe36de2fb5a..9880b83422d 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/UserMenuBean.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/bean/UserMenuBean.java @@ -265,8 +265,8 @@ public void navigateToUserProfile() throws IOException { getExternalContext().redirect(getUserProfileUrl()); } - public void navigateToChatbotDashboard() throws IOException { - getExternalContext().redirect(getChatbotUrl()); + public void navigateToAssistantDashboard() throws IOException { + getExternalContext().redirect(getAssistantDashboardUrl()); } private void navigateToTargetPage() throws IOException { @@ -277,8 +277,8 @@ private String getUserProfileUrl() { return PortalNavigator.buildUserProfileUrl(); } - private String getChatbotUrl() { - return PortalNavigator.buildChatbotUrl(); + private String getAssistantDashboardUrl() { + return PortalNavigator.buildAssistantDashboardUrl(); } private void navigateToPortalManagement() throws IOException { @@ -376,10 +376,10 @@ public String getQRcodeData() { public void navigateToChatBotOrDisplayWorkingTaskWarning(boolean isWorkingOnATask, ITask task) throws IOException { if (isWorkingOnATask && task.getState() != TaskState.DONE) { openTaskLosingConfirmationDialog(); - targetPage = getChatbotUrl(); + targetPage = getAssistantDashboardUrl(); } else { executeJSResetPortalMenuState(); - navigateToChatbotDashboard(); + navigateToAssistantDashboard(); } } } diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/navigation/PortalNavigator.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/navigation/PortalNavigator.java index 96be93a568a..e4b9bb7f0ff 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/navigation/PortalNavigator.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portal/generic/navigation/PortalNavigator.java @@ -4,6 +4,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -14,9 +15,12 @@ import ch.ivy.addon.portalkit.enums.MenuKind; import ch.ivy.addon.portalkit.enums.SessionAttribute; +import ch.ivy.addon.portalkit.service.AiProcessService; import ch.ivy.addon.portalkit.util.RequestUtils; import ch.ivyteam.ivy.environment.Ivy; +import ch.ivyteam.ivy.model.value.WebLink; import ch.ivyteam.ivy.request.IHttpRequest; +import ch.ivyteam.ivy.workflow.IProcessStart; import ch.ivyteam.ivy.workflow.StandardProcessType; public final class PortalNavigator extends BaseNavigator{ @@ -40,7 +44,6 @@ public final class PortalNavigator extends BaseNavigator{ private static final String PORTAL_NEW_DASHBOARD_CONFIGURATION = "Start Processes/PortalStart/PortalDashboardConfiguration.ivp"; private static final String PORTAL_PROCESS_INFO = "Start Processes/PortalStart/ProcessInformation.ivp"; private static final String PORTAL_DASHBOARD_DETAILS = "Start Processes/PortalStart/DashboardDetails.ivp"; - private static final String PORTAL_CHATBOT = "Start Processes/PortalStart/PortalChatDashboard.ivp"; public static final String PORTAL_DASHBOARD_START = "/DefaultDashboardPage.ivp"; public static final String PORTAL_PROCESS_START = "/DefaultProcessStartListPage.ivp"; @@ -279,7 +282,10 @@ public static String buildNotificationFullPageUrl() { return buildUrlByKeyword(PORTAL_NOTIFICATION_FULLPAGE_START, PORTAL_NOTIFICATION_FULLPAGE, new HashMap<>()); } - public static String buildChatbotUrl() { - return buildUrlByKeyword("PortalChatDashboard.ivp", PORTAL_CHATBOT, new HashMap<>()); + public static String buildAssistantDashboardUrl() { + IProcessStart process = AiProcessService.getInstance() + .findAssistantDashboardProcess(); + return Optional.ofNullable(process).map(IProcessStart::getLinkEmbedded) + .map(WebLink::getRelative).orElse(""); } } diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/AssistantModificationBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/AssistantModificationBean.java deleted file mode 100644 index e641d733011..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/AssistantModificationBean.java +++ /dev/null @@ -1,90 +0,0 @@ -package ch.ivy.addon.portalkit.bean; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.faces.bean.ManagedBean; -import javax.faces.bean.ViewScoped; - -import org.apache.commons.collections4.CollectionUtils; - -import com.axonivy.portal.bean.ai.AssistantBean; -import com.axonivy.portal.components.util.SecurityMemberDisplayNameUtils; - -import ch.ivy.addon.portalkit.enums.ChatbotCandidateQuestion; -import ch.ivy.addon.portalkit.service.AssistantService; -import ch.ivyteam.ivy.environment.Ivy; -import ch.ivyteam.ivy.security.ISecurityMember; - -@ManagedBean -@ViewScoped -public class AssistantModificationBean extends AssistantBean - implements Serializable { - - private static final long serialVersionUID = -894113970760912023L; - - private boolean isAddTool; - - private ChatbotCandidateQuestion[] candidateQuestions = ChatbotCandidateQuestion - .values(); - - @PostConstruct - public void init() { - super.initBean(); - isAddTool = false; - } - - public ChatbotCandidateQuestion[] getCandidateQuestions() { - return candidateQuestions; - } - - public String renderPermissions(List permissions) { - String result = ""; - - if (CollectionUtils.isEmpty(permissions)) { - return result; - } - - for (String permission : permissions) { - if (permissions.indexOf(permission) != 0) { - result += ", "; - } - ISecurityMember mem = Ivy.security().members().find(permission); - result += SecurityMemberDisplayNameUtils - .generateBriefDisplayNameForSecurityMember(mem, permission); - } - return result; - } - - public boolean isAddTool() { - return isAddTool; - } - - public void setAddTool(boolean isAddTool) { - this.isAddTool = isAddTool; - } - - public void onAddTool() { - setAddTool(true); - } - - public void onBack() { - setAddTool(false); - } - - @Override - public void save() { - AssistantService.getInstance() - .saveAllPublicConfig(Arrays.asList(getAssistant())); - setAssistantJson(getAssistant().buildDetailsJson()); - onCancel(); - } - - @Override - public void onCancel() { - setAddTool(false); - init(); - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/ChatDashboardBean.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/ChatDashboardBean.java deleted file mode 100644 index 43acb785e42..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/bean/ChatDashboardBean.java +++ /dev/null @@ -1,37 +0,0 @@ -package ch.ivy.addon.portalkit.bean; - -import java.io.Serializable; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.ViewScoped; - -import org.apache.commons.lang3.StringUtils; - -import ch.ivy.addon.portalkit.enums.ChatbotCandidateQuestion; -import ch.ivy.addon.portalkit.enums.PortalVariable; -import ch.ivyteam.ivy.environment.Ivy; - -@ManagedBean -@ViewScoped -public class ChatDashboardBean implements Serializable { - - private static final long serialVersionUID = -894113970760912023L; - - private static ChatbotCandidateQuestion[] candidateQuestions = ChatbotCandidateQuestion.values(); - private String chatbotEndpoint; - - public ChatbotCandidateQuestion[] getCandidateQuestions() { - return candidateQuestions; - } - - public String getChatbotEndpoint() { - if (StringUtils.isBlank(chatbotEndpoint)) { - chatbotEndpoint = Ivy.var().get(PortalVariable.CHATBOT_ENDPOINT.key); - } - return chatbotEndpoint; - } - - public void setChatbotEndpoint(String chatbotEndpoint) { - this.chatbotEndpoint = chatbotEndpoint; - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/AiTool.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/AiTool.java deleted file mode 100644 index c2aa18610ad..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/AiTool.java +++ /dev/null @@ -1,112 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import java.io.Serializable; -import java.util.List; - -import com.axonivy.portal.enums.ai.ToolType; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonSubTypes.Type; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.databind.JsonNode; - -import ch.ivy.addon.portalkit.configuration.AbstractConfiguration; - -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") -@JsonSubTypes({ @Type(value = IvyTool.class, name = "IVY"), - @Type(value = RetrievalQATool.class, name = "RETRIEVAL_QA") }) -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public abstract class AiTool extends AbstractConfiguration - implements Serializable { - - private static final long serialVersionUID = -4652001849527628818L; - - private String name; - private String description; - private List permissions; - private boolean isDefault; - private List steps; - private int workingStepNo; - - public AiTool() { - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getPermissions() { - return permissions; - } - - public void setPermissions(List permissions) { - this.permissions = permissions; - } - - public abstract void init(); - - public boolean isDefault() { - return isDefault; - } - - public void setDefault(boolean isDefault) { - this.isDefault = isDefault; - } - - public abstract ToolType getType(); - - public List getSteps() { - return steps; - } - - public void setSteps(List steps) { - this.steps = steps; - } - - public int getWorkingStepNo() { - return workingStepNo; - } - - public void setWorkingStepNo(int workingStepNo) { - this.workingStepNo = workingStepNo; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AiTool other = (AiTool) obj; - if (getId() == null) { - if (other.getId() != null) - return false; - } else if (!getId().equals(other.getId())) - return false; - return true; - } - - public abstract JsonNode buildJsonNode(); -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/Assistant.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/Assistant.java deleted file mode 100644 index 18561d5b2b2..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/Assistant.java +++ /dev/null @@ -1,178 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.CollectionUtils; - -import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter; -import com.axonivy.portal.components.service.exception.PortalException; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import ch.ivy.addon.portalkit.configuration.AbstractConfiguration; -import ch.ivy.addon.portalkit.service.AiToolService; - -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public class Assistant extends AbstractConfiguration implements Serializable { - - private static final long serialVersionUID = 7885313923903511903L; - - @JsonIgnore - private List toolkit; - - private String name; - private List tools; - - public Assistant() { - this.setIsPublic(true); - } - - public void init(String id, String name) { - setId(id); - this.name = name; - } - - @JsonIgnore - public List getToolkit() { - return toolkit; - } - - @JsonIgnore - public void setToolkit(List toolkit) { - this.toolkit = toolkit; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String toJson() { - return BusinessEntityConverter.entityToJsonValue(this); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Assistant other = (Assistant) obj; - if (getId() == null) { - if (other.getId() != null) - return false; - } else if (!getId().equals(other.getId())) - return false; - return true; - } - - public List getTools() { - return tools; - } - - public void setTools(List tools) { - this.tools = tools; - } - - public void initToolkit() { - if (CollectionUtils.isEmpty(tools)) { - this.toolkit = new ArrayList<>(); - this.tools = new ArrayList<>(); - } - - List allTools = AiToolService.getInstance().getPublicConfig(); - this.toolkit = allTools.stream() - .filter(tool -> this.tools.contains(tool.getId())) - .collect(Collectors.toList()); - } - - public static Assistant addNewAssistant() { - Assistant result = new Assistant(); - result.setId(UUID.randomUUID().toString()); - result.setName(""); - result.setTools(new ArrayList<>()); - result.setToolkit(new ArrayList<>()); - return result; - } - - public String buildDetailsJson() { - ObjectMapper mapper = BusinessEntityConverter.getObjectMapper(); - ObjectNode result; - try { - result = (ObjectNode) mapper - .readTree(BusinessEntityConverter.entityToJsonValue(this)); - } catch (JsonMappingException e) { - throw new PortalException(e); - } catch (JsonProcessingException e) { - throw new PortalException(e); - } - - if (CollectionUtils.isNotEmpty(this.toolkit)) { - ArrayNode toolkitNode = mapper.createArrayNode(); - for (AiTool tool : this.toolkit) { - JsonNode node = tool.buildJsonNode(); - if (node != null) { - toolkitNode.add(node); - } - } - result.set("toolkit", toolkitNode); - } - - result.remove("tools"); - - try { - return mapper.writeValueAsString(result); - } catch (JsonProcessingException e) { - throw new PortalException(e); - } - } - - public void addTool(AiTool tool) { - this.toolkit.add(tool); - this.tools.add(Optional.ofNullable(tool).map(AiTool::getId).orElse("")); - } - - public void removeTool(AiTool toolToRemove) { - if (Optional.ofNullable(toolToRemove).map(AiTool::getId).isEmpty()) { - return; - } - - for (AiTool tool : toolkit) { - if (tool.getId().contentEquals(toolToRemove.getId())) { - toolkit.remove(tool); - break; - } - } - - for (String toolId : tools) { - if (toolId.contentEquals(toolToRemove.getId())) { - tools.remove(toolId); - break; - } - } - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyTool.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyTool.java deleted file mode 100644 index 78071f59d01..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyTool.java +++ /dev/null @@ -1,133 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.collections4.CollectionUtils; - -import com.axonivy.portal.components.enums.ai.RunState; -import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter; -import com.axonivy.portal.components.service.IvyAdapterService; -import com.axonivy.portal.enums.ai.ToolType; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.JsonNode; - -import ch.ivyteam.ivy.environment.Ivy; - -public class IvyTool extends AiTool { - - private static final long serialVersionUID = -5362479525475837795L; - - private List attributes; - private String signature; - private String postAction; - - public List getAttributes() { - return attributes; - } - - public void setAttributes(List attributes) { - this.attributes = attributes; - } - - public String getSignature() { - return signature; - } - - public void setSignature(String signature) { - this.signature = signature; - } - - @Override - public void init() { - } - - @Override - public ToolType getType() { - return ToolType.IVY; - } - - @JsonIgnore - public String getResult() { - if (!hasPermision()) { - setSteps(Arrays.asList(createNoPermisisonStep())); - setWorkingStepNo(0); - return BusinessEntityConverter - .entityToJsonValue(getSteps().get(getWorkingStepNo())); - } - - Map params = new HashMap<>(); - getAttributes().forEach(attr -> { - params.put(attr.getName(), attr.getValue()); - }); - Map result = IvyAdapterService - .startSubProcessInProjectAndAllRequired(getSignature(), params); - - if (CollectionUtils.isEmpty(getSteps())) { - IvyToolStep step = new IvyToolStep(); - step.setStepNo(0); - setWorkingStepNo(0); - step.setToolId(getId()); - step.setPostAction(getPostAction()); - - if (result != null && !result.isEmpty()) { - step.setResult((String) result.get("result")); - step.setDescription(getDescription()); - step.setState(RunState.DONE); - } else { - step.setResult( - "Error happened when proceed your request, please try again."); - step.setState(RunState.ERROR); - } - - setSteps(Arrays.asList(step)); - } - return BusinessEntityConverter - .entityToJsonValue(getSteps().get(getWorkingStepNo())); - } - - @Override - public JsonNode buildJsonNode() { - return BusinessEntityConverter.entityToJsonNode(this); - } - - public String getPostAction() { - return postAction; - } - - public void setPostAction(String postAction) { - this.postAction = postAction; - } - - private boolean hasPermision() { - boolean hasPermission = false; - for (String permission : getPermissions()) { - - // Check if username of login user equals to the permission. - if (permission.startsWith("#")) { - hasPermission = Ivy.session().getSessionUserName() - .contentEquals(permission.substring(1)); - } else { - // Check if the permission is existing in the role list of login user. - hasPermission = Ivy.session().getSessionUser().getAllRoles().stream() - .anyMatch(role -> role.getName().contentEquals(permission)); - } - - if (hasPermission) { - break; - } - } - return hasPermission; - } - - private IvyToolStep createNoPermisisonStep() { - IvyToolStep step = new IvyToolStep(); - step.setStepNo(0); - step.setResult("Sorry, you don't have permission to proceed this request."); - step.setState(RunState.ERROR); - step.setToolId(getId()); - return step; - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolAttribute.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolAttribute.java deleted file mode 100644 index 0c0f9c1c37b..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolAttribute.java +++ /dev/null @@ -1,64 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import java.io.Serializable; - -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonInclude(JsonInclude.Include.ALWAYS) -public class IvyToolAttribute implements Serializable { - - private static final long serialVersionUID = -2291917200620175108L; - - private String name; - private String value; - private String description; - private boolean isRequired; - - public IvyToolAttribute() { - } - - public IvyToolAttribute(String name, String value, String description) { - this.name = name; - this.value = value; - this.description = description; - } - - public IvyToolAttribute(String name, String description, boolean isRequired) { - this.name = name; - this.description = description; - this.isRequired = isRequired; - this.value = ""; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public boolean isRequired() { - return isRequired; - } - - public void setRequired(boolean isRequired) { - this.isRequired = isRequired; - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolStep.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolStep.java deleted file mode 100644 index af781fa0129..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/IvyToolStep.java +++ /dev/null @@ -1,62 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import com.axonivy.portal.components.enums.ai.RunState; -import com.axonivy.portal.enums.ai.StepType; - -public class IvyToolStep { - private int stepNo; - private StepType type; - private String description; - private String result; - private RunState state; - private String toolId; - private String postAction; - - public int getStepNo() { - return stepNo; - } - public void setStepNo(int stepNo) { - this.stepNo = stepNo; - } - public String getDescription() { - return description; - } - public void setDescription(String description) { - this.description = description; - } - public String getResult() { - return result; - } - public void setResult(String result) { - this.result = result; - } - public RunState getState() { - return state; - } - public void setState(RunState state) { - this.state = state; - } - - public String getToolId() { - return toolId; - } - - public void setToolId(String toolId) { - this.toolId = toolId; - } - - public String getPostAction() { - return postAction; - } - - public void setPostAction(String postAction) { - this.postAction = postAction; - } - - public StepType getType() { - return type; - } - public void setType(StepType type) { - this.type = type; - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/RetrievalQATool.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/RetrievalQATool.java deleted file mode 100644 index 83a30b47d09..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/dto/ai/RetrievalQATool.java +++ /dev/null @@ -1,34 +0,0 @@ -package ch.ivy.addon.portalkit.dto.ai; - -import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter; -import com.axonivy.portal.enums.ai.ToolType; -import com.fasterxml.jackson.databind.JsonNode; - -public class RetrievalQATool extends AiTool { - - private static final long serialVersionUID = -6486736943933821211L; - - private String collection; - - public String getCollection() { - return collection; - } - - public void setCollection(String collection) { - this.collection = collection; - } - - @Override - public void init() { - } - - @Override - public ToolType getType() { - return ToolType.RETRIEVAL_QA; - } - - @Override - public JsonNode buildJsonNode() { - return BusinessEntityConverter.entityToJsonNode(this); - } -} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/enums/PortalVariable.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/enums/PortalVariable.java index db296adf969..d6fc73f7a29 100644 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/enums/PortalVariable.java +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/enums/PortalVariable.java @@ -17,7 +17,6 @@ public enum PortalVariable { CUSTOM_MENU_ITEMS("Portal.CustomMenuItems"), STATISTIC_DATA("Portal.StatisticData"), CHATBOT_ENDPOINT("PortalAiUrl"), - AI_ASSISTANT("Portal.Assistant"), AI_TOOL("Portal.AiTool"), DASHBOARD_MAIN_MENU_ENTRY("Portal.Dashboard.MainMenuEntry"), CLIENT_STATISTIC("Portal.ClientStatistic"); diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiProcessService.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiProcessService.java new file mode 100644 index 00000000000..9d679c542a8 --- /dev/null +++ b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiProcessService.java @@ -0,0 +1,24 @@ +package ch.ivy.addon.portalkit.service; + +import com.axonivy.portal.components.util.ProcessStartUtils; + +import ch.ivyteam.ivy.workflow.IProcessStart; + +public class AiProcessService { + + private static final String AI_DASHBOARD_FRIENDLY_REQUEST_PATH = "Start Processes/AiStart/AssistantDashboard.ivp"; + + private static AiProcessService instance; + + public static AiProcessService getInstance() { + if (instance == null) { + instance = new AiProcessService(); + } + return instance; + } + + public IProcessStart findAssistantDashboardProcess() { + return ProcessStartUtils.findProcessStartByUserFriendlyRequestPath( + AI_DASHBOARD_FRIENDLY_REQUEST_PATH); + } +} diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiToolService.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiToolService.java deleted file mode 100644 index eb01a9185c2..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AiToolService.java +++ /dev/null @@ -1,43 +0,0 @@ -package ch.ivy.addon.portalkit.service; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; - -import ch.ivy.addon.portalkit.dto.ai.AiTool; -import ch.ivy.addon.portalkit.enums.PortalVariable; -import ch.ivy.addon.portalkit.persistence.converter.BusinessEntityConverter; -import ch.ivyteam.ivy.environment.Ivy; - -public class AiToolService extends JsonConfigurationService { - - private static AiToolService instance; - - public static AiToolService getInstance() { - if (instance == null) { - instance = new AiToolService(); - } - return instance; - } - - @Override - public Class getType() { - return AiTool.class; - } - - @Override - public String getConfigKey() { - return PortalVariable.AI_TOOL.key; - } - - @Override - public List getPublicConfig() { - String jsonValue = Ivy.var().get(getConfigKey()); - if (StringUtils.isBlank(jsonValue)) { - return new ArrayList<>(); - } - - return BusinessEntityConverter.jsonValueToEntities(jsonValue, getType()); - } -} \ No newline at end of file diff --git a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AssistantService.java b/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AssistantService.java deleted file mode 100644 index 5b222de5483..00000000000 --- a/AxonIvyPortal/portal/src/ch/ivy/addon/portalkit/service/AssistantService.java +++ /dev/null @@ -1,43 +0,0 @@ -package ch.ivy.addon.portalkit.service; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; - -import ch.ivy.addon.portalkit.dto.ai.Assistant; -import ch.ivy.addon.portalkit.enums.PortalVariable; -import ch.ivy.addon.portalkit.persistence.converter.BusinessEntityConverter; -import ch.ivyteam.ivy.environment.Ivy; - -public class AssistantService extends JsonConfigurationService { - - private static AssistantService instance; - - public static AssistantService getInstance() { - if (instance == null) { - instance = new AssistantService(); - } - return instance; - } - - @Override - public Class getType() { - return Assistant.class; - } - - @Override - public String getConfigKey() { - return PortalVariable.AI_ASSISTANT.key; - } - - @Override - public List getPublicConfig() { - String jsonValue = Ivy.var().get(getConfigKey()); - if (StringUtils.isBlank(jsonValue)) { - return new ArrayList<>(); - } - - return BusinessEntityConverter.jsonValueToEntities(jsonValue, getType()); - } -} diff --git a/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantBean.java b/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantBean.java deleted file mode 100644 index c4e6e8dcc72..00000000000 --- a/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantBean.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.axonivy.portal.bean.ai; - -import java.io.Serializable; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; - -import com.axonivy.portal.components.enums.PortalVariable; - -import ch.ivy.addon.portalkit.dto.ai.AiTool; -import ch.ivy.addon.portalkit.dto.ai.Assistant; -import ch.ivy.addon.portalkit.service.AiToolService; -import ch.ivy.addon.portalkit.service.AssistantService; -import ch.ivyteam.ivy.environment.Ivy; - -public abstract class AssistantBean implements Serializable { - - private static final long serialVersionUID = 1683098437048122830L; - - private Assistant assistant; - private String assistantEndPoint; - private String assistantJson; - private List availableTools; - - public void initBean() { - this.assistantEndPoint = getEndpoint(); - this.assistant = AssistantService.getInstance().getPublicConfig().get(0); - this.assistant.initToolkit(); - this.assistantJson = StringEscapeUtils - .escapeJava(this.assistant.buildDetailsJson()); - - this.setAvailableTools(CollectionUtils - .disjunction(AiToolService.getInstance().getPublicConfig(), - this.assistant.getToolkit()) - .stream().collect(Collectors.toList())); - - } - - public String getEndpoint() { - return Ivy.var().get(PortalVariable.CHATBOT_ENDPOINT.key) - .concat("/assistant/"); - } - - public Assistant getAssistant() { - return assistant; - } - - public void setAssistant(Assistant assistant) { - this.assistant = assistant; - } - - public String getAssistantEndPoint() { - return assistantEndPoint; - } - - public void setAssistantEndPoint(String assistantEndPoint) { - this.assistantEndPoint = assistantEndPoint; - } - - public String getAssistantJson() { - return assistantJson; - } - - public void setAssistantJson(String assistantJson) { - this.assistantJson = assistantJson; - } - - public void addTool(String toolId) { - if (StringUtils.isBlank(toolId)) { - return; - } - - AiTool tool = getAvailableTools().stream() - .filter(t -> t.getId().contentEquals(toolId)).findFirst().get(); - this.assistant.addTool(tool); - getAvailableTools().remove(tool); - } - - public void removeTool(String toolId) { - if (StringUtils.isBlank(toolId)) { - return; - } - AiTool tool = this.assistant.getToolkit().stream() - .filter(t -> t.getId().contentEquals(toolId)).findFirst().get(); - this.assistant.removeTool(tool); - getAvailableTools().add(tool); - } - - public abstract void save(); - - public List getAvailableTools() { - return availableTools; - } - - public void setAvailableTools(List availableTools) { - this.availableTools = availableTools; - } - - public abstract void onCancel(); -} diff --git a/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantManagementBean.java b/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantManagementBean.java deleted file mode 100644 index 3b76b0b9cc0..00000000000 --- a/AxonIvyPortal/portal/src/com/axonivy/portal/bean/ai/AssistantManagementBean.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.axonivy.portal.bean.ai; - -import java.util.ArrayList; -import java.util.List; - -import javax.faces.bean.ManagedBean; -import javax.faces.bean.ViewScoped; - -import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter; -import com.axonivy.portal.enums.ai.ToolType; - -import ch.ivy.addon.portalkit.dto.ai.AiTool; -import ch.ivy.addon.portalkit.dto.ai.Assistant; -import ch.ivy.addon.portalkit.dto.ai.IvyTool; -import ch.ivyteam.ivy.environment.Ivy; - -@ManagedBean -@ViewScoped -public class AssistantManagementBean { - - private ToolType[] toolTypes = ToolType.values(); - - private List assistants; - private List ivyTools; - - private Assistant selectedAssistant; - private AiTool selectedTool; - private boolean isAddNewTool; - - public void init() { - setAssistants(BusinessEntityConverter.jsonValueToEntities(Ivy.var().get("Assistants"), Assistant.class)); - setIvyTools(BusinessEntityConverter.jsonValueToEntities(Ivy.var().get("IvyTools"), IvyTool.class)); - this.isAddNewTool = false; - } - - public List getAssistants() { - return assistants; - } - - public void setAssistants(List assistants) { - this.assistants = assistants; - } - - public Assistant getSelectedAssistant() { - return selectedAssistant; - } - - public void setSelectedAssistant(Assistant selectedAssistant) { - this.selectedAssistant = selectedAssistant; - } - - public AiTool getSelectedTool() { - return selectedTool; - } - - public void setSelectedTool(AiTool selectedTool) { - this.selectedTool = selectedTool; - } - - public boolean isAddNewTool() { - return isAddNewTool; - } - - public void addTool() { - this.isAddNewTool = true; - } - - public void finishAddTool() { - this.isAddNewTool = false; - } - - public ToolType[] getToolTypes() { - return toolTypes; - } - - public void setToolTypes(ToolType[] toolTypes) { - this.toolTypes = toolTypes; - } - - public void onAddNewAssistant() { - this.selectedAssistant = new Assistant(); - this.selectedAssistant.setToolkit(new ArrayList<>()); - } - - public List getIvyTools() { - return ivyTools; - } - - public void setIvyTools(List ivyTools) { - this.ivyTools = ivyTools; - } -} diff --git a/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/StepType.java b/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/StepType.java deleted file mode 100644 index 05aee4b310f..00000000000 --- a/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/StepType.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.axonivy.portal.enums.ai; - -public enum StepType { - USE_TOOL, CUSTOM; -} diff --git a/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/ToolType.java b/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/ToolType.java deleted file mode 100644 index c958dd2b807..00000000000 --- a/AxonIvyPortal/portal/src/com/axonivy/portal/enums/ai/ToolType.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.axonivy.portal.enums.ai; - -public enum ToolType { - - IVY("Ivy", "success"), RETRIEVAL_QA("Q&A", "info"), - COMPOSITE("Composite", "warning"); - - private String label; - private String tagSeverity; - - ToolType(String label, String tagSeverity) { - this.label = label; - this.tagSeverity = tagSeverity; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getTagSeverity() { - return tagSeverity; - } - - public void setTagSeverity(String tagSeverity) { - this.tagSeverity = tagSeverity; - } -} diff --git a/AxonIvyPortal/portal/src/com/axonivy/portal/rest/AssistantRestService.java b/AxonIvyPortal/portal/src/com/axonivy/portal/rest/AssistantRestService.java deleted file mode 100644 index b4e0142ee89..00000000000 --- a/AxonIvyPortal/portal/src/com/axonivy/portal/rest/AssistantRestService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.axonivy.portal.rest; - -import javax.annotation.security.RolesAllowed; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.axonivy.portal.components.persistence.converter.BusinessEntityConverter; -import com.axonivy.portal.payload.IvyToolPayload; - -import ch.ivy.addon.portalkit.dto.ai.IvyTool; -import ch.ivyteam.ivy.security.ISecurityConstants; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; - -@Path(value = "assistant") -@RolesAllowed(value = { ISecurityConstants.TOP_LEVEL_ROLE_NAME }) -public class AssistantRestService { - - @POST - @Path(value = "/ivyTool") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = { @Content(mediaType = MediaType.APPLICATION_JSON) }) }) - public Response proceedIvyTool(IvyToolPayload payload) { - IvyTool tool = BusinessEntityConverter.jsonValueToEntity(payload.getToolJson(), IvyTool.class); - return Response.ok(tool.getResult()).build(); - } -} diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.rddescriptor b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.rddescriptor deleted file mode 100644 index ae605f0d9ad..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.rddescriptor +++ /dev/null @@ -1,7 +0,0 @@ - - - - viewTechnology - JSF - - diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.xhtml b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.xhtml deleted file mode 100644 index 7731324607e..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboard.xhtml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - -
- - - - - - -
- - - - - - -
-
- - -
-

#{ivy.cms.co('/Dialogs/com/axonivy/portal/component/ChatDashboard/WelcomeHeaderText')}

-

#{ivy.cms.co('/Dialogs/com/axonivy/portal/component/ChatDashboard/WelcomeText')}

-
- -
- -
-
-
- #{question.headerText} -
-
-

#{question.question}

-
-
-
-
-
-
-
-
- - diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardData.ivyClass b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardData.ivyClass deleted file mode 100644 index 5844577d66f..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardData.ivyClass +++ /dev/null @@ -1,2 +0,0 @@ -ChatDashboardData #class -com.axonivy.portal.component.ChatDashboard #namespace diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardProcess.p.json b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardProcess.p.json deleted file mode 100644 index 9cffd8bb779..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ChatDashboard/ChatDashboardProcess.p.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema" : "https://json-schema.axonivy.com/process/11.3.0/process.json", - "id" : "18CE74C696F6F830", - "kind" : "HTML_DIALOG", - "config" : { - "data" : "com.axonivy.portal.component.ChatDashboard.ChatDashboardData" - }, - "elements" : [ { - "id" : "f0", - "type" : "HtmlDialogStart", - "name" : "start()", - "config" : { - "signature" : "start", - "guid" : "18CE74C69708A7D2" - }, - "visual" : { - "at" : { "x" : 96, "y" : 64 } - }, - "connect" : [ - { "id" : "f2", "to" : "f1" } - ] - }, { - "id" : "f1", - "type" : "HtmlDialogEnd", - "visual" : { - "at" : { "x" : 224, "y" : 64 } - } - }, { - "id" : "f3", - "type" : "HtmlDialogEventStart", - "name" : "close", - "config" : { - "guid" : "18CE74C6971D6A38" - }, - "visual" : { - "at" : { "x" : 96, "y" : 160 } - }, - "connect" : [ - { "id" : "f5", "to" : "f4" } - ] - }, { - "id" : "f4", - "type" : "HtmlDialogExit", - "visual" : { - "at" : { "x" : 224, "y" : 160 } - } - } ] -} \ No newline at end of file diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.rddescriptor b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.rddescriptor deleted file mode 100644 index ae605f0d9ad..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.rddescriptor +++ /dev/null @@ -1,7 +0,0 @@ - - - - viewTechnology - JSF - - diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.xhtml b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.xhtml deleted file mode 100644 index 304e921bdd3..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolList.xhtml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - #{ivy.cms.co('/Dialogs/com/axonivy/portal/component/ToolList/NoAvailableTools')} - - - - -
-
-
- - - -
- -
- - -
-
-
- -
- - - -
- - - -
- - - - - - - - - -
    - -
  • - - - -
  • -
    -
- -
-
-
-
-
-
- \ No newline at end of file diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListData.ivyClass b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListData.ivyClass deleted file mode 100644 index 7302c690ee9..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListData.ivyClass +++ /dev/null @@ -1,2 +0,0 @@ -ToolListData #class -com.axonivy.portal.component.ToolList #namespace diff --git a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListProcess.p.json b/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListProcess.p.json deleted file mode 100644 index fccadea22e0..00000000000 --- a/AxonIvyPortal/portal/src_hd/com/axonivy/portal/component/ToolList/ToolListProcess.p.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema" : "https://json-schema.axonivy.com/process/11.3.0/process.json", - "id" : "18E38E3B04F37BF5", - "kind" : "HTML_DIALOG", - "config" : { - "data" : "com.axonivy.portal.component.ToolList.ToolListData" - }, - "elements" : [ { - "id" : "f0", - "type" : "HtmlDialogStart", - "name" : "start()", - "config" : { - "signature" : "start", - "guid" : "18E38E3B054BD378" - }, - "visual" : { - "at" : { "x" : 96, "y" : 64 } - }, - "connect" : [ - { "id" : "f2", "to" : "f1" } - ] - }, { - "id" : "f1", - "type" : "HtmlDialogEnd", - "visual" : { - "at" : { "x" : 224, "y" : 64 } - } - }, { - "id" : "f3", - "type" : "HtmlDialogEventStart", - "name" : "close", - "config" : { - "guid" : "18E38E3B056852A0" - }, - "visual" : { - "at" : { "x" : 96, "y" : 160 } - }, - "connect" : [ - { "id" : "f5", "to" : "f4" } - ] - }, { - "id" : "f4", - "type" : "HtmlDialogExit", - "visual" : { - "at" : { "x" : 224, "y" : 160 } - } - } ] -} \ No newline at end of file diff --git a/AxonIvyPortal/portal/webContent/layouts/includes/ChatDashboardTemplate.xhtml b/AxonIvyPortal/portal/webContent/layouts/includes/ChatDashboardTemplate.xhtml deleted file mode 100644 index a3afd31ae17..00000000000 --- a/AxonIvyPortal/portal/webContent/layouts/includes/ChatDashboardTemplate.xhtml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - Portal Chat - - - - - - - - - - - - - - -
- - - -
-
-
-
-
- -
-
- - -
- -
- - -
-
-
-
- - - - - - - -
-
- -
-