mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-09-17 14:21:14 +00:00
* [ACS-8399] Integrate all changes with backend * [ACS-8399] Integrate all changes with backend - review fixes
183 lines
6.3 KiB
TypeScript
183 lines
6.3 KiB
TypeScript
/*!
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
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 { AgentWithAvatar } from '@alfresco/js-api';
|
|
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';
|
|
|
|
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<void>();
|
|
|
|
private readonly storedNodesKey = 'knowledgeRetrievalNodes';
|
|
|
|
private _agentControl = new FormControl<AgentWithAvatar>(null);
|
|
private _agents: AgentWithAvatar[] = [];
|
|
private onDestroy$ = new Subject<void>();
|
|
private selectedNodesState: SelectionState;
|
|
private _queryControl = new FormControl('');
|
|
private _initialsByAgentId: { [key: string]: string } = {};
|
|
|
|
get agentControl(): FormControl<AgentWithAvatar> {
|
|
return this._agentControl;
|
|
}
|
|
|
|
get agents(): AgentWithAvatar[] {
|
|
return this._agents;
|
|
}
|
|
|
|
get queryControl(): FormControl<string> {
|
|
return this._queryControl;
|
|
}
|
|
|
|
get initialsByAgentId(): { [key: string]: string } {
|
|
return this._initialsByAgentId;
|
|
}
|
|
|
|
constructor(
|
|
private store: Store<AppStore>,
|
|
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) => {
|
|
this._agents = agents;
|
|
this.agentControl.setValue(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.showInfo(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();
|
|
}
|
|
}
|
|
}
|