From e3b8c2d8f50d0c8a48bfd9710cbc8ee9b23acc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20V=C4=A9nh=20Thi=E1=BB=87n=20Ph=C3=BAc?= Date: Thu, 5 Dec 2024 10:56:03 +0700 Subject: [PATCH 1/5] MARP-1546 Add error message for popup --- .../vertexai/managedBean/GeminiDataBean.java | 26 ++++++++++++++++--- .../vertexai/chatWithAi/chatWithAi.xhtml | 4 +++ .../webContent/layouts/styles/chatwithai.css | 18 ++++++------- .../utils/GeminiDataRequestServiceUtils.java | 11 +++++++- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java b/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java index 1e3e6ed..8f00440 100644 --- a/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java +++ b/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java @@ -13,6 +13,8 @@ import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.primefaces.PrimeFaces; + import com.axonivy.connector.vertexai.entities.*; import com.axonivy.connector.vertexai.enums.Model; import com.axonivy.connector.vertexai.enums.Role; @@ -25,11 +27,13 @@ public class GeminiDataBean { private Model model; private List conversations; private GeminiDataRequestService geminiDataRequestService = new GeminiDataRequestService(); - + private String errorMessage; + private static final String CODE_RESPONSE_PATTERN = "```(.*?)```"; private static final String PRE_TAG_PATTERN = "(.*?)"; private static final String EMOJI_PATTERN = "[\\uD83C-\\uDBFF\\uDC00-\\uDFFF]"; private static final Set PREFIXES = Set.of("html", "xml", "xhtml"); + private static final String OPEN_ERROR_DIALOG_SCRIPT = "PF('errorDialog').show();"; private static String PRE_TAG_MAPPING = "
 %s 
"; @PostConstruct @@ -39,9 +43,14 @@ public void init() { } public void onSendRequest() throws Exception { - conversations = geminiDataRequestService.sendRequestToGemini(inputtedMessage, model); - addCodesToPreTagIfPresent(conversations); - inputtedMessage = StringUtils.EMPTY; + try { + conversations = geminiDataRequestService.sendRequestToGemini(inputtedMessage, model); + addCodesToPreTagIfPresent(conversations); + inputtedMessage = StringUtils.EMPTY; + } catch (Exception e) { + errorMessage = e.getMessage(); + PrimeFaces.current().executeScript(OPEN_ERROR_DIALOG_SCRIPT); + } } public void addCodesToPreTagIfPresent(List conversations) { @@ -154,4 +163,13 @@ public List getConversations() { public void setConversations(List conversations) { this.conversations = conversations; } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + } diff --git a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml index 962d2fd..b82357a 100644 --- a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml +++ b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml @@ -13,6 +13,10 @@ + + +
diff --git a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css index d80b821..ef81f0c 100644 --- a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css +++ b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css @@ -1,8 +1,8 @@ #article-content { - width: 100%; /* Set the desired width */ - overflow-x: auto; /* Enable horizontal scrolling if needed */ - overflow-y: auto; /* Enable vertical scrolling if needed */ - max-height: 300px; /* Set the maximum height for the div */ + width: 100%; + overflow-x: auto; + overflow-y: auto; + max-height: 300px; } #editor { @@ -37,22 +37,22 @@ .form-container { display: flex; flex-direction: column; - height: 100vh; /* Ensure it takes the full height of the viewport */ + height: 95vh; } .ui-panelgrid-blank { - flex: 1; /* Make the panel grid take available space */ - overflow-y: auto; /* Add scroll if content overflows */ + flex: 1; + overflow-y: auto; } .form-bottom { display: flex; flex-direction: column; - margin-top: auto; /* Push this section to the bottom */ + margin-top: auto; } .command-btns { display: flex; justify-content: space-between; - margin-top: 10px; /* Add some spacing between the editor and buttons */ + margin-top: 10px; } \ No newline at end of file diff --git a/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java b/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java index 42ace10..f592e07 100644 --- a/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java +++ b/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java @@ -30,7 +30,16 @@ public class GeminiDataRequestServiceUtils { public static final String IMG_SRC_ATTR_PATTERN = "data:image\\/[^;]+;base64,([^\"]+)"; public static InputStream getInputStream(String keyFilePath) throws IOException { - return new FileInputStream(keyFilePath); + if (StringUtils.isBlank(keyFilePath)) { + throw new IOException("VertexAi credential file path is empty"); + } + + try { + return new FileInputStream(keyFilePath); + } catch (IOException exception) { + throw new IOException("Could not find VertexAi credential file by path " + keyFilePath); + } + } public Content formatRequest(String message) { From 518983b0f689e1072d39530e78d15334363b05ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20V=C4=A9nh=20Thi=E1=BB=87n=20Ph=C3=BAc?= Date: Fri, 6 Dec 2024 10:32:30 +0700 Subject: [PATCH 2/5] MARP-1546 Handle Feedbacks --- .../vertexai/chatWithAi/chatWithAi.xhtml | 17 ++++++++++++++--- .../webContent/layouts/styles/chatwithai.css | 15 +++++++++++++++ .../utils/GeminiDataRequestServiceUtils.java | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml index b82357a..d37c4d5 100644 --- a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml +++ b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml @@ -13,10 +13,21 @@ - - + +
+ + +
+
+
+ +
+
diff --git a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css index ef81f0c..86ee067 100644 --- a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css +++ b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css @@ -55,4 +55,19 @@ display: flex; justify-content: space-between; margin-top: 10px; +} + +.cancel-error-dialog-button { + display: flex; + justify-content: flex-end; +} + +.icon-error-message { + display: flex; + align-items: center; + gap: 10px; +} + +.error-message { + font-size: 14px; } \ No newline at end of file diff --git a/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java b/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java index f592e07..a4e4023 100644 --- a/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java +++ b/vertexai-google/src/com/axonivy/connector/vertexai/utils/GeminiDataRequestServiceUtils.java @@ -31,7 +31,7 @@ public class GeminiDataRequestServiceUtils { public static InputStream getInputStream(String keyFilePath) throws IOException { if (StringUtils.isBlank(keyFilePath)) { - throw new IOException("VertexAi credential file path is empty"); + throw new IOException("Vertex AI credential file path is missing. Please provide it and try again!"); } try { From b5b8dd31677f6db684244bfe980f66e8908cd350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20V=C4=A9nh=20Thi=E1=BB=87n=20Ph=C3=BAc?= Date: Fri, 6 Dec 2024 14:10:19 +0700 Subject: [PATCH 3/5] MARP-1546 Handle Feedbacks --- .../vertexai/managedBean/GeminiDataBean.java | 6 +-- .../vertexai/chatWithAi/chatWithAi.xhtml | 54 +++++++++---------- .../webContent/layouts/styles/chatwithai.css | 5 ++ .../GeminiDataRequestServiceUtilTest.java | 44 +++++++++++++++ 4 files changed, 77 insertions(+), 32 deletions(-) diff --git a/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java b/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java index 8f00440..974a302 100644 --- a/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java +++ b/vertexai-google-demo/src/com/axonivy/connector/vertexai/managedBean/GeminiDataBean.java @@ -13,7 +13,7 @@ import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.primefaces.PrimeFaces; +import org.primefaces.PF; import com.axonivy.connector.vertexai.entities.*; import com.axonivy.connector.vertexai.enums.Model; @@ -42,14 +42,14 @@ public void init() { geminiDataRequestService.cleanData(); } - public void onSendRequest() throws Exception { + public void onSendRequest() { try { conversations = geminiDataRequestService.sendRequestToGemini(inputtedMessage, model); addCodesToPreTagIfPresent(conversations); inputtedMessage = StringUtils.EMPTY; } catch (Exception e) { errorMessage = e.getMessage(); - PrimeFaces.current().executeScript(OPEN_ERROR_DIALOG_SCRIPT); + PF.current().executeScript(OPEN_ERROR_DIALOG_SCRIPT); } } diff --git a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml index d37c4d5..81ea0da 100644 --- a/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml +++ b/vertexai-google-demo/src_hd/com/axonivy/connector/vertexai/chatWithAi/chatWithAi.xhtml @@ -17,9 +17,9 @@ showEffect="fade" hideEffect="fade" closable="true" responsive="true">
- - + +

@@ -82,32 +82,28 @@
- diff --git a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css index 86ee067..3f55c77 100644 --- a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css +++ b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css @@ -70,4 +70,9 @@ .error-message { font-size: 14px; +} + +i { + font-size: 24px !important; + color: orange; } \ No newline at end of file diff --git a/vertexai-google-test/src_test/com/axonivy/connector/vertexai/test/utils/GeminiDataRequestServiceUtilTest.java b/vertexai-google-test/src_test/com/axonivy/connector/vertexai/test/utils/GeminiDataRequestServiceUtilTest.java index 5530dd1..6a06bff 100644 --- a/vertexai-google-test/src_test/com/axonivy/connector/vertexai/test/utils/GeminiDataRequestServiceUtilTest.java +++ b/vertexai-google-test/src_test/com/axonivy/connector/vertexai/test/utils/GeminiDataRequestServiceUtilTest.java @@ -1,10 +1,20 @@ package com.axonivy.connector.vertexai.test.utils; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + import com.axonivy.connector.vertexai.entities.Content; import com.axonivy.connector.vertexai.utils.GeminiDataRequestServiceUtils; import com.google.gson.Gson; @@ -15,8 +25,12 @@ public class GeminiDataRequestServiceUtilTest { public static final String IMG_TAG_PATTERN = "]*>"; public static final String IMG_SRC_ATTR_PATTERN = "data:image\\/[^;]+;base64,([^\"]+)"; + private GeminiDataRequestServiceUtils geminiDataRequestServiceUtils = new GeminiDataRequestServiceUtils(); + + @TempDir + Path tempDir; @BeforeEach void beforeEach(AppFixture fixture) { @@ -83,5 +97,35 @@ public void formatRequest_test() { assertThat(result).usingRecursiveComparison().ignoringFields("id") .isEqualTo(new Gson().fromJson(expectedResult, Content.class)); } + + @Test + void testGetInputStream_BlankKeyFilePath() { + IOException exception = assertThrows(IOException.class, () -> { + GeminiDataRequestServiceUtils.getInputStream(""); + }); + assertEquals("Vertex AI credential file path is missing. Please provide it and try again!", exception.getMessage()); + } + + @Test + void testGetInputStream_FileNotFound() { + String invalidFilePath = tempDir.resolve("nonexistent-file.txt").toString(); + + IOException exception = assertThrows(IOException.class, () -> { + GeminiDataRequestServiceUtils.getInputStream(invalidFilePath); + }); + assertEquals("Could not find VertexAi credential file by path " + invalidFilePath, exception.getMessage()); + } + + @Test + void testGetInputStream_ValidKeyFilePath() throws IOException { + // Create a temporary file + Path tempFile = tempDir.resolve("valid-file.txt"); + File file = tempFile.toFile(); + assertTrue(file.createNewFile()); + + try (InputStream inputStream = GeminiDataRequestServiceUtils.getInputStream(tempFile.toString())) { + assertNotNull(inputStream); + } + } } From 6932c1c9ab458cab8214ab16c06dd22fae34bdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20V=C4=A9nh=20Thi=E1=BB=87n=20Ph=C3=BAc?= Date: Fri, 6 Dec 2024 14:53:59 +0700 Subject: [PATCH 4/5] MARP-1546 Handle Feedbacks --- .../webContent/layouts/styles/chatwithai.css | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css index 3f55c77..1bee108 100644 --- a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css +++ b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css @@ -28,33 +28,33 @@ } .output-text { - background-color: var(--surface-a); + background-color: var(- -surface-a); white-space: pre-line; display: block; padding: 10px 20px; } .form-container { - display: flex; - flex-direction: column; - height: 95vh; + display: flex; + flex-direction: column; + height: 95vh; } .ui-panelgrid-blank { - flex: 1; - overflow-y: auto; + flex: 1; + overflow-y: auto; } .form-bottom { - display: flex; - flex-direction: column; - margin-top: auto; + display: flex; + flex-direction: column; + margin-top: auto; } .command-btns { - display: flex; - justify-content: space-between; - margin-top: 10px; + display: flex; + justify-content: space-between; + margin-top: 10px; } .cancel-error-dialog-button { From 38c4595ecc5fe938ef62edb1f7050e1466e7b76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20V=C4=A9nh=20Thi=E1=BB=87n=20Ph=C3=BAc?= Date: Fri, 6 Dec 2024 15:04:35 +0700 Subject: [PATCH 5/5] MARP-1546 Handle Feedbacks --- vertexai-google-demo/webContent/layouts/styles/chatwithai.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css index 1bee108..b7d0d16 100644 --- a/vertexai-google-demo/webContent/layouts/styles/chatwithai.css +++ b/vertexai-google-demo/webContent/layouts/styles/chatwithai.css @@ -28,7 +28,7 @@ } .output-text { - background-color: var(- -surface-a); + background-color: var(--surface-a); white-space: pre-line; display: block; padding: 10px 20px;