Skip to content

Commit

Permalink
Merge pull request #1181 from axonivy-market/feature/IVYPORTAL-17170-…
Browse files Browse the repository at this point in the history
…Stage-1-Start-process-by-name-or-description

IVYPORTAL-17923: Merge Portal AI functions to master
  • Loading branch information
mnhnam-axonivy authored Nov 19, 2024
2 parents f300310 + b77ab49 commit 87d7ae5
Show file tree
Hide file tree
Showing 78 changed files with 3,091 additions and 111 deletions.
5 changes: 5 additions & 0 deletions AxonIvyPortal/portal-components/cms/cms_de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ Dialogs:
IVY_PROCESS: Geschäftsprozess
ProcessViewerIFrameTitle: Prozessbetrachterrahmen
Labels:
AI:
Error:
CanceledFlow: You have canceled the flow. If you have any requests, please let me know.
ErrorWhenProceedRequest: An error has occurred while trying to process your request. Please try again later.
SomethingWentWrong: Something went wrong when proceed your request. Please try again later.
DisabledUserPrefix: (inaktiv)
NoName: kein Name
NoResults: Keine Ergebnisse
Expand Down
5 changes: 5 additions & 0 deletions AxonIvyPortal/portal-components/cms/cms_en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ Dialogs:
IVY_PROCESS: Business Process
ProcessViewerIFrameTitle: Process viewer frame
Labels:
AI:
Error:
CanceledFlow: You have canceled the flow. If you have any requests, please let me know.
ErrorWhenProceedRequest: An error has occurred while trying to process your request. Please try again later.
SomethingWentWrong: Something went wrong when proceed your request. Please try again later.
DisabledUserPrefix: (disabled)
NoName: no name
NoResults: No results
Expand Down
5 changes: 5 additions & 0 deletions AxonIvyPortal/portal-components/cms/cms_es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ Dialogs:
IVY_PROCESS: Proceso de negocio
ProcessViewerIFrameTitle: Marco del visor de procesos
Labels:
AI:
Error:
CanceledFlow: You have canceled the flow. If you have any requests, please let me know.
ErrorWhenProceedRequest: An error has occurred while trying to process your request. Please try again later.
SomethingWentWrong: Something went wrong when proceed your request. Please try again later.
DisabledUserPrefix: (inactivo)
NoName: Sin nombre
NoResults: Sin resultados
Expand Down
5 changes: 5 additions & 0 deletions AxonIvyPortal/portal-components/cms/cms_fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ Dialogs:
IVY_PROCESS: Processus d'entreprise
ProcessViewerIFrameTitle: Cadre de visualisation du processus
Labels:
AI:
Error:
CanceledFlow: You have canceled the flow. If you have any requests, please let me know.
ErrorWhenProceedRequest: An error has occurred while trying to process your request. Please try again later.
SomethingWentWrong: Something went wrong when proceed your request. Please try again later.
DisabledUserPrefix: (désactivé)
NoName: Aucun nom
NoResults: Aucun résultat
Expand Down
1 change: 0 additions & 1 deletion AxonIvyPortal/portal-components/config/variables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
# please add a 'variables.yaml' in the sub directory '_<environment>'.
#
Variables:
#myVariable: value
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;

import com.axonivy.portal.components.dto.SecurityMemberDTO;
import com.axonivy.portal.components.dto.UserDTO;
import com.axonivy.portal.components.util.SecurityMemberDisplayNameUtils;

import ch.ivyteam.ivy.environment.Ivy;
import ch.ivyteam.ivy.security.ISecurityMember;

@ManagedBean
Expand All @@ -19,6 +21,15 @@ public String generateBriefDisplayNameForSecurityMember(ISecurityMember member,
return SecurityMemberDisplayNameUtils.generateBriefDisplayNameForSecurityMember(member, securityMemberName);
}

public String generateBriefDisplayNameForSecurityMember(
SecurityMemberDTO memberDTO) {
ISecurityMember member = Ivy.security().members()
.findById(memberDTO.getSecurityMemberId());
return SecurityMemberDisplayNameUtils
.generateBriefDisplayNameForSecurityMember(member,
member.getMemberName());
}

