mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-09-17 14:21:14 +00:00
[ACS-8695] Getting Agent avatar
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
[attr.data-automation-id]="'aca-agents-button-agent-' + agent.id"
|
||||
[value]="agent">
|
||||
<div class="aca-agents-button-menu-list-agent-content">
|
||||
<adf-avatar [src]="agent?.avatar" [initials]="initialsByAgentId[agent.id]"></adf-avatar>
|
||||
<adf-avatar [src]="agent?.avatarUrl" [initials]="initialsByAgentId[agent.id]"></adf-avatar>
|
||||
<span class="aca-agents-button-menu-list-agent-content-name" [matTooltip]="agent.name" [matTooltipPosition]="'right'">
|
||||
{{ agent.name }}
|
||||
</span>
|
||||
|
@@ -25,7 +25,6 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AgentsButtonComponent } from './agents-button.component';
|
||||
import { AgentService, ContentTestingModule, SearchAiService } from '@alfresco/adf-content-services';
|
||||
import { AgentWithAvatar, KnowledgeRetrievalConfigEntry } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { MockStore, provideMockStore } from '@ngrx/store/testing';
|
||||
@@ -40,12 +39,14 @@ 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 } from '@alfresco/js-api';
|
||||
import { KnowledgeRetrievalConfigEntry } from '@alfresco/js-api/typings';
|
||||
|
||||
describe('AgentsButtonComponent', () => {
|
||||
let component: AgentsButtonComponent;
|
||||
let fixture: ComponentFixture<AgentsButtonComponent>;
|
||||
let agents$: Subject<AgentWithAvatar[]>;
|
||||
let agentsWithAvatar: AgentWithAvatar[];
|
||||
let agents$: Subject<Agent[]>;
|
||||
let agentsWithAvatar: Agent[];
|
||||
let checkSearchAvailabilitySpy: jasmine.Spy<(selectedNodesState: SelectionState, maxSelectedNodes?: number) => string>;
|
||||
let selectionState: SelectionState;
|
||||
let store: MockStore;
|
||||
@@ -66,20 +67,20 @@ describe('AgentsButtonComponent', () => {
|
||||
fixture = TestBed.createComponent(AgentsButtonComponent);
|
||||
component = fixture.componentInstance;
|
||||
store = TestBed.inject(MockStore);
|
||||
agents$ = new Subject<AgentWithAvatar[]>();
|
||||
agents$ = new Subject<Agent[]>();
|
||||
spyOn(TestBed.inject(AgentService), 'getAgents').and.returnValue(agents$);
|
||||
agentsWithAvatar = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'HR Agent',
|
||||
description: 'Test 1',
|
||||
avatar: undefined
|
||||
avatarUrl: undefined
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Policy Agent',
|
||||
description: 'Test 2',
|
||||
avatar: undefined
|
||||
avatarUrl: undefined
|
||||
}
|
||||
];
|
||||
const searchAiService = TestBed.inject(SearchAiService);
|
||||
@@ -200,7 +201,9 @@ describe('AgentsButtonComponent', () => {
|
||||
expect(notificationServiceSpy).toHaveBeenCalledWith('KNOWLEDGE_RETRIEVAL.SEARCH.ERRORS.HX_INSIGHT_URL_FETCHING');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button actions', () => {
|
||||
['mouseup', 'keydown'].forEach((eventName) => {
|
||||
describe(`${eventName} event`, () => {
|
||||
let event: Event;
|
||||
@@ -322,7 +325,7 @@ describe('AgentsButtonComponent', () => {
|
||||
describe('Agents menu', () => {
|
||||
let loader: HarnessLoader;
|
||||
|
||||
const prepareData = (agents: AgentWithAvatar[]): void => {
|
||||
const prepareData = (agents: Agent[]): void => {
|
||||
config$.next({
|
||||
entry: {
|
||||
knowledgeRetrievalUrl
|
||||
@@ -340,14 +343,25 @@ describe('AgentsButtonComponent', () => {
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
it('should have assigned before to xPosition', () => {
|
||||
const getAvatar = (agentId: string): AvatarComponent =>
|
||||
fixture.debugElement.query(By.css(`[data-automation-id=aca-agents-button-agent-${agentId}]`)).query(By.directive(AvatarComponent))
|
||||
.componentInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
prepareData(agentsWithAvatar);
|
||||
agents$.complete();
|
||||
|
||||
expect(getMenu().xPosition).toBe('before');
|
||||
});
|
||||
|
||||
describe('Agents list', () => {
|
||||
describe('Agents position', () => {
|
||||
it('should have assigned before to xPosition', () => {
|
||||
prepareData(agentsWithAvatar);
|
||||
agents$.complete();
|
||||
|
||||
expect(getMenu().xPosition).toBe('before');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Agents multi words name', () => {
|
||||
const getAgentsListHarness = async (): Promise<MatSelectionListHarness> =>
|
||||
(await loader.getHarness(MatMenuHarness)).getHarness(MatSelectionListHarness);
|
||||
|
||||
@@ -358,76 +372,65 @@ describe('AgentsButtonComponent', () => {
|
||||
|
||||
const getAgentsList = (): MatSelectionList => fixture.debugElement.query(By.directive(MatSelectionList)).componentInstance;
|
||||
|
||||
const getAvatar = (agentId: string): AvatarComponent =>
|
||||
fixture.debugElement.query(By.css(`[data-automation-id=aca-agents-button-agent-${agentId}]`)).query(By.directive(AvatarComponent))
|
||||
.componentInstance;
|
||||
it('should deselect selected agent after selecting other', async () => {
|
||||
component.data = {
|
||||
trigger: SearchAiActionTypes.ToggleAiSearchInput
|
||||
};
|
||||
const selectionList = getAgentsList();
|
||||
spyOn(selectionList, 'deselectAll');
|
||||
await selectAgent();
|
||||
|
||||
describe('Agents multi words name', () => {
|
||||
beforeEach(() => {
|
||||
prepareData(agentsWithAvatar);
|
||||
agents$.complete();
|
||||
});
|
||||
expect(selectionList.deselectAll).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should deselect selected agent after selecting other', async () => {
|
||||
component.data = {
|
||||
trigger: SearchAiActionTypes.ToggleAiSearchInput
|
||||
};
|
||||
const selectionList = getAgentsList();
|
||||
spyOn(selectionList, 'deselectAll');
|
||||
await selectAgent();
|
||||
it('should dispatch on store selected agent', async () => {
|
||||
component.data = {
|
||||
trigger: SearchAiActionTypes.ToggleAiSearchInput
|
||||
};
|
||||
spyOn(store, 'dispatch');
|
||||
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<ToggleAISearchInput>).toHaveBeenCalledWith({
|
||||
type: SearchAiActionTypes.ToggleAiSearchInput,
|
||||
agentId: '2'
|
||||
});
|
||||
});
|
||||
|
||||
it('should disallow selecting multiple agents', () => {
|
||||
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');
|
||||
expect(store.dispatch<ToggleAISearchInput>).toHaveBeenCalledWith({
|
||||
type: SearchAiActionTypes.ToggleAiSearchInput,
|
||||
agentId: '2'
|
||||
});
|
||||
});
|
||||
|
||||
describe('Agents single word name', () => {
|
||||
it('should assign correct initials to each avatar for each agent with single section name', () => {
|
||||
agentsWithAvatar[0].name = 'Adam';
|
||||
agentsWithAvatar[1].name = 'Bob';
|
||||
prepareData(agentsWithAvatar);
|
||||
it('should disallow selecting multiple agents', () => {
|
||||
expect(getAgentsList().multiple).toBeFalse();
|
||||
});
|
||||
|
||||
expect(getAvatar('1').initials).toBe('A');
|
||||
expect(getAvatar('2').initials).toBe('B');
|
||||
});
|
||||
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 single word name', () => {
|
||||
it('should assign correct initials to each avatar for each agent with single section name', () => {
|
||||
agentsWithAvatar[0].name = 'Adam';
|
||||
agentsWithAvatar[1].name = 'Bob';
|
||||
prepareData(agentsWithAvatar);
|
||||
|
||||
expect(getAvatar('1').initials).toBe('A');
|
||||
expect(getAvatar('2').initials).toBe('B');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -33,7 +33,7 @@ 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 { AgentWithAvatar } from '@alfresco/js-api';
|
||||
import { Agent } from '@alfresco/js-api';
|
||||
import { AgentService, SearchAiService } from '@alfresco/adf-content-services';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
||||
@@ -51,13 +51,13 @@ export class AgentsButtonComponent implements OnInit, OnDestroy {
|
||||
data: { trigger: string };
|
||||
|
||||
private selectedNodesState: SelectionState;
|
||||
private _agents: AgentWithAvatar[] = [];
|
||||
private _agents: Agent[] = [];
|
||||
private onDestroy$ = new Subject<void>();
|
||||
private _disabled = true;
|
||||
private _initialsByAgentId: { [key: string]: string } = {};
|
||||
private _hxInsightUrl: string;
|
||||
|
||||
get agents(): AgentWithAvatar[] {
|
||||
get agents(): Agent[] {
|
||||
return this._agents;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
[hideSingleSelectionIndicator]="true">
|
||||
<mat-select-trigger class="aca-search-ai-input-agent-select-displayed-value">
|
||||
<adf-avatar
|
||||
[src]="agentControl.value?.avatar"
|
||||
[src]="agentControl.value?.avatarUrl"
|
||||
[initials]="initialsByAgentId[agentControl.value?.id]"
|
||||
size="26px">
|
||||
</adf-avatar>
|
||||
@@ -18,7 +18,7 @@
|
||||
[value]="agent"
|
||||
class="aca-search-ai-input-agent-select-options-option"
|
||||
[attr.data-automation-id]="'aca-search-ai-input-agent-' + agent.id"><div class="aca-search-ai-input-agent-select-options-option-content">
|
||||
<adf-avatar [src]="agent?.avatar" [initials]="initialsByAgentId[agent.id]"></adf-avatar>
|
||||
<adf-avatar [src]="agent?.avatarUrl" [initials]="initialsByAgentId[agent.id]"></adf-avatar>
|
||||
<span class="aca-search-ai-input-agent-select-options-option-content-text" [matTooltip]="agent.name" [matTooltipPosition]="'right'">{{ agent.name }}</span>
|
||||
</div>
|
||||
</mat-option>
|
||||
@@ -29,7 +29,7 @@
|
||||
<mat-card-title class="aca-search-ai-input-agent-popup-hover-card-container-title">
|
||||
<adf-avatar
|
||||
[initials]="initialsByAgentId[agentControl.value?.id]"
|
||||
[src]="agentControl.value?.avatar"
|
||||
[src]="agentControl.value?.avatarUrl"
|
||||
size="50px">
|
||||
</adf-avatar>
|
||||
<span class="aca-search-ai-input-agent-popup-hover-card-container-title-name"
|
||||
|
@@ -30,7 +30,7 @@ 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 { AgentWithAvatar, NodeEntry } from '@alfresco/js-api';
|
||||
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';
|
||||
@@ -47,18 +47,18 @@ import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dial
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ModalAiService } from '../../../../services/modal-ai.service';
|
||||
|
||||
const agentWithAvatarList: AgentWithAvatar[] = [
|
||||
const agentList: Agent[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'HR Agent',
|
||||
description: 'Test 1',
|
||||
avatar: undefined
|
||||
avatarUrl: undefined
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Policy Agent',
|
||||
description: 'Test 2',
|
||||
avatar: undefined
|
||||
avatarUrl: undefined
|
||||
}
|
||||
];
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('SearchAiInputComponent', () => {
|
||||
let loader: HarnessLoader;
|
||||
let selectionState: SelectionState;
|
||||
let store: MockStore;
|
||||
let agents$: Subject<AgentWithAvatar[]>;
|
||||
let agents$: Subject<Agent[]>;
|
||||
let dialog: MatDialog;
|
||||
|
||||
const prepareBeforeTest = (): void => {
|
||||
@@ -104,7 +104,7 @@ describe('SearchAiInputComponent', () => {
|
||||
component = fixture.componentInstance;
|
||||
store = TestBed.inject(MockStore);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
agents$ = new Subject<AgentWithAvatar[]>();
|
||||
agents$ = new Subject<Agent[]>();
|
||||
dialog = TestBed.inject(MatDialog);
|
||||
spyOn(TestBed.inject(AgentService), 'getAgents').and.returnValue(agents$);
|
||||
prepareBeforeTest();
|
||||
@@ -129,9 +129,9 @@ describe('SearchAiInputComponent', () => {
|
||||
});
|
||||
|
||||
it('should get agents on init', () => {
|
||||
agents$.next(agentWithAvatarList);
|
||||
agents$.next(agentList);
|
||||
component.ngOnInit();
|
||||
expect(component.agents).toEqual(agentWithAvatarList);
|
||||
expect(component.agents).toEqual(agentList);
|
||||
expect(component.initialsByAgentId).toEqual({ 1: 'HA', 2: 'PA' });
|
||||
expect(notificationServiceSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -146,7 +146,7 @@ describe('SearchAiInputComponent', () => {
|
||||
});
|
||||
|
||||
it('should have selected correct agent', async () => {
|
||||
agents$.next(agentWithAvatarList);
|
||||
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');
|
||||
@@ -161,7 +161,7 @@ describe('SearchAiInputComponent', () => {
|
||||
.componentInstance;
|
||||
|
||||
beforeEach(async () => {
|
||||
agents$.next(agentWithAvatarList);
|
||||
agents$.next(agentList);
|
||||
const selectHarness = await loader.getHarness(MatSelectHarness);
|
||||
await selectHarness.open();
|
||||
options = await selectHarness.getOptions();
|
||||
@@ -187,11 +187,11 @@ describe('SearchAiInputComponent', () => {
|
||||
});
|
||||
|
||||
it('should assign correct initials to each avatar for each agent with single section name', () => {
|
||||
const newAgentWithAvatarList = [
|
||||
{ ...agentWithAvatarList[0], name: 'Adam' },
|
||||
{ ...agentWithAvatarList[1], name: 'Bob' }
|
||||
const newAgentList = [
|
||||
{ ...agentList[0], name: 'Adam' },
|
||||
{ ...agentList[1], name: 'Bob' }
|
||||
];
|
||||
agents$.next(newAgentWithAvatarList);
|
||||
agents$.next(newAgentList);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getAvatarForAgent('1').initials).toBe('A');
|
||||
@@ -205,7 +205,7 @@ describe('SearchAiInputComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
queryInput = fixture.debugElement.query(By.directive(MatInput));
|
||||
agents$.next(agentWithAvatarList);
|
||||
agents$.next(agentList);
|
||||
});
|
||||
|
||||
it('should have assigned formControl', () => {
|
||||
@@ -230,7 +230,7 @@ describe('SearchAiInputComponent', () => {
|
||||
beforeEach(async () => {
|
||||
submitButton = fixture.debugElement.query(By.directive(MatButton));
|
||||
queryInput = await loader.getHarness(MatInputHarness);
|
||||
agents$.next(agentWithAvatarList);
|
||||
agents$.next(agentList);
|
||||
});
|
||||
|
||||
it('should be disabled by default', () => {
|
||||
|
@@ -38,7 +38,6 @@ import { AiSearchByTermPayload, AppStore, getAppSelection, SearchByTermAiAction
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { SelectionState } from '@alfresco/adf-extensions';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { AgentWithAvatar } from '@alfresco/js-api';
|
||||
import { AgentService, SearchAiService } from '@alfresco/adf-content-services';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import {
|
||||
@@ -48,6 +47,7 @@ import {
|
||||
MatTooltipModule
|
||||
} from '@angular/material/tooltip';
|
||||
import { ModalAiService } from '../../../../services/modal-ai.service';
|
||||
import { Agent } from '@alfresco/js-api/typings';
|
||||
|
||||
const MatTooltipOptions: MatTooltipDefaultOptions = {
|
||||
...MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY(),
|
||||
@@ -93,18 +93,18 @@ export class SearchAiInputComponent implements OnInit, OnDestroy {
|
||||
|
||||
private readonly storedNodesKey = 'knowledgeRetrievalNodes';
|
||||
|
||||
private _agentControl = new FormControl<AgentWithAvatar>(null);
|
||||
private _agents: AgentWithAvatar[] = [];
|
||||
private _agentControl = new FormControl<Agent>(null);
|
||||
private _agents: Agent[] = [];
|
||||
private onDestroy$ = new Subject<void>();
|
||||
private selectedNodesState: SelectionState;
|
||||
private _queryControl = new FormControl('');
|
||||
private _initialsByAgentId: { [key: string]: string } = {};
|
||||
|
||||
get agentControl(): FormControl<AgentWithAvatar> {
|
||||
get agentControl(): FormControl<Agent> {
|
||||
return this._agentControl;
|
||||
}
|
||||
|
||||
get agents(): AgentWithAvatar[] {
|
||||
get agents(): Agent[] {
|
||||
return this._agents;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user