From edcc6f80473cd9e6d214364f4cbbd07c23c275dd Mon Sep 17 00:00:00 2001 From: jacekpluta <73617938+jacekpluta@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:47:41 +0200 Subject: [PATCH] [ACS-8201] Knowledge Retrieval - getting AI response for one or more selected files (#4127) * [ACS-8202] basic flow getting ai response for one or more selected files (#3936) * ACS-8202 Added animated icon * ACS-8202 Added search ai input * ACS-8202 Added AI search results page * ACS-8202 Allow to run knowledge retrieval on files inside library, shared, favourites and recent files * ACS-8202 Hide icon when selected more than 100 files or non text files * ACS-8202 Display notification when too many files are selected * ACS-8202 Added agents dropdown * ACS-8202 Styles for AI response * ACS-8202 Applied design changes * ACS-8202 Added query card to Knowledge retrieval page results * ACS-8202 Fixed search collapsing when opened results page * ACS-8202 Changed placeholder in input for results page, wrapping text and scrolling for results page * ACS-8202 Display snackbar with messages when conditions are not met * ACS-8202 Disallow run knowledge retrieval for libraries, leave input when click on x button * ACS-8202 Renaming files * ACS-8202 Trigger ai input by selecting agent instead of clicking on button * ACS-8202 Reverted triggering showing input by selecting option from select * ACS-8202 Display dropdown with agents by clicking on button * ACS-8202 Structural changes - services and agents button component * ACS-8202 Removed part for examples from search page * ACS-8202 Simplified html for search page * ACS-8202 Refactored html and styles for search page, translations for search page * ACS-8202 More html and styles refactoring * ACS-8202 Formatting html * ACS-8202 Removed references to angular material classes * ACS-8202 Added data automation id attributes * ACS-8202 Load agents from backend, formatting html for agents button component and adding data automation ids to that component * ACS-8202 Correction after rebase * ACS-8202 Set agent for input based on selected agent from dropdown for agents button * ACS-8202 Hide agent button for libraries pages and use translations for warnings when clicked on agents button * ACS-8202 Pass agent id to search results page * ACS-8202 Used form control instead of ngmodel for search query * ACS-8202 Moved search ai service and search ai input state to ADF * ACS-8202 Results page ts clean up * ACS-8202 Used ask and getAnswer functions from search ai service * ACS-8202 Cleaning of search ai navigation service * ACS-8202 Small clean ups * ACS-8202 Renamed sources to references * ACS-8202 Fixed asking next question from results page * ACS-8202 Added possibility to use knowledge retrieval from search results page * ACS-8202 Fixed issue with selecting the same agent after previously closing input on search results page * ACS-8202 Disallowed using knowledge retrieval on trash page * ACS-8202 Hide toggling knowledge retrieval for tasks and processes, fixed displaying ask button for favorites page * ACS-8202 Removed redundant image and function * ACS-8202 Renamed breadcrumbTemplate to header * ACS-8202 Removed redundant code, added some comments, made some fields as private * ACS-8202 Display error message on search page * ACS-8202 Accessibility changes * ACS-8202 Small correction * ACS-8202 Addressed comments * ACS-8202 Displayed correct initials * ACS-8202 Removed redundant imports * ACS-8202 Change css value * ACS-8202 Removed icon animation * ACS-8202 Removed icon animation * ACS-8201 Small correction after rebasing with Angular 15 * [ACS-8398] unit tests (#3973) * ACS-8398 Unit tests for agents button and part for agents menu * ACS-8398 Unit tests for search ai input component * [ACS-8210] Agent basic details popup (#3942) * [ACS-8210] Agent basic details popup * [ACS-8210] Agent basic details popup - review fixes --------- Co-authored-by: Aleksander Sklorz * [ACS-8382] Blurring the AI answer section before getting response from backend (#3948) * [ACS-8398] Unit tests part 2 (#3989) * ACS-8398 Unit tests for search ai input container * ACS-8398 Unit tests for search ai navigation service and rest tests for search ai input container component * ACS-8398 Added missing type * [ACS-8484] Add feature flag to knowledge retrieval (#4003) * [ACS-8562] "Ask Agent" button name is changed to "Ask Discovery" * [ACS-8573] Allow user to ask question without file selection * [ACS-8312] Display warning about losing response (#4012) * ACS-8201 Fixed issues after rebase * [ACS-8588] Navigation is triggered twice when leaving Knowledge Retrieval page (#4030) [ACS-8588] Navigation is triggered twice when leaving Knowledge Retrieval page * [ACS-8399] Integrate all changes with backend (#4076) * [ACS-8399] Integrate all changes with backend * [ACS-8399] Integrate all changes with backend - review fixes * Answers endpoint fix * Answers endpoint fix (#4107) * [ACS-8664] generic question redirection to hx insight page (#4102) * ACS-8664 Open page in new tab * ACS-8664 Loading HX insight url * ACS-8664 Unit tests * ACS-8664 Fix after rebasing * ACS-8664 Fixed unit tests * ACS-8664 Added type * ACS-8664 Removed duplicated lines * ACS-8664 Removed duplicated lines * ACS-8664 Addressed comments * [ACS-8695] Getting Agent avatar (#4110) * [ACS-8695] Getting Agent avatar * [ACS-8695] Getting Agent avatar - fixes * [ACS-8695] Getting Agent avatar - fixes 2 * Adding mocked agent avatars (#4117) * [ACS-8201] review fixes * [ACS-8201] review fixes * [E2E] excluded failing tests to fix later pt.1 * [ACS-8767] allow to open referenced files (#4129) * ACS-8767 Opening referenced files * ACS-8767 Reverted one line * ACS-8767 Removed unwanted code * ACS-8767 * ACS-8767 Unit tests for allowing clicking on references * ACS-8767 Unit tests * ACS-8767 Moved duplicated code to function * ACS-8767 Resolved sonar issue * ACS-8767 Resolved sonar issue * [ACS-8201] knowledge retrieval feature flag - false * [E2E] excluded failing tests to fix later pt.2 * ACS-8201 Fixed tests --------- Co-authored-by: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com> Co-authored-by: Aleksander Sklorz Co-authored-by: datguychen --- app/src/app.config.json | 3 +- app/src/assets/images/avatars/Blue.png | Bin 0 -> 102159 bytes app/src/assets/images/avatars/Gold.png | Bin 0 -> 98762 bytes app/src/assets/images/avatars/Pink.png | Bin 0 -> 99313 bytes .../copy-move-actions/exclude.tests.json | 14 +- .../delete-actions/exclude.tests.json | 17 +- .../edit-actions/exclude.tests.json | 4 +- e2e/playwright/navigation/exclude.tests.json | 4 +- e2e/playwright/search/exclude.tests.json | 3 +- .../exclude.tests.json | 4 +- .../aca-content/assets/app.extensions.json | 29 ++ projects/aca-content/assets/i18n/en.json | 36 ++ .../assets/images/colored-stars-ai.svg | 19 + .../assets/images/three-magic-stars-ai.svg | 19 + .../aca-content/src/lib/aca-content.module.ts | 3 + .../aca-content/src/lib/aca-content.routes.ts | 269 +++------- .../favorites/favorites.component.html | 12 +- .../favorites/favorites.component.ts | 5 +- .../lib/components/files/files.component.html | 22 +- .../lib/components/files/files.component.ts | 5 +- .../agents-button.component.html | 37 ++ .../agents-button.component.scss | 74 +++ .../agents-button.component.spec.ts | 461 ++++++++++++++++++ .../agents-button/agents-button.component.ts | 148 ++++++ .../search-ai-input-container.component.html | 18 + .../search-ai-input-container.component.scss | 18 + ...earch-ai-input-container.component.spec.ts | 186 +++++++ .../search-ai-input-container.component.ts | 81 +++ .../search-ai-input.component.html | 63 +++ .../search-ai-input.component.scss | 183 +++++++ .../search-ai-input.component.spec.ts | 431 ++++++++++++++++ .../search-ai-input.component.ts | 187 +++++++ .../search-ai-results.component.html | 116 +++++ .../search-ai-results.component.scss | 182 +++++++ .../search-ai-results.component.spec.ts | 372 ++++++++++++++ .../search-ai-results.component.ts | 245 ++++++++++ .../search-ai/search-ai-utils.ts | 35 ++ .../recent-files/recent-files.component.html | 12 +- .../recent-files/recent-files.component.ts | 5 +- .../search-results.component.html | 16 +- .../search-results.component.scss | 7 + .../search-results.component.ts | 4 +- .../shared-files/shared-files.component.html | 12 +- .../shared-files/shared-files.component.ts | 5 +- .../expansion-panel.directive.spec.ts | 20 + .../directives/expansion-panel.directive.ts | 2 +- .../src/lib/services/modal-ai.service.spec.ts | 114 +++++ .../src/lib/services/modal-ai.service.ts | 62 +++ .../search-ai-navigation.service.spec.ts | 134 +++++ .../services/search-ai-navigation.service.ts | 48 ++ .../src/lib/store/app-store.module.ts | 3 + projects/aca-content/src/lib/store/effects.ts | 1 + .../lib/store/effects/search-ai.effects.ts | 65 +++ .../aca-content/src/lib/ui/application.scss | 8 + projects/aca-content/src/lib/ui/theme.scss | 6 + .../src/lib/ui/variables/variables.scss | 14 +- .../src/lib/services/viewer.service.spec.ts | 5 + .../viewer/src/lib/services/viewer.service.ts | 39 +- projects/aca-content/viewer/src/public-api.ts | 1 + .../aca-shared/rules/src/app.rules.spec.ts | 43 +- projects/aca-shared/rules/src/app.rules.ts | 8 + .../document-base-page.component.ts | 22 +- .../store/src/actions/search-ai.actions.ts | 42 ++ .../src/models/ai-search-by-term-payload.ts | 28 ++ projects/aca-shared/store/src/public-api.ts | 2 + 65 files changed, 3778 insertions(+), 255 deletions(-) create mode 100644 app/src/assets/images/avatars/Blue.png create mode 100644 app/src/assets/images/avatars/Gold.png create mode 100644 app/src/assets/images/avatars/Pink.png create mode 100644 projects/aca-content/assets/images/colored-stars-ai.svg create mode 100644 projects/aca-content/assets/images/three-magic-stars-ai.svg create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.html create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.scss create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.spec.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.html create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.scss create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.spec.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.html create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.scss create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.spec.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.html create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.scss create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.spec.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.ts create mode 100644 projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-utils.ts create mode 100644 projects/aca-content/src/lib/services/modal-ai.service.spec.ts create mode 100644 projects/aca-content/src/lib/services/modal-ai.service.ts create mode 100644 projects/aca-content/src/lib/services/search-ai-navigation.service.spec.ts create mode 100644 projects/aca-content/src/lib/services/search-ai-navigation.service.ts create mode 100644 projects/aca-content/src/lib/store/effects/search-ai.effects.ts create mode 100644 projects/aca-shared/store/src/actions/search-ai.actions.ts create mode 100644 projects/aca-shared/store/src/models/ai-search-by-term-payload.ts diff --git a/app/src/app.config.json b/app/src/app.config.json index d8e9f13ef..9e3a71950 100644 --- a/app/src/app.config.json +++ b/app/src/app.config.json @@ -14,7 +14,8 @@ "contentService": true, "folderRules": true, "tagsEnabled": true, - "categoriesEnabled": true + "categoriesEnabled": true, + "knowledgeRetrievalEnabled": false }, "oauth2": { "host": "{protocol}//{hostname}{:port}/auth/realms/alfresco", diff --git a/app/src/assets/images/avatars/Blue.png b/app/src/assets/images/avatars/Blue.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb695ab3f4e32d1b441225f0330d0e21017be73 GIT binary patch literal 102159 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

NJi9x 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�${DL(Xp0TdpG2)lHyzh;jP#kfeM824 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 literal 0 HcmV?d00001 diff --git a/app/src/assets/images/avatars/Gold.png b/app/src/assets/images/avatars/Gold.png new file mode 100644 index 0000000000000000000000000000000000000000..0298736e0908c5b8afa6c9b1b785567b31bca0ae GIT binary patch literal 98762 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 literal 0 HcmV?d00001 diff --git a/app/src/assets/images/avatars/Pink.png b/app/src/assets/images/avatars/Pink.png new file mode 100644 index 0000000000000000000000000000000000000000..9070620536a62d810026c5206dfe539d7bf78876 GIT binary patch literal 99313 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

m>ccy1d6#zY*g^;d_)})c zF;^7@qThG;J<Zb|tWvMJB&QX#$WG>}(*|HWo-LIVmd@y;V^z0N%H+GahJs8pu$^-n zPu#tPXY!_J3fHrTQp0EErD3+O&i|ktc#Yn(VcAeb9QbV_gDdnYHS;Mo?cR?L6<@w= z?_73j={}}_#59frksJ~2386aPl3(zo&i#!1znhAbSm$vpUq)3ToF$Dc()TIll)lAz zUy4siF9A3VpHsYDsC5ZHT@{ylTnJc5{FDT2hIZ%k(%hBD;YUOWZ$BNxi=u^jYq^GJ zX_oi%xK%#7Xo8x}6_yxBpQ%!rD!G-nFyaUOX#)wxY7{}f#A^Y&kPRgj7x;0S6I{#w z**pAh%ONwcr06+Wl8%k1tI{InjVIMQ*D3%N_&#}GFBXa7hC@>q_WM4+ac^4pk{Ouv z0)1-YTY zSsTdHn$B)T(eqJ#z4odv>*OKBRpI+%MW`m%a}GUmDLpZNv!i{CZ&icAM)QN(z)Rv@ z-KZ#EONGWL*m+vA`I;HYB3n5dwN=;04z4eW(ZS3!bYalLljb||s#)D`S9Rk3*2UXc zqzb331{xZ&S6!bE<>2@AK}I^Alh4_2^}TQS{%Eo9#zvSaE}?=?LPjU{-mX~IG*{h4 zH>306l|Pe(f`F@!yyno&4^fYT1TjLtwzx8A57(kyn3@@vDo{Lh#xM5sp)V&hvbws? zG)4++_hlq`8U$+B>ockux^bEF{bFBfKKrfSIZM0Mm;Dd2H(IO{j2YBQF3BW)5|d@B$@vU`A00aLjMoSo}Ir`Wn2d=TJt$C2s+g+q$ zU+ZE}{?xX-rmR+;{XSHEvNF|mYR?_@5ZykB`?Y6|x=eVzOSM;@X>>VD)p)eG`9p$s zQB|$0eEj6(@TjiC`<0MXg=L*7BlB11%55mCIUarAvPtmEp@@ST@a~_#{~s8ba@E<3 z+Jr3b`p_FN6I}0q{{F$hKN$E21OH&)|1Ji0Ni BS;YVV literal 0 HcmV?d00001 diff --git a/e2e/playwright/copy-move-actions/exclude.tests.json b/e2e/playwright/copy-move-actions/exclude.tests.json index 0967ef424..db5930c4b 100644 --- a/e2e/playwright/copy-move-actions/exclude.tests.json +++ b/e2e/playwright/copy-move-actions/exclude.tests.json @@ -1 +1,13 @@ -{} +{ + "C217135": "https://hyland.atlassian.net/browse/ACS-8812", + "C291888": "https://hyland.atlassian.net/browse/ACS-8812", + "C291889": "https://hyland.atlassian.net/browse/ACS-8812", + "C217137": "https://hyland.atlassian.net/browse/ACS-8812", + "C217138": "https://hyland.atlassian.net/browse/ACS-8812", + "C217139": "https://hyland.atlassian.net/browse/ACS-8812", + "C217140": "https://hyland.atlassian.net/browse/ACS-8812", + "C217171": "https://hyland.atlassian.net/browse/ACS-8812", + "C217172": "https://hyland.atlassian.net/browse/ACS-8812", + "C217173": "https://hyland.atlassian.net/browse/ACS-8812", + "C217174": "https://hyland.atlassian.net/browse/ACS-8812" +} diff --git a/e2e/playwright/delete-actions/exclude.tests.json b/e2e/playwright/delete-actions/exclude.tests.json index 893d21a54..00ab00aba 100644 --- a/e2e/playwright/delete-actions/exclude.tests.json +++ b/e2e/playwright/delete-actions/exclude.tests.json @@ -1,3 +1,18 @@ { - "C280502": "https://hyland.atlassian.net/browse/ACS-8200" + "C217125": "https://hyland.atlassian.net/browse/ACS-8812", + "C217129": "https://hyland.atlassian.net/browse/ACS-8812", + "C217091": "https://hyland.atlassian.net/browse/ACS-8812", + "C280416": "https://hyland.atlassian.net/browse/ACS-8812", + "C290103": "https://hyland.atlassian.net/browse/ACS-8812", + "C280417": "https://hyland.atlassian.net/browse/ACS-8812", + "C217177": "https://hyland.atlassian.net/browse/ACS-8812", + "C280438": "https://hyland.atlassian.net/browse/ACS-8812", + "C290104": "https://hyland.atlassian.net/browse/ACS-8812", + "C217182": "https://hyland.atlassian.net/browse/ACS-8812", + "C217178": "https://hyland.atlassian.net/browse/ACS-8812", + "C217179": "https://hyland.atlassian.net/browse/ACS-8812", + "C217183": "https://hyland.atlassian.net/browse/ACS-8812", + "C280502": "https://hyland.atlassian.net/browse/ACS-8812", + "C217130": "https://hyland.atlassian.net/browse/ACS-8812", + "C217184": "https://hyland.atlassian.net/browse/ACS-8812" } diff --git a/e2e/playwright/edit-actions/exclude.tests.json b/e2e/playwright/edit-actions/exclude.tests.json index 0967ef424..aa475482b 100644 --- a/e2e/playwright/edit-actions/exclude.tests.json +++ b/e2e/playwright/edit-actions/exclude.tests.json @@ -1 +1,3 @@ -{} +{ + "XAT-5095": "https://hyland.atlassian.net/browse/ACS-8812" +} diff --git a/e2e/playwright/navigation/exclude.tests.json b/e2e/playwright/navigation/exclude.tests.json index 0967ef424..0ebca7ffa 100644 --- a/e2e/playwright/navigation/exclude.tests.json +++ b/e2e/playwright/navigation/exclude.tests.json @@ -1 +1,3 @@ -{} +{ + "C280034": "https://hyland.atlassian.net/browse/ACS-8812" +} diff --git a/e2e/playwright/search/exclude.tests.json b/e2e/playwright/search/exclude.tests.json index 031cfa0f6..1f79b2c29 100644 --- a/e2e/playwright/search/exclude.tests.json +++ b/e2e/playwright/search/exclude.tests.json @@ -2,5 +2,6 @@ "C290019": "https://hyland.atlassian.net/browse/ACS-6928", "C290018": "https://hyland.atlassian.net/browse/ACS-6928", "C699046-3": "https://hyland.atlassian.net/browse/ACS-7464", - "C699498": "https://hyland.atlassian.net/browse/ACS-7682" + "C699498": "https://hyland.atlassian.net/browse/ACS-7682", + "C280034": "https://hyland.atlassian.net/browse/ACS-8812" } \ No newline at end of file diff --git a/e2e/playwright/upload-download-actions/exclude.tests.json b/e2e/playwright/upload-download-actions/exclude.tests.json index 9e26dfeeb..1a984fdf0 100644 --- a/e2e/playwright/upload-download-actions/exclude.tests.json +++ b/e2e/playwright/upload-download-actions/exclude.tests.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "C297548": "https://hyland.atlassian.net/browse/ACS-8812" +} diff --git a/projects/aca-content/assets/app.extensions.json b/projects/aca-content/assets/app.extensions.json index ca545b754..258fe3a9a 100644 --- a/projects/aca-content/assets/app.extensions.json +++ b/projects/aca-content/assets/app.extensions.json @@ -128,6 +128,16 @@ } } ], + "icons": [ + { + "id": "adf:three_magic_stars_ai", + "value": "./assets/images/three-magic-stars-ai.svg" + }, + { + "id": "adf:colored-stars-ai", + "value": "./assets/images/colored-stars-ai.svg" + } + ], "create": [ { "id": "app.create.folder", @@ -194,6 +204,9 @@ "order": 100, "title": "APP.BROWSE.FILE.SIDENAV_LINK.LABEL", "description": "APP.BROWSE.FILE.SIDENAV_LINK.TOOLTIP", + "data": { + "canBeInactive": true + }, "children": [ { "id": "app.navbar.personalFiles", @@ -676,6 +689,22 @@ } } ] + }, + { + "id": "app.toolbar.ai.search", + "order": 0, + "title": "KNOWLEDGE_RETRIEVAL.SEARCH.AGENTS_BUTTON.TITLE", + "component": "app.toolbar.ai.agents-button", + "type": "custom", + "rules": { + "visible": "app.selection.displayedKnowledgeRetrievalButton" + }, + "actions": { + "click": "app.action.toggle-ai-search-input.execute" + }, + "data": { + "trigger": "TOGGLE_AI_SEARCH_INPUT" + } } ], "contextMenu": [ diff --git a/projects/aca-content/assets/i18n/en.json b/projects/aca-content/assets/i18n/en.json index 32d109265..2aad6b5a8 100644 --- a/projects/aca-content/assets/i18n/en.json +++ b/projects/aca-content/assets/i18n/en.json @@ -609,5 +609,41 @@ "BOOKS-24PX": "file library", "BASELINE-LOCK-24PX": "locked file" } + }, + "KNOWLEDGE_RETRIEVAL": { + "SEARCH": { + "RESULTS_PAGE": { + "QUERY_INPUT_PLACEHOLDER": "Would you like to ask anything else?", + "REFERENCED_DOCUMENTS_HEADER": "Referenced documents", + "REGENERATION_BUTTON_LABEL": "Regenerate", + "COPY_BUTTON_LABEL": "Copy", + "LIKE_BUTTON_LABEL": "Like", + "DISLIKE_BUTTON_LABEL": "Dislike", + "COPY_MESSAGE": "Copied response to clipboard" + }, + "AGENTS_BUTTON": { + "LABEL": "Ask Discovery", + "TITLE": "Knowledge Retrieval" + }, + "SEARCH_INPUT": { + "ASK_BUTTON_LABEL": "Ask", + "DEFAULT_PLACEHOLDER": "Please ask your question with as much detail as possible...", + "HIDE_INPUT": "Hide input" + }, + "ERRORS": { + "AGENTS_FETCHING": "Error while fetching agents.", + "HX_INSIGHT_URL_FETCHING": "Error while fetching HX Insight URL.", + "LOADING_ERROR": "Hmm... something seems to have gone wrong.", + "PAGE_NOT_AVAILABLE_ERROR": "Page is not available for these conditions." + }, + "DISCARD_CHANGES": { + "WARNING": "Warning!", + "ASK_AI": "Ask AI", + "DO_NOT_SHOW_MESSAGE": "Don't show this message again", + "OKAY": "Okay", + "CONVERSATION_DISCARDED": "This conversation will be discarded", + "LOSE_RESPONSE": "By asking another question you will lose your previous response" + } + } } } diff --git a/projects/aca-content/assets/images/colored-stars-ai.svg b/projects/aca-content/assets/images/colored-stars-ai.svg new file mode 100644 index 000000000..bf397f933 --- /dev/null +++ b/projects/aca-content/assets/images/colored-stars-ai.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/projects/aca-content/assets/images/three-magic-stars-ai.svg b/projects/aca-content/assets/images/three-magic-stars-ai.svg new file mode 100644 index 000000000..992394ec0 --- /dev/null +++ b/projects/aca-content/assets/images/three-magic-stars-ai.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/projects/aca-content/src/lib/aca-content.module.ts b/projects/aca-content/src/lib/aca-content.module.ts index 4182327ba..aa3a121ef 100644 --- a/projects/aca-content/src/lib/aca-content.module.ts +++ b/projects/aca-content/src/lib/aca-content.module.ts @@ -77,6 +77,7 @@ import { ContextMenuComponent } from './components/context-menu/context-menu.com import { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material/dialog'; import { SearchResultsRowComponent } from './components/search/search-results-row/search-results-row.component'; import { BulkActionsDropdownComponent } from './components/bulk-actions-dropdown/bulk-actions-dropdown.component'; +import { AgentsButtonComponent } from './components/knowledge-retrieval/search-ai/agents-button/agents-button.component'; @NgModule({ imports: [ @@ -138,6 +139,7 @@ export class ContentServiceExtensionModule { 'app.toolbar.toggleFavorite': ToggleFavoriteComponent, 'app.toolbar.toggleFavoriteLibrary': ToggleFavoriteLibraryComponent, 'app.toolbar.toggleJoinLibrary': ToggleJoinLibraryButtonComponent, + 'app.toolbar.ai.agents-button': AgentsButtonComponent, 'app.menu.toggleJoinLibrary': ToggleJoinLibraryMenuComponent, 'app.bulk-actions-dropdown': BulkActionsDropdownComponent, 'app.shared-link.toggleSharedLink': ToggleSharedComponent, @@ -197,6 +199,7 @@ export class ContentServiceExtensionModule { 'app.selection.hasNoLibraryRole': rules.hasNoLibraryRole, 'app.selection.folder': rules.hasFolderSelected, 'app.selection.folder.canUpdate': rules.canUpdateSelectedFolder, + 'app.selection.displayedKnowledgeRetrievalButton': rules.canDisplayKnowledgeRetrievalButton, 'app.navigation.folder.canCreate': rules.canCreateFolder, 'app.navigation.folder.canUpload': rules.canUpload, diff --git a/projects/aca-content/src/lib/aca-content.routes.ts b/projects/aca-content/src/lib/aca-content.routes.ts index 85da0484e..99c37c7a4 100644 --- a/projects/aca-content/src/lib/aca-content.routes.ts +++ b/projects/aca-content/src/lib/aca-content.routes.ts @@ -27,8 +27,8 @@ import { LibrariesComponent } from './components/libraries/libraries.component'; import { FavoriteLibrariesComponent } from './components/favorite-libraries/favorite-libraries.component'; import { SearchResultsComponent } from './components/search/search-results/search-results.component'; import { SearchLibrariesResultsComponent } from './components/search/search-libraries-results/search-libraries-results.component'; -import { AppSharedRuleGuard, GenericErrorComponent, ExtensionRoute, ExtensionsDataLoaderGuard } from '@alfresco/aca-shared'; -import { AuthGuard } from '@alfresco/adf-core'; +import { AppSharedRuleGuard, GenericErrorComponent, ExtensionRoute, ExtensionsDataLoaderGuard, PluginEnabledGuard } from '@alfresco/aca-shared'; +import { AuthGuard, UnsavedChangesGuard } from '@alfresco/adf-core'; import { FavoritesComponent } from './components/favorites/favorites.component'; import { RecentFilesComponent } from './components/recent-files/recent-files.component'; import { SharedFilesComponent } from './components/shared-files/shared-files.component'; @@ -36,10 +36,11 @@ import { DetailsComponent } from './components/details/details.component'; import { HomeComponent } from './components/home/home.component'; import { ViewProfileComponent } from './components/view-profile/view-profile.component'; import { ViewProfileRuleGuard } from './components/view-profile/view-profile.guard'; -import { Route } from '@angular/router'; +import { Data, Route, Routes } from '@angular/router'; import { SharedLinkViewComponent } from './components/shared-link-view/shared-link-view.component'; import { TrashcanComponent } from './components/trashcan/trashcan.component'; import { ShellLayoutComponent } from '@alfresco/adf-core/shell'; +import { SearchAiResultsComponent } from './components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component'; export const CONTENT_ROUTES: ExtensionRoute[] = [ { @@ -72,6 +73,36 @@ export const CONTENT_ROUTES: ExtensionRoute[] = [ } ]; +const createViewRoutes = (navigateSource: string, additionalData: Data = {}): Routes => [ + { + path: 'view/:nodeId', + outlet: 'viewer', + children: [ + { + path: '', + data: { + navigateSource + }, + loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) + } + ], + ...additionalData + }, + { + path: 'view/:nodeId/:versionId', + outlet: 'viewer', + children: [ + { + path: '', + data: { + navigateSource + }, + loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) + } + ] + } +]; + export const CONTENT_LAYOUT_ROUTES: Route = { path: '', canActivate: [ExtensionsDataLoaderGuard], @@ -117,32 +148,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { } ] }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'personal-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'personal-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('personal-files') ] }, { @@ -156,32 +162,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { sortingPreferenceKey: 'personal-files' } }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'personal-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'personal-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('personal-files') ] }, { @@ -208,35 +189,11 @@ export const CONTENT_LAYOUT_ROUTES: Route = { sortingPreferenceKey: 'libraries-files' } }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'libraries' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ], + ...createViewRoutes('libraries', { data: { navigateSource: 'libraries' } - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'libraries' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + }) ] }, { @@ -268,32 +225,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { sortingPreferenceKey: 'libraries-files' } }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'libraries' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'libraries' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('libraries') ] }, { @@ -310,32 +242,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { sortingPreferenceKey: 'favorites' } }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'favorites' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'favorites' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('favorites') ] }, { @@ -351,32 +258,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { title: 'APP.BROWSE.RECENT.TITLE' } }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'recent-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'recent-files' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('recent-files') ] }, { @@ -390,32 +272,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { }, component: SharedFilesComponent }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'shared' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'shared' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('shared') ], canActivateChild: [AppSharedRuleGuard], canActivate: [AppSharedRuleGuard] @@ -444,32 +301,7 @@ export const CONTENT_LAYOUT_ROUTES: Route = { sortingPreferenceKey: 'search' } }, - { - path: 'view/:nodeId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'search' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - }, - { - path: 'view/:nodeId/:versionId', - outlet: 'viewer', - children: [ - { - path: '', - data: { - navigateSource: 'search' - }, - loadChildren: () => import('@alfresco/aca-content/viewer').then((m) => m.AcaViewerModule) - } - ] - } + ...createViewRoutes('search') ] }, { @@ -507,6 +339,21 @@ export const CONTENT_LAYOUT_ROUTES: Route = { } ] }, + { + path: 'knowledge-retrieval', + canDeactivate: [UnsavedChangesGuard], + canActivate: [PluginEnabledGuard], + data: { + plugin: 'plugins.knowledgeRetrievalEnabled' + }, + children: [ + { + path: '', + component: SearchAiResultsComponent + }, + ...createViewRoutes('knowledge-retrieval') + ] + }, { path: '**', component: GenericErrorComponent diff --git a/projects/aca-content/src/lib/components/favorites/favorites.component.html b/projects/aca-content/src/lib/components/favorites/favorites.component.html index 9b90dec77..75190109e 100644 --- a/projects/aca-content/src/lib/components/favorites/favorites.component.html +++ b/projects/aca-content/src/lib/components/favorites/favorites.component.html @@ -1,9 +1,17 @@

diff --git a/projects/aca-content/src/lib/components/favorites/favorites.component.ts b/projects/aca-content/src/lib/components/favorites/favorites.component.ts index 16d5495ee..c17a0a771 100644 --- a/projects/aca-content/src/lib/components/favorites/favorites.component.ts +++ b/projects/aca-content/src/lib/components/favorites/favorites.component.ts @@ -46,6 +46,7 @@ import { import { DocumentListDirective } from '../../directives/document-list.directive'; import { TranslateModule } from '@ngx-translate/core'; import { DocumentListComponent } from '@alfresco/adf-content-services'; +import { SearchAiInputContainerComponent } from '../knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; @Component({ standalone: true, @@ -59,6 +60,7 @@ import { DocumentListComponent } from '@alfresco/adf-content-services'; PageLayoutComponent, TranslateModule, ToolbarComponent, + SearchAiInputContainerComponent, EmptyContentComponent, DynamicColumnComponent, DocumentListComponent, @@ -67,7 +69,8 @@ import { DocumentListComponent } from '@alfresco/adf-content-services'; CustomEmptyContentTemplateDirective ], templateUrl: './favorites.component.html', - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, + selector: 'aca-favorites' }) export class FavoritesComponent extends PageComponent implements OnInit { columns: DocumentListPresetRef[] = []; diff --git a/projects/aca-content/src/lib/components/files/files.component.html b/projects/aca-content/src/lib/components/files/files.component.html index 6a63c5d96..35a5d0494 100644 --- a/projects/aca-content/src/lib/components/files/files.component.html +++ b/projects/aca-content/src/lib/components/files/files.component.html @@ -1,12 +1,20 @@
- - - + + + +
+ + + +
+
diff --git a/projects/aca-content/src/lib/components/files/files.component.ts b/projects/aca-content/src/lib/components/files/files.component.ts index 549f9e471..62746a938 100644 --- a/projects/aca-content/src/lib/components/files/files.component.ts +++ b/projects/aca-content/src/lib/components/files/files.component.ts @@ -58,6 +58,7 @@ import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { DocumentListDirective } from '../../directives/document-list.directive'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { SearchAiInputContainerComponent } from '../knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; @Component({ standalone: true, @@ -73,6 +74,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; PaginationDirective, PageLayoutComponent, ToolbarComponent, + SearchAiInputContainerComponent, DynamicColumnComponent, BreadcrumbComponent, UploadDragAreaComponent, @@ -82,7 +84,8 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; CustomEmptyContentTemplateDirective ], templateUrl: './files.component.html', - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, + selector: 'aca-files' }) export class FilesComponent extends PageComponent implements OnInit, OnDestroy { isValidPath = true; diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.html b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.html new file mode 100644 index 000000000..6f3c1a25d --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.html @@ -0,0 +1,37 @@ + + + + + +
+ + + {{ agent.name }} + +
+
+
+
+
diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.scss b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.scss new file mode 100644 index 000000000..f3aa6cc7a --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.scss @@ -0,0 +1,74 @@ +aca-agents-button.aca-agents-button { + height: 32px; + display: block; + + button { + &.aca-agents-menu-button { + display: flex; + align-items: end; + + &.aca-agents-button-menu-trigger { + height: auto; + cursor: pointer; + border: none; + background: transparent; + width: max-content; + padding: 0 4px 0 0; + } + + .aca-agents-button-icon { + display: flex; + align-self: baseline; + + svg { + height: 32px; + width: 32px; + position: absolute; + margin-left: -21px; + } + } + } + } +} + +.aca-agents-button-menu { + padding-top: 2px; + padding-bottom: 1px; + + .aca-agents-button-menu-list { + margin-left: -6px; + padding-top: 0; + padding-bottom: 0; + + &-agent { + height: 40px; + + &:not(:last-child) { + margin-bottom: 2px; + } + + &-content { + display: flex; + align-items: center; + + &-name { + width: 120px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + adf-avatar { + margin-right: 12px; + margin-bottom: 2px; + padding-left: 1px; + padding-top: 1px; + + .adf-avatar__image { + cursor: pointer; + } + } + } + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.spec.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.spec.ts new file mode 100644 index 000000000..49b670140 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.spec.ts @@ -0,0 +1,461 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AgentsButtonComponent } from './agents-button.component'; +import { AgentService, ContentTestingModule, SearchAiService } from '@alfresco/adf-content-services'; +import { Subject } from 'rxjs'; +import { By } from '@angular/platform-browser'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { getAppSelection, SearchAiActionTypes, ToggleAISearchInput } from '@alfresco/aca-shared/store'; +import { AvatarComponent, NotificationService } from '@alfresco/adf-core'; +import { SelectionState } from '@alfresco/adf-extensions'; +import { MatMenu, MatMenuPanel, MatMenuTrigger } from '@angular/material/menu'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatSelectionListHarness } from '@angular/material/list/testing'; +import { MatMenuHarness } from '@angular/material/menu/testing'; +import { MatSelectionList } from '@angular/material/list'; +import { MatSnackBarRef } from '@angular/material/snack-bar'; +import { ChangeDetectorRef } from '@angular/core'; +import { Agent, KnowledgeRetrievalConfigEntry } from '@alfresco/js-api'; + +describe('AgentsButtonComponent', () => { + let component: AgentsButtonComponent; + let fixture: ComponentFixture; + let agents$: Subject; + let agentsMock: Agent[]; + let checkSearchAvailabilitySpy: jasmine.Spy<(selectedNodesState: SelectionState, maxSelectedNodes?: number) => string>; + let selectionState: SelectionState; + let store: MockStore; + let config$: Subject; + + const knowledgeRetrievalUrl = 'some url'; + + const getMenu = (): MatMenu => fixture.debugElement.query(By.directive(MatMenu)).componentInstance; + + const getAgentsButton = (): HTMLButtonElement => fixture.debugElement.query(By.css('.aca-agents-menu-button'))?.nativeElement; + + const runButtonActions = (eventName: string): void => { + let event: Event; + let notificationService: NotificationService; + let message: string; + + beforeEach(() => { + config$.next({ + entry: { + knowledgeRetrievalUrl + } + }); + config$.complete(); + event = + eventName === 'mouseup' + ? new MouseEvent(eventName) + : new KeyboardEvent(eventName, { + key: 'Enter' + }); + agents$.next(agentsMock); + agents$.complete(); + spyOn(window, 'open'); + notificationService = TestBed.inject(NotificationService); + spyOn(notificationService, 'showError'); + message = 'Some message'; + component.avatarsMocked = false; + }); + + const getMenuTrigger = (): MatMenuPanel => fixture.debugElement.query(By.directive(MatMenuTrigger)).injector.get(MatMenuTrigger).menu; + + const testButtonActions = (): void => { + it('should not display notification if checkSearchAvailability from SearchAiService returns empty message', () => { + message = ''; + checkSearchAvailabilitySpy.and.returnValue(message); + + getAgentsButton().dispatchEvent(event); + expect(notificationService.showError).not.toHaveBeenCalled(); + }); + + it('should disable menu triggering if checkSearchAvailability from SearchAiService returns message', () => { + checkSearchAvailabilitySpy.and.returnValue('Some message'); + + getAgentsButton().dispatchEvent(event); + fixture.detectChanges(); + expect(getMenuTrigger()).toBeNull(); + }); + }; + + describe('with selected nodes', () => { + beforeEach(() => { + selectionState.isEmpty = false; + }); + + it('should display notification if checkSearchAvailability from SearchAiService returns message', () => { + checkSearchAvailabilitySpy.and.returnValue(message); + + getAgentsButton().dispatchEvent(event); + expect(notificationService.showError).toHaveBeenCalledWith(message); + }); + + testButtonActions(); + + it('should enable menu triggering if checkSearchAvailability from SearchAiService returns empty message', () => { + checkSearchAvailabilitySpy.and.returnValue(''); + + getAgentsButton().dispatchEvent(event); + fixture.detectChanges(); + const menuTrigger = getMenuTrigger(); + expect(menuTrigger).toBeTruthy(); + expect(menuTrigger).toBe(getMenu()); + }); + + it('should call checkSearchAvailability from SearchAiService with correct parameter', () => { + getAgentsButton().dispatchEvent(event); + + expect(checkSearchAvailabilitySpy).toHaveBeenCalledWith(selectionState); + }); + + it('should not open new tab for url loaded from config', () => { + getAgentsButton().dispatchEvent(event); + + expect(window.open).not.toHaveBeenCalled(); + }); + }); + + describe('without selected nodes', () => { + it('should not display notification if checkSearchAvailability from SearchAiService returns message', () => { + checkSearchAvailabilitySpy.and.returnValue(message); + + getAgentsButton().dispatchEvent(event); + expect(notificationService.showError).not.toHaveBeenCalled(); + }); + + testButtonActions(); + + it('should disable menu triggering if checkSearchAvailability from SearchAiService returns empty message', () => { + checkSearchAvailabilitySpy.and.returnValue(''); + + getAgentsButton().dispatchEvent(event); + fixture.detectChanges(); + expect(getMenuTrigger()).toBeNull(); + }); + + it('should not call checkSearchAvailability from SearchAiService', () => { + getAgentsButton().dispatchEvent(event); + + expect(checkSearchAvailabilitySpy).not.toHaveBeenCalled(); + }); + + it('should open new tab for url loaded from config', () => { + getAgentsButton().dispatchEvent(event); + + expect(window.open).toHaveBeenCalledWith(knowledgeRetrievalUrl); + }); + }); + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AgentsButtonComponent, ContentTestingModule], + providers: [provideMockStore({})] + }); + + fixture = TestBed.createComponent(AgentsButtonComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + agents$ = new Subject(); + spyOn(TestBed.inject(AgentService), 'getAgents').and.returnValue(agents$); + agentsMock = [ + { + id: '1', + name: 'HR Agent', + description: 'Test 1', + avatarUrl: undefined + }, + { + id: '2', + name: 'Policy Agent', + description: 'Test 2', + avatarUrl: undefined + } + ]; + const searchAiService = TestBed.inject(SearchAiService); + checkSearchAvailabilitySpy = spyOn(searchAiService, 'checkSearchAvailability'); + config$ = new Subject(); + spyOn(searchAiService, 'getConfig').and.returnValue(config$); + selectionState = { + nodes: [], + isEmpty: true, + count: 0, + libraries: [] + }; + store.overrideSelector(getAppSelection, selectionState); + fixture.detectChanges(); + }); + + afterEach(() => { + store.resetSelectors(); + }); + + describe('Button', () => { + let notificationServiceSpy: jasmine.Spy<(message: string) => MatSnackBarRef>; + + beforeEach(() => { + const notificationService = TestBed.inject(NotificationService); + notificationServiceSpy = spyOn(notificationService, 'showError').and.callThrough(); + }); + + describe('loaded config', () => { + beforeEach(() => { + component.avatarsMocked = false; + config$.next({ + entry: { + knowledgeRetrievalUrl + } + }); + config$.complete(); + }); + + it('should be rendered if any agentsMock are loaded', () => { + agents$.next(agentsMock); + agents$.complete(); + fixture.detectChanges(); + + expect(getAgentsButton()).toBeTruthy(); + }); + + it('should get agentsMock on component init', () => { + agents$.next(agentsMock); + agents$.complete(); + component.ngOnInit(); + + expect(component.initialsByAgentId).toEqual({ 1: 'HA', 2: 'PA' }); + expect(component.agents).toEqual(agentsMock); + expect(notificationServiceSpy).not.toHaveBeenCalled(); + }); + + it('should run detectChanges when getting the agentsMock', () => { + const changeDetectorRef2 = fixture.debugElement.injector.get(ChangeDetectorRef); + const detectChangesSpy = spyOn(changeDetectorRef2.constructor.prototype, 'detectChanges'); + + component.ngOnInit(); + agents$.next(agentsMock); + + expect(detectChangesSpy).toHaveBeenCalled(); + }); + + it('should show notification error on getAgents error', () => { + agents$.error('error'); + component.ngOnInit(); + + expect(component.agents).toEqual([]); + expect(component.initialsByAgentId).toEqual({}); + expect(notificationServiceSpy).toHaveBeenCalledWith('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.AGENTS_FETCHING'); + }); + + it('should not be rendered if none agent is loaded', () => { + agentsMock = []; + agents$.next(agentsMock); + agents$.complete(); + + fixture.detectChanges(); + expect(getAgentsButton()).toBeFalsy(); + }); + + it('should have correct label', () => { + agents$.next(agentsMock); + agents$.complete(); + fixture.detectChanges(); + + expect(getAgentsButton().textContent.trim()).toBe('KNOWLEDGE_RETRIEVAL.SEARCH.AGENTS_BUTTON.LABEL'); + }); + + it('should contain stars icon', () => { + agents$.next(agentsMock); + agents$.complete(); + fixture.detectChanges(); + + expect(fixture.debugElement.query(By.css('.aca-agents-menu-button adf-icon')).componentInstance.value).toBe('adf:colored-stars-ai'); + }); + }); + + describe('loaded config with error', () => { + beforeEach(() => { + config$.error('error'); + config$.complete(); + }); + + it('should not be rendered', () => { + agents$.next(agentsMock); + agents$.complete(); + fixture.detectChanges(); + + expect(getAgentsButton()).toBeFalsy(); + }); + + it('should show notification error', () => { + agents$.next(agentsMock); + agents$.complete(); + component.ngOnInit(); + + expect(component.hxInsightUrl).toBeUndefined(); + expect(notificationServiceSpy).toHaveBeenCalledWith('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.HX_INSIGHT_URL_FETCHING'); + }); + }); + }); + + const buttonKeyboardActions = (eventName: string): void => { + describe(`Button action - ${eventName} event`, () => { + runButtonActions(eventName); + }); + }; + + ['mouseup', 'keydown'].forEach((eventName) => { + buttonKeyboardActions(eventName); + }); + + describe('Agents menu', () => { + let loader: HarnessLoader; + + const prepareData = (agents: Agent[]): void => { + component.avatarsMocked = false; + config$.next({ + entry: { + knowledgeRetrievalUrl + } + }); + config$.complete(); + loader = TestbedHarnessEnvironment.loader(fixture); + agents$.next(agents); + selectionState.isEmpty = false; + checkSearchAvailabilitySpy.and.returnValue(''); + const button = getAgentsButton(); + button.dispatchEvent(new MouseEvent('mouseup')); + fixture.detectChanges(); + button.click(); + fixture.detectChanges(); + }; + + const getAvatar = (agentId: string): AvatarComponent => + fixture.debugElement.query(By.css(`[data-automation-id=aca-agents-button-agent-${agentId}]`)).query(By.directive(AvatarComponent)) + .componentInstance; + + describe('Agents position', () => { + it('should have assigned before to xPosition', () => { + prepareData(agentsMock); + agents$.complete(); + expect(getMenu().xPosition).toBe('before'); + }); + }); + + describe('Agents multi words name', () => { + beforeEach(() => { + prepareData(agentsMock); + agents$.complete(); + }); + + const getAgentsListHarness = async (): Promise => + (await loader.getHarness(MatMenuHarness)).getHarness(MatSelectionListHarness); + + const selectAgent = async (): Promise => + (await getAgentsListHarness()).selectItems({ + fullText: 'PA Policy Agent' + }); + + const getAgentsList = (): MatSelectionList => fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance; + + it('should deselect selected agent after selecting other', async () => { + component.data = { + trigger: SearchAiActionTypes.ToggleAiSearchInput + }; + const selectionList = getAgentsList(); + spyOn(selectionList, 'deselectAll'); + await selectAgent(); + + expect(selectionList.deselectAll).toHaveBeenCalled(); + }); + + it('should dispatch on store selected agent', async () => { + component.data = { + trigger: SearchAiActionTypes.ToggleAiSearchInput + }; + spyOn(store, 'dispatch'); + await selectAgent(); + + expect(store.dispatch).toHaveBeenCalledWith({ + type: SearchAiActionTypes.ToggleAiSearchInput, + agentId: '2' + }); + }); + + it('should disallow selecting multiple agentsMock', () => { + expect(getAgentsList().multiple).toBeFalse(); + }); + + it('should have hidden single selection indicator', () => { + expect(getAgentsList().hideSingleSelectionIndicator).toBeTrue(); + }); + + it('should display option for each agent', async () => { + const agents = await (await getAgentsListHarness()).getItems(); + expect(agents.length).toBe(2); + expect(await agents[0].getFullText()).toBe('HA HR Agent'); + expect(await agents[1].getFullText()).toBe('PA Policy Agent'); + }); + + it('should display avatar for each agent', () => { + expect(getAvatar('1')).toBeTruthy(); + expect(getAvatar('2')).toBeTruthy(); + }); + + it('should assign correct initials to each avatar for each agent with double section name', () => { + expect(getAvatar('1').initials).toBe('HA'); + expect(getAvatar('2').initials).toBe('PA'); + }); + }); + + describe('Agents multi words name', () => { + it('should assign correct initials to each avatar for each agent with single section name', () => { + agentsMock = [ + { + id: '1', + name: 'HR Agent', + description: 'Test 1', + avatarUrl: undefined + }, + { + id: '2', + name: 'Policy Agent', + description: 'Test 2', + avatarUrl: undefined + } + ]; + agentsMock[0].name = 'Adam'; + agentsMock[1].name = 'Bob'; + prepareData(agentsMock); + + expect(getAvatar('1').initials).toBe('A'); + expect(getAvatar('2').initials).toBe('B'); + }); + }); + }); +}); diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.ts new file mode 100644 index 000000000..4d36d8a04 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/agents-button/agents-button.component.ts @@ -0,0 +1,148 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SelectionState } from '@alfresco/adf-extensions'; +import { Store } from '@ngrx/store'; +import { AppStore, getAppSelection } from '@alfresco/aca-shared/store'; +import { AvatarComponent, IconComponent, NotificationService } from '@alfresco/adf-core'; +import { forkJoin, Subject, throwError } from 'rxjs'; +import { catchError, take, takeUntil } from 'rxjs/operators'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatListModule, MatSelectionListChange } from '@angular/material/list'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { Agent } from '@alfresco/js-api'; +import { AgentService, SearchAiService } from '@alfresco/adf-content-services'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { getAgentsWithMockedAvatars } from '../search-ai-utils'; + +@Component({ + standalone: true, + imports: [CommonModule, MatMenuModule, MatListModule, TranslateModule, AvatarComponent, IconComponent, MatTooltipModule], + selector: 'aca-agents-button', + templateUrl: './agents-button.component.html', + styleUrls: ['./agents-button.component.scss'], + encapsulation: ViewEncapsulation.None, + host: { class: 'aca-agents-button' } +}) +export class AgentsButtonComponent implements OnInit, OnDestroy { + @Input() + data: { trigger: string }; + + private selectedNodesState: SelectionState; + private _agents: Agent[] = []; + private onDestroy$ = new Subject(); + private _disabled = true; + private _initialsByAgentId: { [key: string]: string } = {}; + private _hxInsightUrl: string; + + avatarsMocked = true; + + get agents(): Agent[] { + return this._agents; + } + + get disabled(): boolean { + return this._disabled; + } + + get initialsByAgentId(): { [key: string]: string } { + return this._initialsByAgentId; + } + + get hxInsightUrl(): string { + return this._hxInsightUrl; + } + + constructor( + private store: Store, + private notificationService: NotificationService, + private searchAiService: SearchAiService, + private agentService: AgentService, + private translateService: TranslateService, + private cd: ChangeDetectorRef + ) {} + + ngOnInit(): void { + this.store + .select(getAppSelection) + .pipe(takeUntil(this.onDestroy$)) + .subscribe((selection) => { + this.selectedNodesState = selection; + }); + forkJoin({ + agents: this.agentService.getAgents().pipe( + take(1), + catchError(() => throwError('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.AGENTS_FETCHING')) + ), + config: this.searchAiService.getConfig().pipe(catchError(() => throwError('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.HX_INSIGHT_URL_FETCHING'))) + }).subscribe( + (result) => { + this._hxInsightUrl = result.config.entry.knowledgeRetrievalUrl; + this._agents = result.agents; + + // TODO remove mocked avatar images after backend is done (https://hyland.atlassian.net/browse/ACS-8769) + this._agents = getAgentsWithMockedAvatars(result.agents, this.avatarsMocked); + + this.cd.detectChanges(); + + if (this.agents.length) { + this._initialsByAgentId = this.agents.reduce((initials, agent) => { + const words = agent.name.split(' ').filter((word) => !word.match(/[^a-zA-Z]+/g)); + initials[agent.id] = `${words[0][0]}${words[1]?.[0] || ''}`; + return initials; + }, {}); + } + }, + (error: string) => this.notificationService.showError(this.translateService.instant(error)) + ); + } + + ngOnDestroy(): void { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } + + onClick(): void { + if (!this.selectedNodesState.isEmpty) { + const message = this.searchAiService.checkSearchAvailability(this.selectedNodesState); + if (message) { + this.notificationService.showError(message); + } + this._disabled = !!message; + return; + } + this._disabled = true; + open(this.hxInsightUrl); + } + + onAgentSelection(change: MatSelectionListChange): void { + this.store.dispatch({ + type: this.data.trigger, + agentId: change.options[0].value.id + }); + change.source.deselectAll(); + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.html b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.html new file mode 100644 index 000000000..526f6ab3c --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.html @@ -0,0 +1,18 @@ + + + + + diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.scss b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.scss new file mode 100644 index 000000000..6fd639575 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.scss @@ -0,0 +1,18 @@ +aca-search-ai-input-container { + display: flex; + flex-direction: row; + flex: 1; + align-items: center; + width: 100%; + + .aca-search-ai-input-container-divider { + height: 24px; + margin-left: 30px; + margin-right: 7px; + background: var(--adf-theme-foreground-text-color-025); + } + + .aca-search-ai-input-container-close { + display: flex; + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.spec.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.spec.ts new file mode 100644 index 000000000..e09f40770 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.spec.ts @@ -0,0 +1,186 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { SearchAiInputContainerComponent } from './search-ai-input-container.component'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { SearchAiInputComponent } from '../search-ai-input/search-ai-input.component'; +import { By } from '@angular/platform-browser'; +import { AgentService, ContentTestingModule, SearchAiService } from '@alfresco/adf-content-services'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { of, Subject } from 'rxjs'; +import { MatDivider } from '@angular/material/divider'; +import { DebugElement } from '@angular/core'; +import { MatIconButton } from '@angular/material/button'; +import { MatIcon } from '@angular/material/icon'; +import { SearchAiNavigationService } from '../../../../services/search-ai-navigation.service'; +import { NavigationEnd, NavigationStart, Router, RouterEvent } from '@angular/router'; +import { getAppSelection } from '@alfresco/aca-shared/store'; + +describe('SearchAiInputContainerComponent', () => { + let component: SearchAiInputContainerComponent; + let fixture: ComponentFixture; + let routingEvents$: Subject; + let searchAiService: SearchAiService; + let store: MockStore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [SearchAiInputContainerComponent, ContentTestingModule], + providers: [ + provideMockStore(), + { + provide: AgentService, + useValue: { + getAgents: () => + of([ + { + id: '1', + name: 'HR Agent', + description: 'HR Agent', + avatar: 'avatar1' + } + ]) + } + } + ] + }); + + fixture = TestBed.createComponent(SearchAiInputContainerComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + searchAiService = TestBed.inject(SearchAiService); + store.overrideSelector(getAppSelection, { + nodes: [], + isEmpty: true, + count: 0, + libraries: [] + }); + component.agentId = '1'; + routingEvents$ = new Subject(); + spyOnProperty(TestBed.inject(Router), 'events').and.returnValue(routingEvents$); + fixture.detectChanges(); + }); + + afterEach(() => { + store.resetSelectors(); + }); + + describe('Search ai input', () => { + let inputComponent: SearchAiInputComponent; + + beforeEach(() => { + inputComponent = fixture.debugElement.query(By.directive(SearchAiInputComponent)).componentInstance; + }); + + it('should have assigned correct default placeholder', () => { + expect(inputComponent.placeholder).toBe('KNOWLEDGE_RETRIEVAL.SEARCH.SEARCH_INPUT.DEFAULT_PLACEHOLDER'); + }); + + it('should have assigned correct placeholder if placeholder has been changed', () => { + component.placeholder = 'Some placeholder'; + fixture.detectChanges(); + + expect(inputComponent.placeholder).toBe(component.placeholder); + }); + + it('should have assigned correct agentId', () => { + expect(inputComponent.agentId).toBe(component.agentId); + }); + + it('should have assigned correct useStoredNodes flag', () => { + component.useStoredNodes = true; + fixture.detectChanges(); + + expect(inputComponent.useStoredNodes).toBeTrue(); + }); + + it('should call updateSearchAiInputState on SearchAiService when triggered searchSubmitted event', () => { + spyOn(searchAiService, 'updateSearchAiInputState'); + inputComponent.searchSubmitted.emit(); + + expect(searchAiService.updateSearchAiInputState).toHaveBeenCalledWith({ + active: false + }); + }); + }); + + describe('Divider', () => { + it('should have a vertical divider', () => { + fixture.detectChanges(); + + expect(fixture.debugElement.query(By.directive(MatDivider)).componentInstance.vertical).toBeTrue(); + }); + }); + + describe('Leaving button', () => { + let button: DebugElement; + + beforeEach(() => { + button = fixture.debugElement.query(By.directive(MatIconButton)); + }); + + it('should have correct title', () => { + expect(button.nativeElement.title).toBe('KNOWLEDGE_RETRIEVAL.SEARCH.SEARCH_INPUT.HIDE_INPUT'); + }); + + it('should contain close icon', () => { + expect(button.query(By.directive(MatIcon)).nativeElement.textContent).toBe('close'); + }); + + it('should call updateSearchAiInputState on SearchAiService when clicked', () => { + spyOn(searchAiService, 'updateSearchAiInputState'); + button.nativeElement.click(); + + expect(searchAiService.updateSearchAiInputState).toHaveBeenCalledWith({ + active: false + }); + }); + + it('should call navigateToPreviousRoute on SearchAiNavigationService when clicked', () => { + const searchNavigationService = TestBed.inject(SearchAiNavigationService); + spyOn(searchNavigationService, 'navigateToPreviousRoute'); + button.nativeElement.click(); + + expect(searchNavigationService.navigateToPreviousRoute).toHaveBeenCalled(); + }); + }); + + describe('Navigation', () => { + it('should call updateSearchAiInputState on SearchAiService when navigation starts', () => { + spyOn(searchAiService, 'updateSearchAiInputState'); + routingEvents$.next(new NavigationStart(1, '')); + + expect(searchAiService.updateSearchAiInputState).toHaveBeenCalledWith({ + active: false + }); + }); + + it('should not call updateSearchAiInputState on SearchAiService when there is different event than navigation starts', () => { + spyOn(searchAiService, 'updateSearchAiInputState'); + routingEvents$.next(new NavigationEnd(1, '', '')); + + expect(searchAiService.updateSearchAiInputState).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.ts new file mode 100644 index 000000000..af5fa2a16 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component.ts @@ -0,0 +1,81 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { SearchAiInputComponent } from '../search-ai-input/search-ai-input.component'; +import { MatDividerModule } from '@angular/material/divider'; +import { SearchAiNavigationService } from '../../../../services/search-ai-navigation.service'; +import { NavigationStart, Router } from '@angular/router'; +import { filter, takeUntil } from 'rxjs/operators'; +import { SearchAiService } from '@alfresco/adf-content-services'; +import { TranslateModule } from '@ngx-translate/core'; +import { Subject } from 'rxjs'; + +@Component({ + standalone: true, + imports: [SearchAiInputComponent, MatIconModule, MatDividerModule, MatButtonModule, TranslateModule], + selector: 'aca-search-ai-input-container', + templateUrl: './search-ai-input-container.component.html', + styleUrls: ['./search-ai-input-container.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class SearchAiInputContainerComponent implements OnInit, OnDestroy { + @Input() + placeholder = 'KNOWLEDGE_RETRIEVAL.SEARCH.SEARCH_INPUT.DEFAULT_PLACEHOLDER'; + @Input() + agentId: string; + @Input() + useStoredNodes: boolean; + + private onDestroy$ = new Subject(); + + constructor(private searchAiService: SearchAiService, private searchNavigationService: SearchAiNavigationService, private router: Router) {} + + ngOnInit(): void { + this.router.events + .pipe( + filter((event) => event instanceof NavigationStart), + takeUntil(this.onDestroy$) + ) + .subscribe(() => this.hideSearchInput()); + } + + ngOnDestroy(): void { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } + + hideSearchInput(): void { + this.searchAiService.updateSearchAiInputState({ + active: false + }); + } + + leaveSearchInput(): void { + this.searchNavigationService.navigateToPreviousRoute(); + this.hideSearchInput(); + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.html b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.html new file mode 100644 index 000000000..b0c5a0163 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.html @@ -0,0 +1,63 @@ +
+ + + + + {{ agentControl.value?.name }} + +
+ + {{ agent.name }} +
+
+
+ +
+ + + + + + {{ agentControl.value?.name }} + + + + {{ agentControl.value?.description }} + + +
+
+ + diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.scss b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.scss new file mode 100644 index 000000000..0e464ac42 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.scss @@ -0,0 +1,183 @@ +@import '@alfresco/adf-core/lib/styles/mat-selectors'; + +aca-search-ai-input { + width: 100%; + display: flex; + align-items: center; + + .aca-search-ai-input-text { + margin-top: 4px; + flex: 1; + font-size: 20px; + margin-right: 167px; + border: none; + outline: none; + + &:focus { + &::placeholder { + color: var(--theme-primary-color); + } + } + } + + .aca-search-ai-asking-button { + display: flex; + align-items: center; + padding-left: 0; + padding-right: 12px; + height: 32px; + border-radius: 6px; + width: 92px; + font-weight: 600; + + &-label { + vertical-align: super; + } + + adf-icon { + margin-bottom: 3px; + margin-right: 7px; + + svg { + width: 34px; + height: 34px; + margin-left: -6px; + margin-top: -4px; + } + } + } + + .aca-search-ai-input-agent-select { + width: 149px; + height: 35px; + align-content: center; + border-radius: 16px; + padding-left: 3px; + padding-right: 10px; + background-color: var(--theme-grey-text-background-color); + color: var(--theme-text-light-color); + font-size: 15px; + margin-right: 26px; + + #{$mat-select-trigger} { + height: auto; + margin-top: 4px; + } + + &:focus { + outline: -webkit-focus-ring-color auto 1px; + } + + &-displayed-value { + display: flex; + align-items: center; + + &-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + adf-avatar { + margin-left: 2px; + margin-right: 6px; + padding-top: 1px; + padding-bottom: 3px; + + .adf-avatar__image { + cursor: pointer; + } + } + } +} + +.aca-search-ai-input-agent-select-options.aca-search-ai-input-agent-select-agents#{$mat-select-panel} { + margin-top: 9px; + + .aca-search-ai-input-agent-select-options-option { + padding-left: 11px; + padding-right: 11px; + + &-content { + display: flex; + align-items: center; + padding-top: 1px; + padding-bottom: 1px; + + &-text { + width: 120px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + adf-avatar { + margin-right: 12px; + padding-left: 1px; + + .adf-avatar__image { + cursor: pointer; + } + } + } +} + +.aca-search-ai-input-agent-container { + position: relative; + + .aca-search-ai-input-agent-popup-hover-card { + display: none; + position: absolute; + left: 0; + z-index: 1; + + &-container { + width: 315px; + height: fit-content; + border-radius: 12px; + margin-top: 4px; + + &-title { + display: flex; + align-items: center; + font-size: 20px; + font-weight: 700; + padding: 16px 16px 8px; + gap: 4px; + + &-name { + margin: 0 12px; + } + + img { + height: 50px; + width: 50px; + min-width: 50px; + min-height: 50px; + } + + span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin-right: 14px; + } + } + + &-content { + display: flex; + color: var(--theme-content-color); + text-align: justify; + text-justify: inter-word; + } + } + } + + &:hover { + .aca-search-ai-input-agent-popup-hover-card { + display: block; + } + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.spec.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.spec.ts new file mode 100644 index 000000000..7434043a7 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.spec.ts @@ -0,0 +1,431 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { SearchAiInputComponent } from './search-ai-input.component'; +import { MatSelect, MatSelectModule } from '@angular/material/select'; +import { By } from '@angular/platform-browser'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { AgentService, ContentTestingModule, SearchAiService } from '@alfresco/adf-content-services'; +import { getAppSelection, SearchByTermAiAction } from '@alfresco/aca-shared/store'; +import { of, Subject } from 'rxjs'; +import { Agent, NodeEntry } from '@alfresco/js-api'; +import { FormControlDirective } from '@angular/forms'; +import { DebugElement } from '@angular/core'; +import { AvatarComponent, IconComponent, NotificationService, UnsavedChangesDialogComponent, UserPreferencesService } from '@alfresco/adf-core'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatSelectHarness } from '@angular/material/select/testing'; +import { MatOptionHarness } from '@angular/material/core/testing'; +import { MatInput } from '@angular/material/input'; +import { MatButton } from '@angular/material/button'; +import { MatInputHarness } from '@angular/material/input/testing'; +import { SelectionState } from '@alfresco/adf-extensions'; +import { MatSnackBarRef } from '@angular/material/snack-bar'; +import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog'; +import { ActivatedRoute } from '@angular/router'; +import { ModalAiService } from '../../../../services/modal-ai.service'; + +const agentList: Agent[] = [ + { + id: '1', + name: 'HR Agent', + description: 'Test 1', + avatarUrl: undefined + }, + { + id: '2', + name: 'Policy Agent', + description: 'Test 2', + avatarUrl: undefined + } +]; + +describe('SearchAiInputComponent', () => { + let component: SearchAiInputComponent; + let fixture: ComponentFixture; + let loader: HarnessLoader; + let selectionState: SelectionState; + let store: MockStore; + let agents$: Subject; + let dialog: MatDialog; + + const prepareBeforeTest = (): void => { + selectionState = { + nodes: [], + isEmpty: true, + count: 0, + libraries: [] + }; + store.overrideSelector(getAppSelection, selectionState); + component.agentId = '2'; + component.avatarsMocked = false; + component.ngOnInit(); + fixture.detectChanges(); + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [SearchAiInputComponent, ContentTestingModule, MatSelectModule], + providers: [ + provideMockStore(), + { + provide: ActivatedRoute, + useValue: { + snapshot: { + queryParams: { query: 'some query' } + } + } + } + ] + }); + + fixture = TestBed.createComponent(SearchAiInputComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + loader = TestbedHarnessEnvironment.loader(fixture); + agents$ = new Subject(); + dialog = TestBed.inject(MatDialog); + spyOn(TestBed.inject(AgentService), 'getAgents').and.returnValue(agents$); + prepareBeforeTest(); + }); + + afterEach(() => { + store.resetSelectors(); + }); + + describe('Agent select box', () => { + let selectElement: DebugElement; + let notificationServiceSpy: jasmine.Spy<(message: string) => MatSnackBarRef>; + + beforeEach(() => { + selectElement = fixture.debugElement.query(By.directive(MatSelect)); + const notificationService = TestBed.inject(NotificationService); + notificationServiceSpy = spyOn(notificationService, 'showError').and.callThrough(); + }); + + it('should have assigned formControl', () => { + expect(selectElement.injector.get(FormControlDirective).form).toBe(component.agentControl); + }); + + it('should have hidden single selection indicator', () => { + expect(selectElement.componentInstance.hideSingleSelectionIndicator).toBeTrue(); + }); + + it('should get agents on init', () => { + agents$.next(agentList); + component.ngOnInit(); + expect(component.agents).toEqual(agentList); + expect(component.initialsByAgentId).toEqual({ 1: 'HA', 2: 'PA' }); + expect(notificationServiceSpy).not.toHaveBeenCalled(); + }); + + it('should show notification on getAgents error', () => { + agents$.error('error'); + component.ngOnInit(); + + expect(component.agents).toEqual([]); + expect(component.initialsByAgentId).toEqual({}); + expect(notificationServiceSpy).toHaveBeenCalledWith('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.AGENTS_FETCHING'); + }); + + it('should have selected correct agent', async () => { + agents$.next(agentList); + expect(await (await loader.getHarness(MatSelectHarness)).getValueText()).toBe('PAPolicy Agent'); + const avatar = selectElement.query(By.directive(AvatarComponent))?.componentInstance; + expect(avatar.initials).toBe('PA'); + expect(avatar.size).toBe('26px'); + }); + + describe('Agents options', () => { + let options: MatOptionHarness[]; + + const getAvatarForAgent = (agentId: string): AvatarComponent => + fixture.debugElement.query(By.css(`[data-automation-id=aca-search-ai-input-agent-${agentId}]`)).query(By.directive(AvatarComponent)) + .componentInstance; + + beforeEach(async () => { + agents$.next(agentList); + const selectHarness = await loader.getHarness(MatSelectHarness); + await selectHarness.open(); + options = await selectHarness.getOptions(); + }); + + it('should have correct number of agents', () => { + expect(options.length).toBe(2); + }); + + it('should have correct agent names', async () => { + expect(await options[0].getText()).toBe('HAHR Agent'); + expect(await options[1].getText()).toBe('PAPolicy Agent'); + }); + + it('should display avatar for each agent', () => { + expect(getAvatarForAgent('1')).toBeTruthy(); + expect(getAvatarForAgent('2')).toBeTruthy(); + }); + + it('should have correct initials for avatars for each of agent', () => { + expect(getAvatarForAgent('1').initials).toBe('HA'); + expect(getAvatarForAgent('2').initials).toBe('PA'); + }); + + it('should assign correct initials to each avatar for each agent with single section name', () => { + const newAgentList = [ + { ...agentList[0], name: 'Adam' }, + { ...agentList[1], name: 'Bob' } + ]; + agents$.next(newAgentList); + fixture.detectChanges(); + + expect(getAvatarForAgent('1').initials).toBe('A'); + expect(getAvatarForAgent('2').initials).toBe('B'); + }); + }); + }); + + describe('Query input', () => { + let queryInput: DebugElement; + + beforeEach(() => { + queryInput = fixture.debugElement.query(By.directive(MatInput)); + agents$.next(agentList); + }); + + it('should have assigned formControl', () => { + fixture.detectChanges(); + + expect(queryInput.injector.get(FormControlDirective).form).toBe(component.queryControl); + }); + + it('should have assigned correct placeholder', () => { + component.placeholder = 'Please ask your question with as much detail as possible...'; + + expect(queryInput.componentInstance.placeholder).toBe(component.placeholder); + }); + + testSubmitting(false); + }); + + describe('Submit button', () => { + let submitButton: DebugElement; + let queryInput: MatInputHarness; + + beforeEach(async () => { + submitButton = fixture.debugElement.query(By.directive(MatButton)); + queryInput = await loader.getHarness(MatInputHarness); + agents$.next(agentList); + }); + + it('should be disabled by default', () => { + expect(submitButton.nativeElement.disabled).toBeTrue(); + }); + + it('should be enabled if query input is filled', async () => { + await queryInput.setValue('Some question'); + + expect(submitButton.nativeElement.disabled).toBeFalse(); + }); + + it('should be disabled if query input was filled but after that it was emptied', async () => { + await queryInput.setValue('Some question'); + await queryInput.setValue(''); + + expect(submitButton.nativeElement.disabled).toBeTrue(); + }); + + it('should contain stars icon', () => { + expect(submitButton.query(By.directive(IconComponent)).componentInstance.value).toBe('adf:three_magic_stars_ai'); + }); + + it('should have correct label', () => { + expect(submitButton.nativeElement.textContent.trim()).toBe('KNOWLEDGE_RETRIEVAL.SEARCH.SEARCH_INPUT.ASK_BUTTON_LABEL'); + }); + + testSubmitting(); + }); + + function testSubmitting(useButton = true) { + describe('Submitting', () => { + let checkSearchAvailabilitySpy: jasmine.Spy<(selectedNodesState: SelectionState, maxSelectedNodes?: number) => string>; + let notificationService: NotificationService; + let userPreferencesService: UserPreferencesService; + let submitButton: DebugElement; + let queryInput: MatInputHarness; + let submittingTrigger: () => void; + const query = 'some query'; + let dialogOpenSpy: jasmine.Spy<(component: typeof UnsavedChangesDialogComponent, config?: MatDialogConfig) => MatDialogRef>; + let modalAiService: ModalAiService; + + beforeEach(async () => { + prepareBeforeTest(); + + modalAiService = TestBed.inject(ModalAiService); + checkSearchAvailabilitySpy = spyOn(TestBed.inject(SearchAiService), 'checkSearchAvailability'); + notificationService = TestBed.inject(NotificationService); + userPreferencesService = TestBed.inject(UserPreferencesService); + spyOn(userPreferencesService, 'set'); + spyOn(notificationService, 'showError'); + queryInput = await loader.getHarness(MatInputHarness); + submitButton = fixture.debugElement.query(By.directive(MatButton)); + await queryInput.setValue(query); + const inputElement = fixture.debugElement.query(By.directive(MatInput)).nativeElement; + dialogOpenSpy = spyOn(dialog, 'open').and.returnValue({ + afterClosed: () => of(true) + } as MatDialogRef); + submittingTrigger = useButton + ? () => submitButton.nativeElement.click() + : () => + inputElement.dispatchEvent( + new KeyboardEvent('keyup', { + key: 'Enter' + }) + ); + }); + + it('should call showError on NotificationService if checkSearchAvailability from SearchAiService returns message', () => { + const message = 'Some message'; + checkSearchAvailabilitySpy.and.returnValue(message); + submittingTrigger(); + + expect(notificationService.showError).toHaveBeenCalledWith(message); + }); + + it('should not call showError on NotificationService if checkSearchAvailability from SearchAiService returns empty message', () => { + checkSearchAvailabilitySpy.and.returnValue(''); + submittingTrigger(); + + expect(notificationService.showError).not.toHaveBeenCalled(); + }); + + it('should call checkSearchAvailability on SearchAiService with parameter based on value returned by store', () => { + submittingTrigger(); + + expect(checkSearchAvailabilitySpy).toHaveBeenCalledWith(selectionState); + }); + + it('should call checkSearchAvailability on SearchAiService with parameter based on value returned by UserPreferencesService', () => { + component.useStoredNodes = true; + const newSelectionState: SelectionState = { + ...selectionState, + file: { + entry: { + id: 'some-id' + } + } as NodeEntry + }; + spyOn(userPreferencesService, 'get').and.returnValue(JSON.stringify(newSelectionState)); + component.ngOnInit(); + submittingTrigger(); + + expect(checkSearchAvailabilitySpy).toHaveBeenCalledWith(newSelectionState); + expect(userPreferencesService.get).toHaveBeenCalledWith('knowledgeRetrievalNodes'); + }); + + it('should call set on UserPreferencesService with parameter based on value returned by store', () => { + submittingTrigger(); + + expect(userPreferencesService.set).toHaveBeenCalledWith('knowledgeRetrievalNodes', JSON.stringify(selectionState)); + }); + + it('should call set on UserPreferencesService with parameter based on value returned by UserPreferencesService', () => { + component.useStoredNodes = true; + const newSelectionState: SelectionState = { + ...selectionState, + file: { + entry: { + id: 'some-id' + } + } as NodeEntry + }; + spyOn(userPreferencesService, 'get').and.returnValue(JSON.stringify(newSelectionState)); + component.ngOnInit(); + submittingTrigger(); + + expect(userPreferencesService.get).toHaveBeenCalledWith('knowledgeRetrievalNodes'); + expect(userPreferencesService.set).toHaveBeenCalledWith('knowledgeRetrievalNodes', JSON.stringify(newSelectionState)); + }); + + it('should call dispatch on store with correct parameter', () => { + spyOn(store, 'dispatch'); + submittingTrigger(); + + expect(store.dispatch).toHaveBeenCalledOnceWith( + new SearchByTermAiAction({ + searchTerm: query, + agentId: component.agentId + }) + ); + }); + + it('should call dispatch on store with correct parameter if selected agent was changed', async () => { + spyOn(store, 'dispatch'); + await ( + await loader.getHarness(MatSelectHarness) + ).clickOptions({ + text: 'HAHR Agent' + }); + submittingTrigger(); + + expect(store.dispatch).toHaveBeenCalledOnceWith( + new SearchByTermAiAction({ + searchTerm: query, + agentId: '1' + }) + ); + }); + + it('should reset query input', () => { + spyOn(component.queryControl, 'reset'); + submittingTrigger(); + + expect(component.queryControl.reset).toHaveBeenCalled(); + }); + + it('should emit searchSubmitted event', () => { + spyOn(component.searchSubmitted, 'emit'); + submittingTrigger(); + + expect(component.searchSubmitted.emit).toHaveBeenCalled(); + }); + + it('should call open modal if there was a previous search phrase in url', () => { + submittingTrigger(); + + expect(dialogOpenSpy).toHaveBeenCalled(); + }); + + it('should open Unsaved Changes Modal and run callback successfully', () => { + const modalAiSpy = spyOn(modalAiService, 'openUnsavedChangesModal').and.callThrough(); + spyOn(component.searchSubmitted, 'emit'); + + fixture.detectChanges(); + + submittingTrigger(); + expect(modalAiSpy).toHaveBeenCalledWith(jasmine.any(Function)); + expect(component.searchSubmitted.emit).toHaveBeenCalled(); + }); + }); + } +}); diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.ts new file mode 100644 index 000000000..c5cc14624 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-input/search-ai-input.component.ts @@ -0,0 +1,187 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { A11yModule } from '@angular/cdk/a11y'; +import { AvatarComponent, IconComponent, NotificationService, UserPreferencesService } from '@alfresco/adf-core'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { AiSearchByTermPayload, AppStore, getAppSelection, SearchByTermAiAction } from '@alfresco/aca-shared/store'; +import { takeUntil } from 'rxjs/operators'; +import { SelectionState } from '@alfresco/adf-extensions'; +import { MatSelectModule } from '@angular/material/select'; +import { AgentService, SearchAiService } from '@alfresco/adf-content-services'; +import { MatCardModule } from '@angular/material/card'; +import { + MAT_TOOLTIP_DEFAULT_OPTIONS, + MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY, + MatTooltipDefaultOptions, + MatTooltipModule +} from '@angular/material/tooltip'; +import { ModalAiService } from '../../../../services/modal-ai.service'; +import { Agent } from '@alfresco/js-api'; +import { getAgentsWithMockedAvatars } from '../search-ai-utils'; + +const MatTooltipOptions: MatTooltipDefaultOptions = { + ...MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY(), + disableTooltipInteractivity: true +}; + +@Component({ + standalone: true, + imports: [ + CommonModule, + TranslateModule, + MatButtonModule, + MatIconModule, + MatFormFieldModule, + MatInputModule, + A11yModule, + FormsModule, + ReactiveFormsModule, + MatSelectModule, + IconComponent, + AvatarComponent, + MatCardModule, + MatTooltipModule + ], + selector: 'aca-search-ai-input', + templateUrl: './search-ai-input.component.html', + styleUrls: ['./search-ai-input.component.scss'], + encapsulation: ViewEncapsulation.None, + providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: MatTooltipOptions }] +}) +export class SearchAiInputComponent implements OnInit, OnDestroy { + @Input() + placeholder: string; + + @Input() + agentId: string; + + @Input() + useStoredNodes: boolean; + + @Output() + searchSubmitted = new EventEmitter(); + + private readonly storedNodesKey = 'knowledgeRetrievalNodes'; + + private _agentControl = new FormControl(null); + private _agents: Agent[] = []; + private onDestroy$ = new Subject(); + private selectedNodesState: SelectionState; + private _queryControl = new FormControl(''); + private _initialsByAgentId: { [key: string]: string } = {}; + + avatarsMocked = true; + + get agentControl(): FormControl { + return this._agentControl; + } + + get agents(): Agent[] { + return this._agents; + } + + get queryControl(): FormControl { + return this._queryControl; + } + + get initialsByAgentId(): { [key: string]: string } { + return this._initialsByAgentId; + } + + constructor( + private store: Store, + private searchAiService: SearchAiService, + private notificationService: NotificationService, + private agentService: AgentService, + private userPreferencesService: UserPreferencesService, + private translateService: TranslateService, + private modalAiService: ModalAiService + ) {} + + ngOnInit(): void { + if (!this.useStoredNodes) { + this.store + .select(getAppSelection) + .pipe(takeUntil(this.onDestroy$)) + .subscribe((selection) => { + this.selectedNodesState = selection; + }); + } else { + this.selectedNodesState = JSON.parse(this.userPreferencesService.get(this.storedNodesKey)); + } + + this.agentService + .getAgents() + .pipe(takeUntil(this.onDestroy$)) + .subscribe( + (agents) => { + // TODO remove mocked avatar images after backend is done (https://hyland.atlassian.net/browse/ACS-8769) + this._agents = getAgentsWithMockedAvatars(agents, this.avatarsMocked); + + this.agentControl.setValue(this._agents.find((agent) => agent.id === this.agentId)); + this._initialsByAgentId = this.agents.reduce((initials, agent) => { + const words = agent.name.split(' ').filter((word) => !word.match(/[^a-zA-Z]+/g)); + initials[agent.id] = `${words[0][0]}${words[1]?.[0] || ''}`; + return initials; + }, {}); + }, + () => this.notificationService.showError(this.translateService.instant('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.AGENTS_FETCHING')) + ); + } + + ngOnDestroy(): void { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } + + onSearchSubmit() { + this.modalAiService.openUnsavedChangesModal(() => this.search()); + } + + search() { + const error = this.searchAiService.checkSearchAvailability(this.selectedNodesState); + if (error) { + this.notificationService.showError(error); + } else { + const payload: AiSearchByTermPayload = { + searchTerm: this.queryControl.value, + agentId: this.agentControl.value.id + }; + this.userPreferencesService.set(this.storedNodesKey, JSON.stringify(this.selectedNodesState)); + this.store.dispatch(new SearchByTermAiAction(payload)); + this.queryControl.reset(); + this.searchSubmitted.emit(); + } + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.html b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.html new file mode 100644 index 000000000..617e37afc --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.html @@ -0,0 +1,116 @@ + + + +
+ + + + + +
+
+
+
diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.scss b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.scss new file mode 100644 index 000000000..5a8ff684b --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.scss @@ -0,0 +1,182 @@ +@import '@alfresco/adf-core/lib/styles/mat-selectors'; + +.aca-search-ai-results { + aca-page-layout { + .aca-page-layout-content { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + background-color: white; + border-top: 1px solid var(--theme-grey-background-color); + padding-top: 28px; + + .aca-search-ai-results-container { + display: flex; + flex-direction: column; + height: 100%; + overflow-y: auto; + padding-right: 24%; + padding-left: 24%; + min-width: 51%; + + &-query { + border-radius: 12px; + padding: 20px 15px 19px; + background: var(--theme-card-background-grey-color); + } + } + + .aca-search-ai-response-container { + padding: 18px 20px; + display: flex; + flex-direction: column; + border: 1px solid var(--adf-card-view-border-color); + border-radius: 12px; + margin: 16px 0 75px; + + &-references-container-header { + padding-left: 8px; + } + + .adf-skeleton { + position: relative; + background-image: linear-gradient( + to left, + var(--theme-light-grey-1-color) 0%, + var(--theme-light-grey-2-color) 20%, + var(--theme-light-grey-3-color) 40%, + var(--theme-light-grey-1-color) 100% + ); + background-size: 200%; + display: inline-block; + height: 1em; + overflow: hidden; + width: 100%; + margin-bottom: 0.5rem; + border-radius: 0.25rem; + + &-half { + width: 50%; + margin-bottom: 8px; + } + + &::after { + position: absolute; + inset: 0; + transform: translateX(-100%); + background-image: linear-gradient(90deg, rgba(white, 0) 0, rgba(white, 0.2) 20%, rgba(white, 0.5) 60%, rgba(white, 0)); + animation: shimmer 2s infinite; + content: ''; + } + + @keyframes shimmer { + 100% { + transform: translateX(100%); + } + } + } + + &-error { + border-color: var(--adf-error-color); + padding: 32px 18px; + + &-message { + display: flex; + justify-content: space-between; + align-items: center; + + &-regeneration-button { + background-color: var(--adf-secondary-button-background); + + &-icon { + font-size: 24px; + height: 24px; + width: 23px; + } + } + } + } + + &-body { + &-response { + margin-bottom: 17px; + overflow-wrap: break-word; + + &-action { + width: max-content; + padding: 0; + + mat-icon { + font-size: 17.25px; + } + + &-regeneration { + margin-left: 2px; + margin-right: 2px; + } + + &-thumb-down { + margin-left: 4px; + } + + #{$mat-button-touch-target} { + width: 24px; + } + } + } + + &-divider { + margin-top: 9px; + } + + &-references-container { + padding-right: 8px; + padding-left: 8px; + + &-header { + margin-top: 16px; + color: var(--theme-text-light-color); + font-weight: 400; + margin-bottom: 3px; + } + + &-documents { + padding-right: 5px; + padding-top: 5px; + margin-left: -2px; + display: flex; + gap: 21px; + + &-document { + display: flex; + flex-direction: row; + padding-top: 7px; + padding-bottom: 7px; + + &-icon { + padding-right: 11px; + } + + &-name { + display: flex; + flex-direction: column; + width: 100%; + justify-content: center; + } + + &:hover { + text-decoration: underline; + text-decoration-color: var(--theme-primary-color); + color: var(--theme-primary-color); + cursor: pointer; + } + } + } + } + } + } + } + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.spec.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.spec.ts new file mode 100644 index 000000000..ab6def533 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.spec.ts @@ -0,0 +1,372 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { TestBed, ComponentFixture, tick, fakeAsync } from '@angular/core/testing'; +import { SearchAiResultsComponent } from './search-ai-results.component'; +import { ActivatedRoute, Params, Router } from '@angular/router'; +import { of, Subject, throwError } from 'rxjs'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; +import { EmptyContentComponent, UserPreferencesService } from '@alfresco/adf-core'; +import { MatDialogModule } from '@angular/material/dialog'; +import { AppTestingModule } from '../../../../testing/app-testing.module'; +import { MatIconTestingModule } from '@angular/material/icon/testing'; +import { AgentService, NodesApiService, SearchAiService } from '@alfresco/adf-content-services'; +import { By } from '@angular/platform-browser'; +import { ModalAiService } from '../../../../services/modal-ai.service'; +import { delay } from 'rxjs/operators'; +import { AiAnswer, AiAnswerEntry, QuestionModel } from '@alfresco/js-api/typings'; +import { SearchAiInputComponent } from '../search-ai-input/search-ai-input.component'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { getAppSelection, getCurrentFolder, ViewNodeAction } from '@alfresco/aca-shared/store'; +import { ViewerService } from '@alfresco/aca-content/viewer'; + +const questionMock: QuestionModel = { question: 'test', questionId: 'testId', restrictionQuery: { nodesIds: [] } }; +const aiAnswerMock: AiAnswer = { answer: 'Some answer', questionId: 'some id', references: [] }; +const getAiAnswerEntry = (noAnswer?: boolean): AiAnswerEntry => { + return { entry: { answer: noAnswer ? '' : 'Some answer', questionId: 'some id', references: [] } }; +}; + +describe('SearchAiResultsComponent', () => { + const knowledgeRetrievalNodes = '{"isEmpty":"false","nodes":[{"entry":{"id": "someId","isFolder":"true"}}]}'; + let fixture: ComponentFixture; + let component: SearchAiResultsComponent; + let userPreferencesService: UserPreferencesService; + let mockQueryParams = new Subject(); + let modalAiService: ModalAiService; + let searchAiService: SearchAiService; + let store: MockStore; + let viewerService: ViewerService; + + afterEach(() => { + store.resetSelectors(); + mockQueryParams = new Subject(); + fixture.destroy(); + }); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AppTestingModule, SearchAiResultsComponent, MatSnackBarModule, MatDialogModule, MatIconTestingModule], + providers: [ + { + provide: NodesApiService, + useValue: { + getNode: () => of({ id: 'someId', isFolder: true }).pipe(delay(50)) + } + }, + { + provide: ActivatedRoute, + useValue: { + queryParams: mockQueryParams.asObservable(), + snapshot: { + queryParams: { query: 'testQuery' } + } + } + }, + provideMockStore() + ] + }); + + fixture = TestBed.createComponent(SearchAiResultsComponent); + modalAiService = TestBed.inject(ModalAiService); + searchAiService = TestBed.inject(SearchAiService); + userPreferencesService = TestBed.inject(UserPreferencesService); + viewerService = TestBed.inject(ViewerService); + store = TestBed.inject(MockStore); + store.overrideSelector(getAppSelection, { + nodes: [], + isEmpty: true, + count: 0, + libraries: [] + }); + store.overrideSelector(getCurrentFolder, null); + spyOn(searchAiService, 'ask').and.returnValue(of(questionMock)); + spyOn(TestBed.inject(AgentService), 'getAgents').and.returnValue(of([])); + component = fixture.componentInstance; + component.ngOnInit(); + }); + + describe('query params change', () => { + it('should perform ai search and sets agents on query params change', () => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + expect(component.searchQuery).toBe('test'); + expect(component.agentId).toBe('agentId1'); + expect(component.hasError).toBeFalse(); + }); + + it('should throw an error if searchQuery not available', () => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + mockQueryParams.next({ agentId: 'agentId1' }); + + expect(component.searchQuery).toBe(''); + expect(component.agentId).toBe('agentId1'); + expect(component.hasError).toBeTrue(); + }); + + it('should not throw an error if selectedNodesState nodes not available', () => { + spyOn(userPreferencesService, 'get').and.returnValue('{}'); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + expect(component.searchQuery).toBe('test'); + expect(component.agentId).toBe('agentId1'); + expect(component.hasError).toBeFalse(); + }); + + it('should throw an error if agentId not available', () => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + mockQueryParams.next({ query: 'test' }); + + expect(component.searchQuery).toBe('test'); + expect(component.agentId).toBe(undefined); + expect(component.hasError).toBeTrue(); + }); + + it('should not get query answer and display an error when getAnswer throws error', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValue(throwError('error').pipe(delay(100))); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(30000); + + expect(component.queryAnswer).toBeUndefined(); + expect(component.hasAnsweringError).toBeTrue(); + expect(component.loading).toBeFalse(); + })); + + it('should get query answer and not display an error when getAnswer throws one error and one successful response', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValues(throwError('error'), of(getAiAnswerEntry())); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(3000); + + expect(component.queryAnswer).toEqual({ answer: 'Some answer', questionId: 'some id', references: [] }); + expect(component.hasAnsweringError).toBeFalse(); + })); + + it('should display and answer and not display an error when getAnswer throws nine errors and one successful response', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValues(...Array(9).fill(throwError('error')), of(getAiAnswerEntry())); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(50000); + + expect(component.queryAnswer).toEqual({ answer: 'Some answer', questionId: 'some id', references: [] }); + expect(component.hasAnsweringError).toBeFalse(); + })); + + it('should not display an answer and display an error when getAnswer throws ten errors', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValues(...Array(14).fill(throwError('error')), of(getAiAnswerEntry(true))); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(30000); + + expect(component.queryAnswer).toBeUndefined(); + expect(component.hasAnsweringError).toBeTrue(); + expect(component.loading).toBeFalse(); + })); + + it('should not display answer and display an error if received AiAnswerPaging without answer ten times', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValues(...Array(10).fill(of(getAiAnswerEntry(true)))); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(30000); + + expect(component.queryAnswer).toBeUndefined(); + expect(component.hasAnsweringError).toBeTrue(); + expect(component.loading).toBeFalse(); + })); + + it('should not display error and display and answer if received AiAnswerPaging without answer nine times and with answer one time', fakeAsync(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + spyOn(searchAiService, 'getAnswer').and.returnValues(...Array(9).fill(of(getAiAnswerEntry(true))), of(getAiAnswerEntry())); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(30000); + + expect(component.queryAnswer).toEqual({ answer: 'Some answer', questionId: 'some id', references: [] }); + expect(component.hasAnsweringError).toBeFalse(); + })); + + describe('when query params contains location', () => { + let params: Params; + + beforeEach(() => { + params = { + query: 'test', + agentId: 'agentId1', + location: 'some-location' + }; + }); + + it('should not render search ai input container', () => { + mockQueryParams.next(params); + + fixture.detectChanges(); + expect(fixture.debugElement.query(By.directive(SearchAiInputComponent))).toBeNull(); + }); + + it('should not render empty content', () => { + mockQueryParams.next({ + location: 'some-location' + }); + + fixture.detectChanges(); + expect(fixture.debugElement.query(By.directive(EmptyContentComponent))).toBeNull(); + }); + + it('should not display search query', () => { + mockQueryParams.next(params); + + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css(`[data-automation-id="aca-search-ai-results-query"]`)).nativeElement.textContent.trim()).toBe(''); + }); + + it('should not call searchAiService.ask', () => { + mockQueryParams.next(params); + + fixture.detectChanges(); + expect(searchAiService.ask).not.toHaveBeenCalled(); + }); + }); + }); + + describe('skeleton loader', () => { + const getSkeletonElementsLength = (): number => { + return fixture.nativeElement.querySelectorAll('.adf-skeleton').length; + }; + + beforeEach(() => { + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + }); + + it('should display skeleton when loading is true', () => { + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + component.performAiSearch(); + fixture.detectChanges(); + + expect(component.loading).toBeTrue(); + expect(getSkeletonElementsLength()).toBe(3); + }); + + it('should not display skeleton when loading is false', fakeAsync(() => { + spyOn(searchAiService, 'getAnswer').and.returnValue(of(getAiAnswerEntry())); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + component.performAiSearch(); + tick(30000); + + expect(component.loading).toBeFalse(); + expect(getSkeletonElementsLength()).toBe(0); + })); + }); + + describe('Unsaved Changes Modal', () => { + beforeEach(() => { + spyOn(userPreferencesService, 'get').and.returnValue('true'); + }); + + it('should open Unsaved Changes Modal and run callback successfully', () => { + const modalAiSpy = spyOn(modalAiService, 'openUnsavedChangesModal').and.callThrough(); + + spyOn(searchAiService, 'getAnswer').and.returnValue(of(getAiAnswerEntry())); + + fixture.detectChanges(); + + fixture.debugElement.query(By.css(`[data-automation-id="aca-search-ai-results-regeneration-button"]`)).nativeElement.click(); + expect(modalAiSpy).toHaveBeenCalledWith(jasmine.any(Function)); + expect(component.queryAnswer).toEqual(aiAnswerMock); + }); + }); + + describe('References', () => { + let documentElement: HTMLDivElement; + let nodesOrder: string[]; + + const nodeId = 'someId'; + const url = 'some-url'; + + beforeEach(fakeAsync(() => { + spyOnProperty(viewerService, 'customNodesOrder', 'set').and.callFake((passedNodesOrder) => (nodesOrder ??= passedNodesOrder)); + spyOn(userPreferencesService, 'set'); + spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); + const answer = getAiAnswerEntry(); + answer.entry.references = [{ referenceId: nodeId, referenceText: 'some text' }]; + spyOn(searchAiService, 'getAnswer').and.returnValues(throwError('error'), of(answer)); + mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); + + tick(3051); + fixture.detectChanges(); + documentElement = fixture.debugElement.query(By.css(`[data-automation-id="aca-search-ai-results-someId-document"]`)).nativeElement; + spyOn(store, 'dispatch'); + spyOnProperty(TestBed.inject(Router), 'url').and.returnValue(url); + })); + + it('should dispatch ViewNodeAction on store when clicked', () => { + documentElement.click(); + expect(store.dispatch).toHaveBeenCalledWith( + new ViewNodeAction(nodeId, { + location: url + }) + ); + }); + + it('should dispatch ViewNodeAction on store when pressed enter', () => { + documentElement.dispatchEvent( + new KeyboardEvent('keyup', { + key: 'Enter' + }) + ); + expect(store.dispatch).toHaveBeenCalledWith( + new ViewNodeAction(nodeId, { + location: url + }) + ); + }); + + it('should assign nodes ids to customNodesOrder for ViewerService', () => { + expect(nodesOrder).toEqual([nodeId]); + }); + + it('should call set on userPreferencesService with correct parameters', () => { + expect(userPreferencesService.set).toHaveBeenCalledWith('aiReferences', JSON.stringify([nodeId])); + }); + }); + + describe('ngOnInit', () => { + it('should set customNodesOrder on ViewerService', () => { + spyOn(userPreferencesService, 'get').and.returnValue('["node1", "node2"]'); + let nodesOrder: string[]; + spyOnProperty(viewerService, 'customNodesOrder', 'set').and.callFake((passedNodesOrder) => (nodesOrder = passedNodesOrder)); + + component.ngOnInit(); + + expect(nodesOrder).toEqual(['node1', 'node2']); + }); + }); +}); diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.ts new file mode 100644 index 000000000..882d21a76 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-results/search-ai-results.component.ts @@ -0,0 +1,245 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { PageComponent, PageLayoutComponent, ToolbarActionComponent, ToolbarComponent } from '@alfresco/aca-shared'; +import { concatMap, delay, filter, finalize, retryWhen, skipWhile, switchMap, takeUntil } from 'rxjs/operators'; +import { + AvatarComponent, + ClipboardService, + EmptyContentComponent, + ThumbnailService, + ToolbarModule, + UnsavedChangesGuard, + UserPreferencesService +} from '@alfresco/adf-core'; +import { AiAnswer, Node } from '@alfresco/js-api'; +import { CommonModule } from '@angular/common'; +import { SearchAiInputContainerComponent } from '../search-ai-input-container/search-ai-input-container.component'; +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { NodesApiService } from '@alfresco/adf-content-services'; +import { forkJoin, Observable, of, throwError } from 'rxjs'; +import { SelectionState } from '@alfresco/adf-extensions'; +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { MatListModule } from '@angular/material/list'; +import { MatCardModule } from '@angular/material/card'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { ModalAiService } from '../../../../services/modal-ai.service'; +import { ViewNodeAction } from '@alfresco/aca-shared/store'; +import { ViewerService } from '@alfresco/aca-content/viewer'; + +@Component({ + standalone: true, + imports: [ + CommonModule, + PageLayoutComponent, + ToolbarActionComponent, + ToolbarModule, + ToolbarComponent, + SearchAiInputContainerComponent, + TranslateModule, + MatIconModule, + MatButtonModule, + MatListModule, + EmptyContentComponent, + MatCardModule, + AvatarComponent, + MatTooltipModule + ], + selector: 'aca-search-ai-results', + templateUrl: './search-ai-results.component.html', + styleUrls: ['./search-ai-results.component.scss'], + encapsulation: ViewEncapsulation.None, + host: { class: 'aca-search-ai-results' } +}) +export class SearchAiResultsComponent extends PageComponent implements OnInit, OnDestroy { + private _agentId: string; + private _hasAnsweringError = false; + private _hasError = false; + private _loading = false; + private _mimeTypeIconsByNodeId: { [key: string]: string } = {}; + private _nodes: Node[] = []; + private openedViewer = false; + private _selectedNodesState: SelectionState; + private _searchQuery = ''; + private _queryAnswer: AiAnswer; + + get agentId(): string { + return this._agentId; + } + + get hasAnsweringError(): boolean { + return this._hasAnsweringError; + } + + get hasError(): boolean { + return this._hasError; + } + + get loading(): boolean { + return this._loading; + } + + get mimeTypeIconsByNodeId(): { [key: string]: string } { + return this._mimeTypeIconsByNodeId; + } + + get nodes(): Node[] { + return this._nodes; + } + + get queryAnswer(): AiAnswer { + return this._queryAnswer; + } + + get searchQuery(): string { + return this._searchQuery; + } + + constructor( + private route: ActivatedRoute, + private clipboardService: ClipboardService, + private thumbnailService: ThumbnailService, + private nodesApiService: NodesApiService, + private userPreferencesService: UserPreferencesService, + private translateService: TranslateService, + private unsavedChangesGuard: UnsavedChangesGuard, + private modalAiService: ModalAiService, + private viewerService: ViewerService + ) { + super(); + } + + ngOnInit(): void { + this.viewerService.customNodesOrder = JSON.parse(this.userPreferencesService.get('aiReferences', '[]')); + this.route.queryParams + .pipe( + filter((params) => { + const openedViewerPreviously = this.openedViewer; + this.openedViewer = !!params.location; + return !this.openedViewer && (!openedViewerPreviously || !this.queryAnswer); + }), + takeUntil(this.onDestroy$) + ) + .subscribe((params) => { + this._agentId = params.agentId; + this._searchQuery = params.query ? decodeURIComponent(params.query) : ''; + if (!this.searchQuery || !this.agentId) { + this._hasError = true; + return; + } + this._selectedNodesState = JSON.parse(this.userPreferencesService.get('knowledgeRetrievalNodes')); + this.performAiSearch(); + }); + super.ngOnInit(); + + this.unsavedChangesGuard.unsaved = this.route.snapshot?.queryParams?.query?.length > 0; + this.unsavedChangesGuard.data = { + descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.CONVERSATION_DISCARDED', + confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.OKAY', + headerText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.WARNING' + }; + } + + ngOnDestroy(): void { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } + + copyResponseToClipboard(): void { + this.clipboardService.copyContentToClipboard( + this.queryAnswer.answer, + this.translateService.instant('KNOWLEDGE_RETRIEVAL.SEARCH.RESULTS_PAGE.COPY_MESSAGE') + ); + } + + checkUnsavedChangesAndSearch(): void { + this.modalAiService.openUnsavedChangesModal(() => this.performAiSearch()); + } + + performAiSearch(): void { + this._loading = true; + + this.searchAiService + .ask({ + question: this.searchQuery, + nodeIds: this._selectedNodesState?.nodes?.length ? this._selectedNodesState.nodes.map((node) => node.entry.id) : [], + agentId: this._agentId + }) + .pipe( + switchMap((response) => this.searchAiService.getAnswer(response.questionId)), + switchMap((response) => { + if (!response.entry?.answer) { + return throwError((e) => e); + } + this._queryAnswer = response.entry; + return forkJoin(this.queryAnswer.references.map((reference) => this.nodesApiService.getNode(reference.referenceId))); + }), + retryWhen((errors: Observable) => this.aiSearchRetryWhen(errors)), + finalize(() => (this._loading = false)), + takeUntil(this.onDestroy$) + ) + .subscribe( + (nodes) => { + nodes.forEach((node) => { + this._mimeTypeIconsByNodeId[node.id] = this.thumbnailService.getMimeTypeIcon(node.content?.mimeType); + }); + this._nodes = nodes; + const nodesIds = nodes.map((node) => node.id); + this.viewerService.customNodesOrder = nodesIds; + this.userPreferencesService.set('aiReferences', JSON.stringify(nodesIds)); + }, + () => (this._hasAnsweringError = true) + ); + } + + openFile(id: string): void { + this.store.dispatch( + new ViewNodeAction(id, { + location: this.router.url + }) + ); + } + + private aiSearchRetryWhen(errors: Observable): Observable { + this._hasAnsweringError = false; + const delayBetweenRetries = 3000; + const maxRetries = 9; + + return errors.pipe( + skipWhile(() => this.hasAnsweringError), + delay(delayBetweenRetries), + concatMap((e, index) => { + if (index === maxRetries) { + this._hasAnsweringError = true; + this._loading = false; + return throwError(e); + } + return of(null); + }) + ); + } +} diff --git a/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-utils.ts b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-utils.ts new file mode 100644 index 000000000..9f76d2e74 --- /dev/null +++ b/projects/aca-content/src/lib/components/knowledge-retrieval/search-ai/search-ai-utils.ts @@ -0,0 +1,35 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Agent } from '@alfresco/js-api/typings'; + +export const getAgentsWithMockedAvatars = (agents: Agent[], mocked: boolean) => { + if (mocked) { + const images = ['assets/images/avatars/Blue.png', 'assets/images/avatars/Gold.png', 'assets/images/avatars/Pink.png']; + return agents.map((agent, index) => { + return { ...agent, avatarUrl: images[index > 2 ? 2 : index] }; + }); + } + return agents; +}; diff --git a/projects/aca-content/src/lib/components/recent-files/recent-files.component.html b/projects/aca-content/src/lib/components/recent-files/recent-files.component.html index 80cfa618b..2a2a84fb8 100644 --- a/projects/aca-content/src/lib/components/recent-files/recent-files.component.html +++ b/projects/aca-content/src/lib/components/recent-files/recent-files.component.html @@ -1,9 +1,17 @@
-

+ + + +
+

{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.RECENT.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}

- + +
+

diff --git a/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts b/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts index 8db29b52c..c7ef0377a 100644 --- a/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts +++ b/projects/aca-content/src/lib/components/recent-files/recent-files.component.ts @@ -39,6 +39,7 @@ import { DocumentListModule } from '@alfresco/adf-content-services'; import { DataTableModule, EmptyContentComponent, PaginationComponent } from '@alfresco/adf-core'; import { DocumentListDirective } from '../../directives/document-list.directive'; import { TranslateModule } from '@ngx-translate/core'; +import { SearchAiInputContainerComponent } from '../knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; @Component({ standalone: true, @@ -54,11 +55,13 @@ import { TranslateModule } from '@ngx-translate/core'; PageLayoutComponent, TranslateModule, ToolbarComponent, + SearchAiInputContainerComponent, EmptyContentComponent, DynamicColumnComponent ], templateUrl: './recent-files.component.html', - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, + selector: 'aca-recent-files' }) export class RecentFilesComponent extends PageComponent implements OnInit { columns: DocumentListPresetRef[] = []; diff --git a/projects/aca-content/src/lib/components/search/search-results/search-results.component.html b/projects/aca-content/src/lib/components/search/search-results/search-results.component.html index 9274f94fd..d2b32cba2 100644 --- a/projects/aca-content/src/lib/components/search/search-results/search-results.component.html +++ b/projects/aca-content/src/lib/components/search/search-results/search-results.component.html @@ -1,9 +1,15 @@ - +
- - -
- + + +
+ + +
+ +
diff --git a/projects/aca-content/src/lib/components/search/search-results/search-results.component.scss b/projects/aca-content/src/lib/components/search/search-results/search-results.component.scss index 4b42cbfc1..112adcd66 100644 --- a/projects/aca-content/src/lib/components/search/search-results/search-results.component.scss +++ b/projects/aca-content/src/lib/components/search/search-results/search-results.component.scss @@ -1,6 +1,13 @@ @import '../../../ui/mixins'; aca-search-results { + .aca-search-results-active-search-ai-input { + .aca-header-container, + .adf-search-results__content-header.aca-content { + display: none; + } + } + .aca-search-toolbar-spacer { width: 100%; } diff --git a/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts b/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts index 2ddf74b44..0598ca69a 100644 --- a/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts +++ b/projects/aca-content/src/lib/components/search/search-results/search-results.component.ts @@ -77,6 +77,7 @@ import { MatIconModule } from '@angular/material/icon'; import { SearchResultsRowComponent } from '../search-results-row/search-results-row.component'; import { DocumentListPresetRef, DynamicColumnComponent } from '@alfresco/adf-extensions'; import { BulkActionsDropdownComponent } from '../../bulk-actions-dropdown/bulk-actions-dropdown.component'; +import { SearchAiInputContainerComponent } from '../../knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; @Component({ standalone: true, @@ -110,7 +111,8 @@ import { BulkActionsDropdownComponent } from '../../bulk-actions-dropdown/bulk-a DateColumnHeaderComponent, CustomEmptyContentTemplateDirective, ViewerToolbarComponent, - BulkActionsDropdownComponent + BulkActionsDropdownComponent, + SearchAiInputContainerComponent ], selector: 'aca-search-results', templateUrl: './search-results.component.html', diff --git a/projects/aca-content/src/lib/components/shared-files/shared-files.component.html b/projects/aca-content/src/lib/components/shared-files/shared-files.component.html index e8f446754..33e6fe8b0 100644 --- a/projects/aca-content/src/lib/components/shared-files/shared-files.component.html +++ b/projects/aca-content/src/lib/components/shared-files/shared-files.component.html @@ -1,10 +1,18 @@
-

+ + + +
+

{{ (selectedRowItemsCount < 1 ? 'APP.BROWSE.SHARED.TITLE' : 'APP.HEADER.SELECTED') | translate: { count: selectedRowItemsCount } }}

- + +
+

diff --git a/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts b/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts index 3c8793aad..d84d0e36f 100644 --- a/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts +++ b/projects/aca-content/src/lib/components/shared-files/shared-files.component.ts @@ -40,6 +40,7 @@ import { DocumentListModule } from '@alfresco/adf-content-services'; import { DataTableModule, EmptyContentComponent, PaginationComponent } from '@alfresco/adf-core'; import { DocumentListDirective } from '../../directives/document-list.directive'; import { TranslateModule } from '@ngx-translate/core'; +import { SearchAiInputContainerComponent } from '../knowledge-retrieval/search-ai/search-ai-input-container/search-ai-input-container.component'; @Component({ standalone: true, @@ -55,11 +56,13 @@ import { TranslateModule } from '@ngx-translate/core'; PageLayoutComponent, TranslateModule, ToolbarComponent, + SearchAiInputContainerComponent, EmptyContentComponent, DynamicColumnComponent ], templateUrl: './shared-files.component.html', - encapsulation: ViewEncapsulation.None + encapsulation: ViewEncapsulation.None, + selector: 'aca-shared-files' }) export class SharedFilesComponent extends PageComponent implements OnInit { columns: DocumentListPresetRef[] = []; diff --git a/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.spec.ts b/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.spec.ts index 230387591..10c8a8b4e 100644 --- a/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.spec.ts +++ b/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.spec.ts @@ -118,5 +118,25 @@ describe('AcaExpansionPanel', () => { expect(router.navigate).not.toHaveBeenCalled(); }); + + it('should not navigate to first child if none is active route and acaExpansionPanel has canBeInactive property', () => { + const router: any = new RouterStub('dummy-route-2'); + spyOn(router, 'navigate').and.callThrough(); + const item = { + children: [{ url: 'dummy-route-1' }, { url: 'dummy-route-2' }], + data: { + canBeInactive: true + } + }; + + const directive = new ExpansionPanelDirective(mockStore, router, mockMatExpansionPanel); + + directive.acaExpansionPanel = item; + mockMatExpansionPanel.expanded = true; + + directive.onClick(); + + expect(router.navigate).not.toHaveBeenCalled(); + }); }); }); diff --git a/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.ts b/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.ts index dd4e27405..be559ff4b 100644 --- a/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.ts +++ b/projects/aca-content/src/lib/components/sidenav/directives/expansion-panel.directive.ts @@ -42,7 +42,7 @@ export class ExpansionPanelDirective implements OnInit, OnDestroy { @HostListener('click') onClick() { - if (this.expansionPanel.expanded && !this.hasActiveLinks()) { + if (this.expansionPanel.expanded && !this.hasActiveLinks() && !this.acaExpansionPanel.data?.canBeInactive) { const firstChild = this.acaExpansionPanel.children[0]; if (firstChild.url) { this.router.navigate(this.getNavigationCommands(firstChild.url)); diff --git a/projects/aca-content/src/lib/services/modal-ai.service.spec.ts b/projects/aca-content/src/lib/services/modal-ai.service.spec.ts new file mode 100644 index 000000000..01f1658bc --- /dev/null +++ b/projects/aca-content/src/lib/services/modal-ai.service.spec.ts @@ -0,0 +1,114 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { ModalAiService } from './modal-ai.service'; +import { TestBed } from '@angular/core/testing'; +import { ContentTestingModule } from '@alfresco/adf-content-services'; +import { MatDialog, MatDialogConfig, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; +import { ActivatedRoute, Params } from '@angular/router'; +import { of, Subject } from 'rxjs'; +import { StorageService, UnsavedChangesDialogComponent } from '@alfresco/adf-core'; + +describe('ModalAiService', () => { + const mockQueryParams = new Subject(); + + let service: ModalAiService; + let dialogOpenSpy: jasmine.Spy<(component: typeof UnsavedChangesDialogComponent, config?: MatDialogConfig) => MatDialogRef>; + let dialog: MatDialog; + + const setupBeforeEach = (query: string, storageGetItem: string) => { + TestBed.configureTestingModule({ + imports: [ContentTestingModule, MatDialogModule], + providers: [ + { + provide: StorageService, + useValue: { + getItem: () => storageGetItem, + setItem: () => storageGetItem + } + }, + { + provide: ActivatedRoute, + useValue: { + queryParams: mockQueryParams.asObservable(), + snapshot: { + queryParams: { query } + } + } + } + ] + }); + + dialog = TestBed.inject(MatDialog); + dialogOpenSpy = spyOn(dialog, 'open').and.returnValue({ + afterClosed: () => of(true) + } as MatDialogRef); + service = TestBed.inject(ModalAiService); + }; + + describe('when there is no previous search and no UNSAVED_CHANGES_MODAL_HIDDEN in the storage', () => { + it('should not open unsaved changes modal when there is not previous search and no UNSAVED_CHANGES_MODAL_HIDDEN in storage', () => { + setupBeforeEach('', ''); + service.openUnsavedChangesModal(() => {}); + + expect(dialogOpenSpy).not.toHaveBeenCalled(); + }); + }); + + describe('when there is no previous search and there is UNSAVED_CHANGES_MODAL_HIDDEN in storage', () => { + it('should open unsaved changes modal when there is previous search and no UNSAVED_CHANGES_MODAL_HIDDEN in local storage', () => { + setupBeforeEach('test', ''); + service.openUnsavedChangesModal(() => {}); + + expect(dialogOpenSpy).toHaveBeenCalledWith(UnsavedChangesDialogComponent, { + width: '345px', + data: { + descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.LOSE_RESPONSE', + confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.ASK_AI', + checkboxText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.DO_NOT_SHOW_MESSAGE', + headerText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.WARNING' + } + }); + }); + + it('should call callback after modal has been closed and change test value to true', () => { + let test = false; + const mockFunc = () => { + test = true; + }; + setupBeforeEach('test', ''); + service.openUnsavedChangesModal(mockFunc); + expect(test).toBeTrue(); + }); + }); + + describe('when there is previous search in query and UNSAVED_CHANGES_MODAL_HIDDEN is the storage', () => { + it('should not open unsaved changes modal when has previous search and there is UNSAVED_CHANGES_MODAL_HIDDEN in local storage', () => { + setupBeforeEach('test', 'true'); + service.openUnsavedChangesModal(() => {}); + + expect(dialogOpenSpy).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/projects/aca-content/src/lib/services/modal-ai.service.ts b/projects/aca-content/src/lib/services/modal-ai.service.ts new file mode 100644 index 000000000..59649af5c --- /dev/null +++ b/projects/aca-content/src/lib/services/modal-ai.service.ts @@ -0,0 +1,62 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { inject, Injectable } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { AppConfigValues, UnsavedChangesDialogComponent, UserPreferencesService } from '@alfresco/adf-core'; +import { MatDialog } from '@angular/material/dialog'; + +@Injectable({ providedIn: 'root' }) +export class ModalAiService { + private route = inject(ActivatedRoute); + private dialog = inject(MatDialog); + private userPreferencesService = inject(UserPreferencesService); + + openUnsavedChangesModal(callback: () => void): void { + const hasPreviousSearch = this.route.snapshot?.queryParams?.query?.length > 0; + const modalHidden = this.userPreferencesService.get(AppConfigValues.UNSAVED_CHANGES_MODAL_HIDDEN) === 'true'; + + if (!hasPreviousSearch || modalHidden) { + callback(); + return; + } + + this.dialog + .open(UnsavedChangesDialogComponent, { + width: '345px', + data: { + descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.LOSE_RESPONSE', + confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.ASK_AI', + checkboxText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.DO_NOT_SHOW_MESSAGE', + headerText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.WARNING' + } + }) + .afterClosed() + .subscribe((openModal: boolean) => { + if (openModal) { + callback(); + } + }); + } +} diff --git a/projects/aca-content/src/lib/services/search-ai-navigation.service.spec.ts b/projects/aca-content/src/lib/services/search-ai-navigation.service.spec.ts new file mode 100644 index 000000000..7da4d1c80 --- /dev/null +++ b/projects/aca-content/src/lib/services/search-ai-navigation.service.spec.ts @@ -0,0 +1,134 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { SearchAiNavigationService } from './search-ai-navigation.service'; +import { Params, Router } from '@angular/router'; +import { TestBed } from '@angular/core/testing'; +import { ContentTestingModule } from '@alfresco/adf-content-services'; + +describe('SearchAiNavigationService', () => { + let service: SearchAiNavigationService; + let router: Router; + + const knowledgeRetrievalUrl = '/knowledge-retrieval'; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ContentTestingModule] + }); + service = TestBed.inject(SearchAiNavigationService); + router = TestBed.inject(Router); + }); + + describe('navigateToPreviousRoute', () => { + let urlSpy: jasmine.Spy<() => string>; + let navigateByUrlSpy: jasmine.Spy<(url: string) => Promise>; + + const sourceUrl = '/some-url'; + const personalFilesUrl = '/personal-files'; + + beforeEach(() => { + navigateByUrlSpy = spyOn(router, 'navigateByUrl'); + urlSpy = spyOnProperty(router, 'url'); + }); + + it('should navigate to personal files if there is not previous route and actual route is knowledge retrieval', () => { + urlSpy.and.returnValue(knowledgeRetrievalUrl); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).toHaveBeenCalledWith(personalFilesUrl); + }); + + it('should not navigate if there is not previous route and actual route is not knowledge retrieval', () => { + urlSpy.and.returnValue('/some-url'); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).not.toHaveBeenCalled(); + }); + + it('should navigate to previous route if there is some previous route and actual route is knowledge retrieval', () => { + urlSpy.and.returnValue(sourceUrl); + service.navigateToSearchAi({ + agentId: 'some agent id' + }); + urlSpy.and.returnValue(knowledgeRetrievalUrl); + navigateByUrlSpy.calls.reset(); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).toHaveBeenCalledWith(sourceUrl); + }); + + it('should not navigate to previous route if there is some previous route but actual route is not knowledge retrieval', () => { + urlSpy.and.returnValue(sourceUrl); + service.navigateToSearchAi({ + agentId: 'some agent id' + }); + urlSpy.and.returnValue('/some-different-url'); + navigateByUrlSpy.calls.reset(); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).not.toHaveBeenCalled(); + }); + + it('should navigate to personal files if previous route is knowledge retrieval and actual route is knowledge retrieval', () => { + urlSpy.and.returnValue(knowledgeRetrievalUrl); + service.navigateToSearchAi({ + agentId: 'some agent id' + }); + navigateByUrlSpy.calls.reset(); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).toHaveBeenCalledWith(personalFilesUrl); + }); + + it('should not navigate if previous route is knowledge retrieval and actual route is different than knowledge retrieval', () => { + urlSpy.and.returnValue(knowledgeRetrievalUrl); + service.navigateToSearchAi({ + agentId: 'some agent id' + }); + urlSpy.and.returnValue(sourceUrl); + navigateByUrlSpy.calls.reset(); + service.navigateToPreviousRoute(); + + expect(navigateByUrlSpy).not.toHaveBeenCalled(); + }); + }); + + describe('navigateToSearchAi', () => { + beforeEach(() => { + spyOn(router, 'navigate'); + }); + + it('should navigate to search ai results page', () => { + const queryParams: Params = { + agentId: 'some agent id' + }; + service.navigateToSearchAi(queryParams); + + expect(router.navigate).toHaveBeenCalledWith([knowledgeRetrievalUrl], { + queryParams + }); + }); + }); +}); diff --git a/projects/aca-content/src/lib/services/search-ai-navigation.service.ts b/projects/aca-content/src/lib/services/search-ai-navigation.service.ts new file mode 100644 index 000000000..6bc745e3c --- /dev/null +++ b/projects/aca-content/src/lib/services/search-ai-navigation.service.ts @@ -0,0 +1,48 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Injectable } from '@angular/core'; +import { Params, Router } from '@angular/router'; + +@Injectable({ providedIn: 'root' }) +export class SearchAiNavigationService { + private readonly knowledgeRetrievalRoute = '/knowledge-retrieval'; + + private previousRoute = ''; + + constructor(private router: Router) {} + + navigateToPreviousRoute(): void { + if (this.router.url.includes(this.knowledgeRetrievalRoute)) { + void this.router.navigateByUrl(this.previousRoute || '/personal-files'); + } + } + + navigateToSearchAi(queryParams: Params): void { + if (!this.router.url.includes(this.knowledgeRetrievalRoute)) { + this.previousRoute = this.router.url; + } + void this.router.navigate([this.knowledgeRetrievalRoute], { queryParams }); + } +} diff --git a/projects/aca-content/src/lib/store/app-store.module.ts b/projects/aca-content/src/lib/store/app-store.module.ts index 02297d68b..dfeb5d107 100644 --- a/projects/aca-content/src/lib/store/app-store.module.ts +++ b/projects/aca-content/src/lib/store/app-store.module.ts @@ -41,6 +41,7 @@ import { ContextMenuEffects } from './effects'; import { INITIAL_STATE } from './initial-state'; +import { SearchAiEffects } from './effects/search-ai.effects'; @NgModule({ imports: [ @@ -69,6 +70,8 @@ import { INITIAL_STATE } from './initial-state'; FavoriteEffects, TemplateEffects, ContextMenuEffects, + SearchAiEffects, + ContextMenuEffects, SnackbarEffects, RouterEffects ]) diff --git a/projects/aca-content/src/lib/store/effects.ts b/projects/aca-content/src/lib/store/effects.ts index f8eb84022..423fed8d0 100644 --- a/projects/aca-content/src/lib/store/effects.ts +++ b/projects/aca-content/src/lib/store/effects.ts @@ -33,3 +33,4 @@ export * from './effects/upload.effects'; export * from './effects/upload.effects'; export * from './effects/template.effects'; export * from './effects/contextmenu.effects'; +export * from './effects/search-ai.effects'; diff --git a/projects/aca-content/src/lib/store/effects/search-ai.effects.ts b/projects/aca-content/src/lib/store/effects/search-ai.effects.ts new file mode 100644 index 000000000..4670b8a77 --- /dev/null +++ b/projects/aca-content/src/lib/store/effects/search-ai.effects.ts @@ -0,0 +1,65 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { SearchAiActionTypes, SearchByTermAiAction, ToggleAISearchInput } from '@alfresco/aca-shared/store'; +import { map } from 'rxjs/operators'; +import { SearchAiNavigationService } from '../../services/search-ai-navigation.service'; +import { SearchAiService } from '@alfresco/adf-content-services'; +import { Params } from '@angular/router'; + +@Injectable() +export class SearchAiEffects { + constructor(private actions$: Actions, private searchNavigationService: SearchAiNavigationService, private searchAiService: SearchAiService) {} + + searchByTerm$ = createEffect( + () => + this.actions$.pipe( + ofType(SearchAiActionTypes.SearchByTermAi), + map((action) => { + const queryParams: Params = { + query: encodeURIComponent(action.payload.searchTerm), + agentId: action.payload.agentId + }; + this.searchNavigationService.navigateToSearchAi(queryParams); + }) + ), + { dispatch: false } + ); + + toggleAISearchInput$ = createEffect( + () => + this.actions$.pipe( + ofType(SearchAiActionTypes.ToggleAiSearchInput), + map((action) => + this.searchAiService.updateSearchAiInputState({ + active: true, + selectedAgentId: action.agentId + }) + ) + ), + { dispatch: false } + ); +} diff --git a/projects/aca-content/src/lib/ui/application.scss b/projects/aca-content/src/lib/ui/application.scss index 0762b52a4..31eac5710 100644 --- a/projects/aca-content/src/lib/ui/application.scss +++ b/projects/aca-content/src/lib/ui/application.scss @@ -66,3 +66,11 @@ ng-component { color: var(--adf-theme-foreground-text-color-087); width: 100%; } + +.aca-header-container { + display: flex; + flex-direction: row; + flex: 1; + align-items: center; + width: 100%; +} diff --git a/projects/aca-content/src/lib/ui/theme.scss b/projects/aca-content/src/lib/ui/theme.scss index 34aa31e10..f34e93429 100644 --- a/projects/aca-content/src/lib/ui/theme.scss +++ b/projects/aca-content/src/lib/ui/theme.scss @@ -338,3 +338,9 @@ adf-dynamic-component { min-width: 160px; } } + +.adf-unsaved-changes-dialog { + .adf-unsaved-changes-dialog-actions-discard-changes-button:is(button) { + background-color: var(--theme-blue-button-color); + } +} diff --git a/projects/aca-content/src/lib/ui/variables/variables.scss b/projects/aca-content/src/lib/ui/variables/variables.scss index aa6ec1d4c..ad1fbe316 100644 --- a/projects/aca-content/src/lib/ui/variables/variables.scss +++ b/projects/aca-content/src/lib/ui/variables/variables.scss @@ -28,6 +28,7 @@ $blue-save-button-background: #1f74db; $blue-checkbox-background: rgb(10, 96, 206); $blue-active-table-row: rgb(10, 96, 206, 0.24); $black-heading: #4e4c4c; +$light-grey-content: #4b5563; $theme-dropdown-background: darken($background-color, 5%); $theme-dropdown-background-hover: darken($background-color, 10%); $grey-divider: rgba(0, 0, 0, 0.22); @@ -46,6 +47,11 @@ $disabled-chip-background-color: #f5f5f5; $contrast-gray: mat.get-color-from-palette($foreground, 'secondary-tex'); $search-highlight-background-color: #ffd180; $info-snackbar-background: #1f74db; +$text-light-color: rgba(33, 35, 40, 0.7); +$card-background-grey-color: rgb(248, 248, 248); +$light-grey-1: #d5d5d5; +$light-grey-2: #d9d9d9; +$light-grey-3: #dedede; // CSS Variables $defaults: ( @@ -75,6 +81,7 @@ $defaults: ( --theme-blue-checkbox-color: $blue-checkbox-background, --theme-blue-active-table-row-color: $blue-active-table-row, --theme-heading-color: $black-heading, + --theme-content-color: $light-grey-content, --theme-dropdown-color: $theme-dropdown-background, --theme-dropdown-background-hover: $theme-dropdown-background-hover, --theme-grey-divider-color: $grey-divider, @@ -96,7 +103,12 @@ $defaults: ( --theme-search-chip-icon-color: $search-chip-icon-color, --theme-disabled-chip-background-color: $disabled-chip-background-color, --theme-secondary-text: $secondary-text, - --theme-search-highlight-background-color: $search-highlight-background-color + --theme-search-highlight-background-color: $search-highlight-background-color, + --theme-text-light-color: $text-light-color, + --theme-card-background-grey-color: $card-background-grey-color, + --theme-light-grey-1-color: $light-grey-1, + --theme-light-grey-2-color: $light-grey-2, + --theme-light-grey-3-color: $light-grey-3 ); // propagates SCSS variables into the CSS variables scope diff --git a/projects/aca-content/viewer/src/lib/services/viewer.service.spec.ts b/projects/aca-content/viewer/src/lib/services/viewer.service.spec.ts index c3fd364e9..b68bdc6e8 100644 --- a/projects/aca-content/viewer/src/lib/services/viewer.service.spec.ts +++ b/projects/aca-content/viewer/src/lib/services/viewer.service.spec.ts @@ -215,4 +215,9 @@ describe('ViewerService', () => { const ids = await viewerService.getFileIds('libraries', null); expect(ids).toEqual([]); }); + + it('should return custom nodes order if did not find nodes', async () => { + viewerService.customNodesOrder = ['someNode1', 'someNode2']; + expect(await viewerService.getFileIds('', null)).toEqual(['someNode1', 'someNode2']); + }); }); diff --git a/projects/aca-content/viewer/src/lib/services/viewer.service.ts b/projects/aca-content/viewer/src/lib/services/viewer.service.ts index 3cf9a9aee..ad87ade59 100644 --- a/projects/aca-content/viewer/src/lib/services/viewer.service.ts +++ b/projects/aca-content/viewer/src/lib/services/viewer.service.ts @@ -36,6 +36,12 @@ interface AdjacentFiles { providedIn: 'root' }) export class ViewerService { + private _customNodesOrder: string[] = []; + + set customNodesOrder(customNodesOrder: string[]) { + this._customNodesOrder = customNodesOrder; + } + constructor(private preferences: UserPreferencesService, private contentApi: ContentApiService) {} recentFileFilters = [ @@ -103,7 +109,6 @@ export class ViewerService { } const isClient = this.preferences.get(`${source}.sorting.mode`) === 'client'; const [sortKey, sortDirection, previousSortKey, previousSortDir] = this.getSortKeyDir(source); - let entries: Node[] | SharedLink[] = []; let nodes: NodePaging | FavoritePaging | SharedLinkPaging | ResultSetPaging; if (source === 'personal-files' || source === 'libraries-files') { @@ -164,15 +169,7 @@ export class ViewerService { }; nodes = await this.contentApi.search(query).toPromise(); } - - entries = nodes.list.entries.map((obj) => obj.entry.target?.file ?? obj.entry); - if (isClient) { - if (previousSortKey) { - this.sort(entries, previousSortKey, previousSortDir); - } - this.sort(entries, sortKey, sortDirection); - } - return entries.map((entry) => entry.id ?? entry.nodeId); + return this.getCustomNodesOrderIfNoNodes(nodes, isClient, previousSortKey, previousSortDir, sortKey, sortDirection); } /** @@ -224,4 +221,26 @@ export class ViewerService { return ['modifiedAt', 'desc']; } } + + private getCustomNodesOrderIfNoNodes( + nodes: NodePaging | FavoritePaging | SharedLinkPaging | ResultSetPaging, + isClient: boolean, + previousSortKey: string, + previousSortDir: string, + sortKey: string, + sortDirection: string + ): string[] { + if (nodes) { + const entries = nodes.list.entries.map((obj) => obj.entry.target?.file ?? obj.entry); + if (isClient) { + if (previousSortKey) { + this.sort(entries, previousSortKey, previousSortDir); + } + this.sort(entries, sortKey, sortDirection); + } + return entries.map((entry) => entry.id ?? entry.nodeId); + } else { + return this._customNodesOrder; + } + } } diff --git a/projects/aca-content/viewer/src/public-api.ts b/projects/aca-content/viewer/src/public-api.ts index 21c382658..9bd7663c5 100644 --- a/projects/aca-content/viewer/src/public-api.ts +++ b/projects/aca-content/viewer/src/public-api.ts @@ -29,3 +29,4 @@ export * from './lib/components/viewer/viewer.component'; export * from './lib/components/preview/preview.component'; export * from './lib/viewer.module'; +export * from './lib/services/viewer.service'; diff --git a/projects/aca-shared/rules/src/app.rules.spec.ts b/projects/aca-shared/rules/src/app.rules.spec.ts index aebdc0827..d5fe674a9 100644 --- a/projects/aca-shared/rules/src/app.rules.spec.ts +++ b/projects/aca-shared/rules/src/app.rules.spec.ts @@ -23,9 +23,9 @@ */ import * as app from './app.rules'; -import { getFileExtension } from './app.rules'; import { TestRuleContext } from './test-rule-context'; import { NodeEntry, RepositoryInfo, StatusInfo } from '@alfresco/js-api'; +import { getFileExtension } from './app.rules'; describe('app.evaluators', () => { let context: TestRuleContext; @@ -540,6 +540,47 @@ describe('app.evaluators', () => { }); }); + describe('isKnowledgeRetrievalEnabled', () => { + it('should call context.appConfig.get with correct parameters', () => { + context.appConfig = { get: jasmine.createSpy() } as any; + + app.canDisplayKnowledgeRetrievalButton(context); + expect(context.appConfig.get).toHaveBeenCalledWith('plugins.knowledgeRetrievalEnabled', true); + }); + + it('should return false if get from appConfig returns false', () => { + expect( + app.canDisplayKnowledgeRetrievalButton({ + appConfig: { + get: () => false + } + } as any) + ).toBeFalse(); + }); + + it('should return true if get from appConfig returns true and navigation is correct', () => { + expect( + app.canDisplayKnowledgeRetrievalButton({ + navigation: { url: '/personal-files' }, + appConfig: { + get: () => true + } + } as any) + ).toBeTrue(); + }); + + it('should return false if get from appConfig returns true, but navigation is not correct', () => { + expect( + app.canDisplayKnowledgeRetrievalButton({ + navigation: { url: '/my-special-files' }, + appConfig: { + get: () => true + } + } as any) + ).toBeFalse(); + }); + }); + describe('isContentServiceEnabled', () => { it('should call context.appConfig.get with correct parameters', () => { context.appConfig = { get: jasmine.createSpy() } as any; diff --git a/projects/aca-shared/rules/src/app.rules.ts b/projects/aca-shared/rules/src/app.rules.ts index d97b5f105..1b0db6e7b 100644 --- a/projects/aca-shared/rules/src/app.rules.ts +++ b/projects/aca-shared/rules/src/app.rules.ts @@ -629,3 +629,11 @@ export function isSmartFolder(context: RuleContext): boolean { export const areTagsEnabled = (context: AcaRuleContext): boolean => context.appConfig.get('plugins.tagsEnabled', true); export const areCategoriesEnabled = (context: AcaRuleContext): boolean => context.appConfig.get('plugins.categoriesEnabled', true); + +export const canDisplayKnowledgeRetrievalButton = (context: AcaRuleContext): boolean => + context.appConfig.get('plugins.knowledgeRetrievalEnabled', false) && + (navigation.isPersonalFiles(context) || + navigation.isSharedFiles(context) || + navigation.isRecentFiles(context) || + navigation.isFavorites(context) || + ((navigation.isSearchResults(context) || navigation.isLibraryContent(context)) && navigation.isNotLibraries(context))); diff --git a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts index f404b68f3..1e8b88132 100644 --- a/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts +++ b/projects/aca-shared/src/lib/components/document-base-page/document-base-page.component.ts @@ -22,7 +22,14 @@ * from Hyland Software. If not, see . */ -import { DocumentListComponent, DocumentListService, ShareDataRow, UploadService } from '@alfresco/adf-content-services'; +import { + DocumentListComponent, + DocumentListService, + SearchAiInputState, + SearchAiService, + ShareDataRow, + UploadService +} from '@alfresco/adf-content-services'; import { ShowHeaderMode } from '@alfresco/adf-core'; import { ContentActionRef, DocumentListPresetRef, SelectionState } from '@alfresco/adf-extensions'; import { OnDestroy, OnInit, OnChanges, ViewChild, SimpleChanges, Directive, inject, HostListener } from '@angular/core'; @@ -81,8 +88,17 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { protected router = inject(Router); private autoDownloadService = inject(AutoDownloadService, { optional: true }); + protected searchAiService: SearchAiService = inject(SearchAiService); protected subscriptions: Subscription[] = []; + private _searchAiInputState: SearchAiInputState = { + active: false + }; + + get searchAiInputState(): SearchAiInputState { + return this._searchAiInputState; + } + ngOnInit() { this.extensions .getCreateActions() @@ -135,6 +151,10 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { .subscribe((result) => { this.isSmallScreen = result.matches; }); + + this.searchAiService.toggleSearchAiInput$ + .pipe(takeUntil(this.onDestroy$)) + .subscribe((searchAiInputState) => (this._searchAiInputState = searchAiInputState)); } ngOnChanges(changes: SimpleChanges) { diff --git a/projects/aca-shared/store/src/actions/search-ai.actions.ts b/projects/aca-shared/store/src/actions/search-ai.actions.ts new file mode 100644 index 000000000..e4d54683e --- /dev/null +++ b/projects/aca-shared/store/src/actions/search-ai.actions.ts @@ -0,0 +1,42 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +import { Action } from '@ngrx/store'; +import { AiSearchByTermPayload } from '../models/ai-search-by-term-payload'; + +export enum SearchAiActionTypes { + SearchByTermAi = 'SEARCH_BY_TERM_AI', + ToggleAiSearchInput = 'TOGGLE_AI_SEARCH_INPUT' +} + +export class SearchByTermAiAction implements Action { + readonly type = SearchAiActionTypes.SearchByTermAi; + constructor(public payload: AiSearchByTermPayload) {} +} + +export class ToggleAISearchInput implements Action { + readonly type = SearchAiActionTypes.ToggleAiSearchInput; + + constructor(public agentId: string) {} +} diff --git a/projects/aca-shared/store/src/models/ai-search-by-term-payload.ts b/projects/aca-shared/store/src/models/ai-search-by-term-payload.ts new file mode 100644 index 000000000..696d555a3 --- /dev/null +++ b/projects/aca-shared/store/src/models/ai-search-by-term-payload.ts @@ -0,0 +1,28 @@ +/*! + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Alfresco Example Content Application + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * from Hyland Software. If not, see . + */ + +export interface AiSearchByTermPayload { + searchTerm: string; + agentId: string; +} diff --git a/projects/aca-shared/store/src/public-api.ts b/projects/aca-shared/store/src/public-api.ts index e23673eaf..b6ef1adba 100644 --- a/projects/aca-shared/store/src/public-api.ts +++ b/projects/aca-shared/store/src/public-api.ts @@ -37,10 +37,12 @@ export * from './actions/viewer.actions'; export * from './actions/metadata-aspect.actions'; export * from './actions/template.actions'; export * from './actions/contextmenu.actions'; +export * from './actions/search-ai.actions'; export * from './effects/router.effects'; export * from './effects/snackbar.effects'; +export * from './models/ai-search-by-term-payload'; export * from './models/delete-status.model'; export * from './models/deleted-node-info.model'; export * from './models/node-info.model';