[ACS-8210] Agent basic details popup (#9956)

This commit is contained in:
jacekpluta
2024-07-30 10:19:31 +02:00
committed by Aleksander Sklorz
parent 16e851e6b5
commit 8abc6d495d
9 changed files with 205 additions and 51 deletions

View File

@@ -15,49 +15,83 @@
* limitations under the License.
*/
import { AgentService } from './agent.service';
import { TestBed } from '@angular/core/testing';
import { AgentPaging } from '@alfresco/js-api';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { AlfrescoApiService, CoreTestingModule } from '@alfresco/adf-core';
import { Agent, AgentPaging, AgentsApi, AgentWithAvatar } from '@alfresco/js-api';
import { AgentService } from '@alfresco/adf-content-services';
const agent1: Agent = {
id: '1',
name: 'HR Agent',
description: 'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
};
const agent2: Agent = {
id: '2',
name: 'Policy Agent',
description: 'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
};
const agentPagingObjectMock: AgentPaging = {
list: {
entries: [
{
entry: agent1
},
{
entry: agent2
}
]
}
};
const avatarAgentMock = 'https://res.cloudinary.com/hyld/image/upload/f_auto,c_fill,g_auto,w_1400,h_730/v1/h2/hero/blue-shirt-woman';
const agentWithAvatarListMock: AgentWithAvatar[] = [
{
...agent1,
avatar: avatarAgentMock
},
{
...agent2,
avatar: avatarAgentMock
}
];
describe('AgentService', () => {
let service: AgentService;
let agentService: AgentService;
let apiService: AlfrescoApiService;
let agentsApi: AgentsApi;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
imports: [CoreTestingModule]
});
service = TestBed.inject(AgentService);
service.mocked = false;
agentService = TestBed.inject(AgentService);
apiService = TestBed.inject(AlfrescoApiService);
agentsApi = new AgentsApi(apiService.getInstance());
agentService.mocked = false;
spyOn(agentsApi, 'getAgentAvatar').and.returnValue(Promise.resolve(avatarAgentMock));
spyOn(agentService.agentsApi, 'getAgentAvatar').and.returnValue(Promise.resolve(avatarAgentMock));
});
describe('getAgents', () => {
it('should load agents', (done) => {
const paging: AgentPaging = {
list: {
entries: [
{
entry: {
id: '1',
name: 'HR Agent'
}
},
{
entry: {
id: '2',
name: 'Policy Agent'
}
}
]
}
};
spyOn(service.agentsApi, 'getAgents').and.returnValue(Promise.resolve(paging));
it('should load agents', (done) => {
spyOn(agentService.agentsApi, 'getAgents').and.returnValue(Promise.resolve(agentPagingObjectMock));
service.getAgents().subscribe((pagingResponse) => {
expect(pagingResponse).toBe(paging);
expect(service.agentsApi.getAgents).toHaveBeenCalled();
done();
});
agentService.getAgents().subscribe((pagingResponse) => {
expect(pagingResponse).toEqual(agentWithAvatarListMock);
expect(agentService.agentsApi.getAgents).toHaveBeenCalled();
done();
});
});
it('should get agent avatar', (done) => {
agentService.getAgentAvatar('avatarId').subscribe((response) => {
expect(response).toEqual(avatarAgentMock);
expect(agentService.agentsApi.getAgentAvatar).toHaveBeenCalledWith('avatarId');
done();
});
});
});

View File

@@ -16,9 +16,10 @@
*/
import { Injectable } from '@angular/core';
import { AgentPaging, AgentsApi } from '@alfresco/js-api';
import { AgentPaging, AgentsApi, AgentWithAvatar } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { from, Observable, of } from 'rxjs';
import { BehaviorSubject, forkJoin, from, Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
@@ -26,6 +27,7 @@ import { from, Observable, of } from 'rxjs';
export class AgentService {
private _agentsApi: AgentsApi;
private _mocked = true;
private agents = new BehaviorSubject<AgentWithAvatar[]>([]);
get agentsApi(): AgentsApi {
this._agentsApi = this._agentsApi ?? new AgentsApi(this.apiService.getInstance());
@@ -36,14 +38,42 @@ export class AgentService {
this._mocked = mocked;
}
agents$ = this.agents.asObservable();
constructor(private apiService: AlfrescoApiService) {}
/**
* Gets all agents from cache. If cache is empty, fetches agents from backend.
*
* @returns AgentWithAvatar[] list containing agents.
*/
getAgents(): Observable<AgentWithAvatar[]> {
return this.agents$.pipe(
switchMap((agentsList) => {
if (agentsList.length) {
return of(agentsList);
}
return this.getMockedAgents().pipe(
switchMap((paging) => {
const agents = paging.list.entries.map((agentEntry) => agentEntry.entry);
return forkJoin([of(agents), ...agents.map((agent) => this.getAgentAvatar(agent.id))]);
}),
switchMap(([agents, ...avatars]: [AgentWithAvatar[], string]) => {
const agentsWithAvatar = agents.map((agent, index) => ({ ...agent, avatar: avatars[index] }));
this.agents.next(agentsWithAvatar);
return of(agentsWithAvatar);
})
);
})
);
}
/**
* Gets all agents.
*
* @returns AgentPaging object containing the agents.
*/
getAgents(): Observable<AgentPaging> {
private getMockedAgents(): Observable<AgentPaging> {
return this._mocked
? of({
list: {
@@ -51,19 +81,17 @@ export class AgentService {
{
entry: {
id: '1',
name: 'HR Agent'
name: 'HR Agent',
description:
'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
}
},
{
entry: {
id: '2',
name: 'Policy Agent'
}
},
{
entry: {
id: '3',
name: 'Rules & Rates Agent'
name: 'Policy Agent',
description:
'Your Claims Doc Agent streamlines the extraction, analysis, and management of data from insurance claims documents.'
}
}
]
@@ -71,4 +99,16 @@ export class AgentService {
})
: from(this.agentsApi.getAgents());
}
/**
* Gets agent avatar by agent id.
*
* @param agentId agent unique id.
* @returns string with an image.
*/
getAgentAvatar(agentId: string): Observable<string> {
return this._mocked
? of('https://res.cloudinary.com/hyld/image/upload/f_auto,c_fill,g_auto,w_1400,h_730/v1/h2/hero/blue-shirt-woman')
: from(this._agentsApi.getAgentAvatar(agentId));
}
}

View File

@@ -32,4 +32,15 @@ export class AgentsApi extends BaseApi {
path: '/agents'
});
}
/**
* Gets agent avatar by id.
*
* @returns string with an image.
*/
getAgentAvatar(agentId: string): Promise<string> {
return this.get({
path: `/agents/${agentId}/avatars/-default-`
});
}
}

View File

@@ -1,8 +1,9 @@
# AgentsApi
| Method | HTTP request | Description |
|-------------------------|-----------------|------------------|
| [getAgents](#getAgents) | **GET** /agents | Gets all agents. |
| Method | HTTP request | Description |
|-----------------------------------|----------------------------------------------|--------------------------|
| [getAgents](#getAgents) | **GET** /agents | Gets all agents. |
| [getAgentAvatar](#getAgentAvatar) | **GET** /agents/${agentId}/avatars/-default- | Gets agent avatar by id. |
## getAgents
@@ -46,6 +47,31 @@ agentsApi.getAgents().then((agents) => {
**Return type**: [AgentPaging](#AgentPaging)
## getAgentAvatar
Gets agent avatar by agent id.
**Parameters**
| Name | Type |
|---------------|----------|
| **agentId** | string |
**Example**
```javascript
import { AlfrescoApi, AgentsApi } from '@alfresco/js-api';
const alfrescoApi = new AlfrescoApi(/*..*/);
const agentsApi = new AgentsApi(alfrescoApi);
agentsApi.getAgentAvatar('agentId').then((agentAvatarImage) => {
console.log('API called successfully. Returned data: ' + agentAvatarImage);
});
```
**Return type**: String
# Models
## AgentPaging
@@ -77,7 +103,8 @@ agentsApi.getAgents().then((agents) => {
**Properties**
| Name | Type |
|----------|--------|
| **id** | string |
| **name** | string |
| Name | Type |
|-----------------|--------|
| **id** | string |
| **name** | string |
| **description** | string |

View File

@@ -18,4 +18,5 @@
export interface Agent {
id: string;
name: string;
description: string;
}

View File

@@ -0,0 +1,22 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Agent } from './agent';
export interface AgentWithAvatar extends Agent {
avatar: string;
}

View File

@@ -28,6 +28,7 @@ export * from './activityEntry';
export * from './activityPaging';
export * from './activityPagingList';
export * from './agent';
export * from './agentWithAvatar';
export * from './agentEntry';
export * from './agentPaging';
export * from './agentPagingList';

View File

@@ -67,5 +67,17 @@ describe('AgentsApi', () => {
done();
});
});
describe('getAgentAvatar', () => {
it('should get agent avatar', (done) => {
const agentId = 'agentId';
agentMock.getAgentAvatar200Response(agentId);
agentsApi.getAgentAvatar(agentId).then((data) => {
assert.deepStrictEqual(data, { avatarImage: 'agentAvatarImageMock' });
done();
});
});
});
});
});

View File

@@ -47,4 +47,10 @@ export class AgentMock extends BaseMock {
}
});
}
getAgentAvatar200Response(agentId: string): void {
nock(this.host, { encodedQueryParams: true })
.get(`/alfresco/api/-default-/private/hxi/versions/1/agents/${agentId}/avatars/-default-`)
.reply(200, { avatarImage: 'agentAvatarImageMock' });
}
}