From a93722bea63f1cd52d5222595e90bc21e4ae7371 Mon Sep 17 00:00:00 2001
From: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com>
Date: Fri, 27 Sep 2024 09:49:47 +0200
Subject: [PATCH] [ACS-8833] Displaying error page when there is no selected
 nodes (#4142)

---
 .../search-ai-results.component.spec.ts       | 51 ++++++++++++++++++-
 .../search-ai-results.component.ts            |  7 +--
 2 files changed, 53 insertions(+), 5 deletions(-)

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
index ab6def5334..6feed0e8ad 100644
--- 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
@@ -27,7 +27,7 @@ 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 { EmptyContentComponent, UnsavedChangesGuard, 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';
@@ -40,6 +40,7 @@ import { SearchAiInputComponent } from '../search-ai-input/search-ai-input.compo
 import { MockStore, provideMockStore } from '@ngrx/store/testing';
 import { getAppSelection, getCurrentFolder, ViewNodeAction } from '@alfresco/aca-shared/store';
 import { ViewerService } from '@alfresco/aca-content/viewer';
+import { DebugElement } from '@angular/core';
 
 const questionMock: QuestionModel = { question: 'test', questionId: 'testId', restrictionQuery: { nodesIds: [] } };
 const aiAnswerMock: AiAnswer = { answer: 'Some answer', questionId: 'some id', references: [] };
@@ -57,6 +58,7 @@ describe('SearchAiResultsComponent', () => {
   let searchAiService: SearchAiService;
   let store: MockStore;
   let viewerService: ViewerService;
+  let unsavedChangesGuard: UnsavedChangesGuard;
 
   afterEach(() => {
     store.resetSelectors();
@@ -92,6 +94,7 @@ describe('SearchAiResultsComponent', () => {
     searchAiService = TestBed.inject(SearchAiService);
     userPreferencesService = TestBed.inject(UserPreferencesService);
     viewerService = TestBed.inject(ViewerService);
+    unsavedChangesGuard = TestBed.inject(UnsavedChangesGuard);
     store = TestBed.inject(MockStore);
     store.overrideSelector(getAppSelection, {
       nodes: [],
@@ -107,6 +110,8 @@ describe('SearchAiResultsComponent', () => {
   });
 
   describe('query params change', () => {
+    const getEmptyContentElement = (): DebugElement => fixture.debugElement.query(By.directive(EmptyContentComponent));
+
     it('should perform ai search and sets agents on query params change', () => {
       spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
       mockQueryParams.next({ query: 'test', agentId: 'agentId1' });
@@ -212,6 +217,27 @@ describe('SearchAiResultsComponent', () => {
       expect(component.hasAnsweringError).toBeFalse();
     }));
 
+    it('should render empty content when there are not selected nodes', () => {
+      mockQueryParams.next({
+        query: 'test',
+        agentId: 'agentId1'
+      });
+
+      fixture.detectChanges();
+      expect(getEmptyContentElement()).not.toBeNull();
+    });
+
+    it('should not render empty content when there are selected nodes', () => {
+      spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
+      mockQueryParams.next({
+        query: 'test',
+        agentId: 'agentId1'
+      });
+
+      fixture.detectChanges();
+      expect(getEmptyContentElement()).toBeNull();
+    });
+
     describe('when query params contains location', () => {
       let params: Params;
 
@@ -236,7 +262,7 @@ describe('SearchAiResultsComponent', () => {
         });
 
         fixture.detectChanges();
-        expect(fixture.debugElement.query(By.directive(EmptyContentComponent))).toBeNull();
+        expect(getEmptyContentElement()).toBeNull();
       });
 
       it('should not display search query', () => {
@@ -368,5 +394,26 @@ describe('SearchAiResultsComponent', () => {
 
       expect(nodesOrder).toEqual(['node1', 'node2']);
     });
+
+    it('should set unsaved on UnsavedChangesGuard to false when there are no selected nodes', () => {
+      mockQueryParams.next({
+        query: 'test',
+        agentId: 'agentId1'
+      });
+
+      component.ngOnInit();
+      expect(unsavedChangesGuard.unsaved).toBeFalse();
+    });
+
+    it('should set unsaved on UnsavedChangesGuard to true when there are selected nodes', () => {
+      spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
+      mockQueryParams.next({
+        query: 'test',
+        agentId: 'agentId1'
+      });
+
+      component.ngOnInit();
+      expect(unsavedChangesGuard.unsaved).toBeTrue();
+    });
   });
 });
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
index 882d21a76e..60bb0017b3 100644
--- 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
@@ -147,16 +147,17 @@ export class SearchAiResultsComponent extends PageComponent implements OnInit, O
       .subscribe((params) => {
         this._agentId = params.agentId;
         this._searchQuery = params.query ? decodeURIComponent(params.query) : '';
-        if (!this.searchQuery || !this.agentId) {
+        const selectedNodesState = this.userPreferencesService.get('knowledgeRetrievalNodes');
+        if (!this.searchQuery || !this.agentId || !selectedNodesState) {
           this._hasError = true;
           return;
         }
-        this._selectedNodesState = JSON.parse(this.userPreferencesService.get('knowledgeRetrievalNodes'));
+        this._selectedNodesState = JSON.parse(selectedNodesState);
         this.performAiSearch();
       });
     super.ngOnInit();
 
-    this.unsavedChangesGuard.unsaved = this.route.snapshot?.queryParams?.query?.length > 0;
+    this.unsavedChangesGuard.unsaved = this.route.snapshot?.queryParams?.query?.length > 0 && !this.hasError;
     this.unsavedChangesGuard.data = {
       descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.CONVERSATION_DISCARDED',
       confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.OKAY',