public String getDisplayNameForUserDTO(UserDTO user) {
return SecurityMemberDisplayNameUtils.generateDisplayNameForUserDTO(user);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.axonivy.portal.components.dto;

import com.axonivy.portal.components.enums.AIState;

public class AiResultDTO {
private String result;
private String resultForAI;
private AIState state;

public String getResult() {
return result;
}

public void setResult(String result) {
this.result = result;
}

public String getResultForAI() {
return resultForAI;
}

public void setResultForAI(String resultForAI) {
this.resultForAI = resultForAI;
}

public AIState getState() {
return state;
}

public void setState(AIState state) {
this.state = state;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.axonivy.portal.components.enums;

import com.fasterxml.jackson.annotation.JsonValue;

public enum AIState {
OPEN, IN_PROGRESS, DONE, ERROR, TRIGGER;

@JsonValue
public String value() {
return this.name().toLowerCase();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ private List<UserDTO> queryUsers(String query, int startIndex, int count, List<S

if (CollectionUtils.isNotEmpty(fromRoles)) {
UserQuery hasRolesQuery = queryHasRoles(fromRoles);
filterQuery.andOverall(hasRolesQuery);
if (hasRolesQuery != null) {
filterQuery.andOverall(hasRolesQuery);
}
}
excludeUsername(excludedUsernames, filterQuery);

Expand Down Expand Up @@ -99,6 +101,10 @@ private UserQuery queryHasRoles(List<String> fromRoles) {
}
}

if (CollectionUtils.isEmpty(roles)) {
return null;
}

UserQuery hasRolesQuery = UserQuery.create();
IFilterQuery hasRolesFilter = hasRolesQuery.where();
for (IRole role : roles) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,78 @@
import com.axonivy.portal.components.service.exception.PortalException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* This class provides method to convert Business entity object into Json value
* and reverse
*/
public final class BusinessEntityConverter {
public static ObjectMapper objectMapper;
public static ObjectMapper objectMapper;

private BusinessEntityConverter() {
}
private BusinessEntityConverter() {
}

public static String entityToJsonValue(BusinessEntity entity) {
try {
return getObjectMapper().writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}
public static String entityToJsonValue(BusinessEntity entity) {
try {
return getObjectMapper().writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}

public static <T> T jsonValueToEntity(String jsonValue, Class<T> classType) {
try {
return getObjectMapper().readValue(jsonValue, classType);
} catch (IOException e) {
throw new PortalException(e);
}
}
public static <T> T jsonValueToEntity(String jsonValue, Class<T> classType) {
try {
return getObjectMapper().readValue(jsonValue, classType);
} catch (IOException e) {
throw new PortalException(e);
}
}

public static String entityToJsonValue(Object entity) {
try {
return getObjectMapper().writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}
public static String entityToJsonValue(Object entity) {
try {
return getObjectMapper().writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}

public static <T> List<T> jsonValueToEntities(String jsonValue, Class<T> classType) {
if (StringUtils.isBlank(jsonValue)) {
return new ArrayList<>();
}
try {
return getObjectMapper().readValue(jsonValue,
getObjectMapper().getTypeFactory().constructCollectionType(List.class, classType));
} catch (IOException e) {
throw new PortalException(e);
}
}
public static JsonNode entityToJsonNode(Object entity) {
try {
return getObjectMapper().readTree(entityToJsonValue(entity));
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}

public static ObjectMapper getObjectMapper() {
if (objectMapper == null) {
objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
return objectMapper;
}
public static <T> List<T> jsonValueToEntities(String jsonValue,
Class<T> classType) {
if (StringUtils.isBlank(jsonValue)) {
return new ArrayList<>();
}
try {
return getObjectMapper().readValue(jsonValue, getObjectMapper()
.getTypeFactory().constructCollectionType(List.class, classType));
} catch (IOException e) {
throw new PortalException(e);
}
}

public static ObjectMapper getObjectMapper() {
if (objectMapper == null) {
objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
return objectMapper;
}

public static String prettyPrintEntityToJsonValue(Object entity) {
try {
return getObjectMapper().writerWithDefaultPrettyPrinter()
.writeValueAsString(entity);
} catch (JsonProcessingException e) {
throw new PortalException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.axonivy.portal.components.publicapi;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.axonivy.portal.components.dto.AiResultDTO;
import com.axonivy.portal.components.enums.AIState;
import com.axonivy.portal.components.service.impl.ProcessService;

import ch.ivyteam.ivy.environment.Ivy;
import ch.ivyteam.ivy.workflow.start.IWebStartable;
import ch.ivyteam.util.ExceptionUtil;

public class AiAssistantAPI {
private static final String IFRAME_RESULT_PATTERN = "<iframe>%s</iframe>";
private static final String EXECUTE_RESULT_PATTERN = "<execute>%s</execute>";

public static void addIframeIvyProcessLinkToAiResult(String link,
Map<String, String> params, AiResultDTO result) {
try {
IWebStartable process = initWebStartable(link);
result.setResult(String.format(IFRAME_RESULT_PATTERN,
process.getLink().queryParams(params).getRelative()));
} catch (Exception e) {
result = generateErrorAiResult(e,
Ivy.cms().co("/Labels/AI/Error/ErrorWhenProceedRequest"));
}
}

public static String generateExecutableResult(String link) {
return String.format(EXECUTE_RESULT_PATTERN, link);
}

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 AiResultDTO generateErrorAiResult(Throwable error,
String errorDescription) {
AiResultDTO result = new AiResultDTO();
result.setResult(errorDescription.concat(StringUtils.LF)
.concat(ExceptionUtil.getAllMessages(error)));
result.setState(AIState.ERROR);

return result;
}

public static AiResultDTO generateErrorAiResult(String error) {
AiResultDTO result = new AiResultDTO();
result.setResult(error);
result.setResultForAI(error);
result.setState(AIState.ERROR);

return result;
}

public static AiResultDTO createSomethingWentWrongError() {
AiResultDTO result = new AiResultDTO();
result.setResult(Ivy.cms().co("/Labels/AI/Error/SomethingWentWrong"));
result.setState(AIState.ERROR);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;


import ch.ivyteam.ivy.environment.Ivy;
import ch.ivyteam.ivy.security.exec.Sudo;
import ch.ivyteam.ivy.workflow.IWorkflowSession;
Expand All @@ -37,6 +36,14 @@ public List<IWebStartable> findProcesses() {
});
}

public List<IWebStartable> findAllProcesses() {
return Sudo.get(() -> {
return Ivy.session().getAllStartables()
.filter(process -> isNotPortalHomeAndMSTeamsProcess(process))
.collect(Collectors.toList());
});
}

private List<IWebStartable> findStartablesWithoutPortalHomeAndMSTeamsProcess(IWorkflowSession session) {
return session.getStartables().stream().filter(process -> isNotPortalHomeAndMSTeamsProcess(process))
.collect(Collectors.toList());
Expand All @@ -55,4 +62,4 @@ public List<IWebStartable> findCustomDashboardProcesses() {
private Predicate<? super IWebStartable> filterByCustomDashboardProcess() {
return start -> BooleanUtils.toBoolean(start.customFields().value(IS_DASHBOARD_PROCESS));
}
}
}
Loading

0 comments on commit 87d7ae5

Please sign in to comment.