[ACS-8695] Getting Agent avatar

This commit is contained in:
Jacek Pluta
2024-09-10 10:17:01 +02:00
parent d3303a765c
commit 7a3209afb6
6 changed files with 105 additions and 102 deletions

View File

@@ -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>

View File

@@ -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();
};
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();
});
describe('Agents position', () => {
it('should have assigned before to xPosition', () => {
prepareData(agentsWithAvatar);
agents$.complete();
expect(getMenu().xPosition).toBe('before');
});
});
describe('Agents list', () => {
describe('Agents multi words name', () => {
const getAgentsListHarness = async (): Promise<MatSelectionListHarness> =>
(await loader.getHarness(MatMenuHarness)).getHarness(MatSelectionListHarness);
@@ -358,16 +372,6 @@ 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;
describe('Agents multi words name', () => {
beforeEach(() => {
prepareData(agentsWithAvatar);
agents$.complete();
});
it('should deselect selected agent after selecting other', async () => {
component.data = {
trigger: SearchAiActionTypes.ToggleAiSearchInput
@@ -431,4 +435,3 @@ describe('AgentsButtonComponent', () => {
});
});
});
});

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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', () => {

View File

@@ -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;
}