UNPKG

@progress/kendo-angular-grid

Version:

Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.

273 lines (272 loc) 14 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Component, ViewChild, NgZone } from '@angular/core'; import { AIPromptComponent, OutputViewComponent, PromptViewComponent, AIPromptCustomMessagesComponent, AIPromptOutputTemplateDirective, AIPromptOutputBodyTemplateDirective } from '@progress/kendo-angular-conversational-ui'; import { HttpClient, HttpRequest } from '@angular/common/http'; import { ContextService } from './../../../../common/provider.service'; import { ColumnInfoService } from './../../../../common/column-info.service'; import { GridAIAssistantResponseSuccessEvent, GridAIAssistantResponseErrorEvent } from './models'; import { GridAIRequestResponseService } from './ai-request-response.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common/http"; import * as i2 from "./../../../../common/provider.service"; import * as i3 from "./../../../../common/column-info.service"; import * as i4 from "./ai-request-response.service"; /** * @hidden */ export class AiAssistantComponent { http; ctx; columnInfoService; zone; aiRequestResponseService; aiPrompt; activeView = 0; requestUrl; requestOptions; aiPromptSettings; aiToolDirective; streaming = false; disabledGenerateButton = false; lastMessage; requestData; currentRequestSubscription = null; //Remove this when the AI Assistant has a built-in loading indicator loadingOutput = { id: 'k-loading-item', output: '', prompt: '' }; // flat columns used for highlight utilities (expects { field }) columns = []; leafColumns = []; idCounter = 0; constructor(http, ctx, columnInfoService, zone, aiRequestResponseService) { this.http = http; this.ctx = ctx; this.columnInfoService = columnInfoService; this.zone = zone; this.aiRequestResponseService = aiRequestResponseService; } ngAfterViewInit() { // Preserve a flat columns array (fields) for highlight utilities. // Use leafNamedColumns as the canonical list of leaf columns with display titles. this.leafColumns = this.columnInfoService.leafNamedColumns || []; this.columns = this.leafColumns.map((col) => ({ field: col.field })); } ngOnDestroy() { this.unsubscribeCurrentRequest(); } message(message) { return this.ctx.localization.get(message); } cancelRequest() { this.aiToolDirective.cancelRequest.emit(); this.unsubscribeCurrentRequest(); this.streaming = false; } onPromptRequest(ev) { if (this.aiToolDirective.promptOutputs.length === 0) { this.aiToolDirective.promptOutputs.push(this.loadingOutput); } this.unsubscribeCurrentRequest(); this.streaming = true; this.activeView = 1; if (ev.prompt) { this.lastMessage = ev.prompt; } this.requestData = { columns: [], // Will be populated by service promptMessage: ev.prompt, url: this.requestUrl, requestOptions: { ...this.requestOptions } }; if (!this.requestOptions.body) { this.requestData.requestOptions.body = this.aiRequestResponseService.buildRequestBody(this.requestData.promptMessage, this.requestData.requestOptions.role); } this.aiToolDirective.promptRequest.emit({ requestData: this.requestData, isRetry: ev.isRetry }); if (!this.requestUrl) { return; } this.currentRequestSubscription = this.sendPromptRequest().subscribe((res) => { if (res.body) { this.processResponse(res); this.streaming = false; } this.currentRequestSubscription = null; }, (error) => { this.handleError(error); this.streaming = false; this.currentRequestSubscription = null; }); } sendPromptRequest() { const request = new HttpRequest(this.requestData.requestOptions.method, this.requestData.url, this.requestData.requestOptions.body, this.requestData.requestOptions); return this.http.request(request); } processResponse(response) { if (this.aiToolDirective.autoClose) { this.aiToolDirective.emitOpenClose = true; this.aiToolDirective.toggleWindow(); } const responseBody = response.body || { commands: [] }; const responseSuccessEvent = new GridAIAssistantResponseSuccessEvent(response); this.aiToolDirective.responseSuccess.emit(responseSuccessEvent); if (responseSuccessEvent.isDefaultPrevented()) { this.deleteLoadingOutput(); return; } const messages = []; if (responseBody.message) { messages.push(responseBody.message); } const commandMessages = this.aiRequestResponseService.processCommands(responseBody.commands || [], this.columns, this.leafColumns); messages.push(...commandMessages); const responseContentStart = [`${this.ctx.localization.get('aiAssistantOutputCardBodyContent')} \n`]; const responseContentBody = messages .map((output, idx) => `${idx + 1} ${output}`) .join('\n'); const output = { id: this.idCounter++, title: this.ctx.localization.get('aiAssistantOutputCardTitle'), prompt: this.lastMessage, output: responseContentStart.concat(responseContentBody).join(''), }; this.deleteLoadingOutput(); this.aiToolDirective.promptOutputs.unshift(output); } handleError(error) { const responseErrorEvent = new GridAIAssistantResponseErrorEvent(error); this.aiToolDirective.responseError.emit(responseErrorEvent); if (responseErrorEvent.isDefaultPrevented()) { this.deleteLoadingOutput(); return; } const output = { id: this.idCounter++, prompt: this.lastMessage, output: error.message }; this.deleteLoadingOutput(); this.aiToolDirective.promptOutputs.unshift(output); } deleteLoadingOutput() { if (this.aiToolDirective.promptOutputs[0]?.id === this.loadingOutput.id) { this.aiToolDirective.promptOutputs.splice(0, 1); } } unsubscribeCurrentRequest() { if (this.currentRequestSubscription) { this.currentRequestSubscription.unsubscribe(); this.currentRequestSubscription = null; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AiAssistantComponent, deps: [{ token: i1.HttpClient }, { token: i2.ContextService }, { token: i3.ColumnInfoService }, { token: i0.NgZone }, { token: i4.GridAIRequestResponseService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AiAssistantComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "aiPrompt", first: true, predicate: AIPromptComponent, descendants: true }], ngImport: i0, template: ` <kendo-aiprompt #aiPrompt [promptSuggestions]="aiPromptSettings?.promptSuggestions" [showOutputRating]="aiPromptSettings?.showOutputRating" [streaming]="streaming" [speechToTextButton]="aiPromptSettings?.speechToTextButton" [(activeView)]="activeView" [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon" [generateButtonIcon]="aiPromptSettings?.generateButtonIcon" [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0" [promptOutputs]="aiPromptSettings?.promptOutputs" [textAreaSettings]="aiPromptSettings?.textAreaSettings" (promptRequest)="onPromptRequest($event)" (promptRequestCancel)="cancelRequest()" > <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view> <kendo-aiprompt-output-view></kendo-aiprompt-output-view> @if (streaming && aiPrompt.streaming; as output) { <ng-template kendoAIPromptOutputTemplate let-output> <div class="k-card"> <div class="k-card-header"> <div class="k-card-title"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span> </div> <div class="k-card-subtitle"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span> </div> </div> <div class="k-card-body"> <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span> </div> <div class="k-card-actions"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span> </div> </div> </ng-template> } @if (!(streaming && aiPrompt.streaming); as output) { <ng-template kendoAIPromptOutputBodyTemplate let-output> <p>{{output.output}}</p> </ng-template> } <kendo-aiprompt-messages [generateOutput]="message('aiAssistantApplyButtonText')" ></kendo-aiprompt-messages> </kendo-aiprompt> `, isInline: true, dependencies: [{ kind: "component", type: AIPromptComponent, selector: "kendo-aiprompt", inputs: ["activeView", "promptCommands", "promptSuggestions", "promptOutputs", "showOutputRating", "streaming", "speechToTextButton", "textAreaSettings", "generateButtonSVGIcon", "generateButtonIcon", "disabledGenerateButton"], outputs: ["activeViewChange", "promptRequest", "commandExecute", "outputCopy", "outputRatingChange", "promptRequestCancel"], exportAs: ["kendoAIPrompt"] }, { kind: "component", type: AIPromptCustomMessagesComponent, selector: "kendo-aiprompt-messages" }, { kind: "component", type: PromptViewComponent, selector: "kendo-aiprompt-prompt-view" }, { kind: "component", type: OutputViewComponent, selector: "kendo-aiprompt-output-view" }, { kind: "directive", type: AIPromptOutputTemplateDirective, selector: "[kendoAIPromptOutputTemplate]" }, { kind: "directive", type: AIPromptOutputBodyTemplateDirective, selector: "[kendoAIPromptOutputBodyTemplate]" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AiAssistantComponent, decorators: [{ type: Component, args: [{ standalone: true, imports: [AIPromptComponent, AIPromptCustomMessagesComponent, PromptViewComponent, OutputViewComponent, AIPromptOutputTemplateDirective, AIPromptOutputBodyTemplateDirective], template: ` <kendo-aiprompt #aiPrompt [promptSuggestions]="aiPromptSettings?.promptSuggestions" [showOutputRating]="aiPromptSettings?.showOutputRating" [streaming]="streaming" [speechToTextButton]="aiPromptSettings?.speechToTextButton" [(activeView)]="activeView" [generateButtonSVGIcon]="aiPromptSettings?.generateButtonSVGIcon" [generateButtonIcon]="aiPromptSettings?.generateButtonIcon" [disabledGenerateButton]="disabledGenerateButton || promptView.textAreaValue?.length === 0" [promptOutputs]="aiPromptSettings?.promptOutputs" [textAreaSettings]="aiPromptSettings?.textAreaSettings" (promptRequest)="onPromptRequest($event)" (promptRequestCancel)="cancelRequest()" > <kendo-aiprompt-prompt-view #promptView></kendo-aiprompt-prompt-view> <kendo-aiprompt-output-view></kendo-aiprompt-output-view> @if (streaming && aiPrompt.streaming; as output) { <ng-template kendoAIPromptOutputTemplate let-output> <div class="k-card"> <div class="k-card-header"> <div class="k-card-title"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" [style.width.px]="200"></span> </div> <div class="k-card-subtitle"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span> </div> </div> <div class="k-card-body"> <span class="k-skeleton k-skeleton-rect k-skeleton-pulse" style="height: 80px;"></span> </div> <div class="k-card-actions"> <span class="k-skeleton k-skeleton-text k-skeleton-pulse" style="width: 100%;"></span> </div> </div> </ng-template> } @if (!(streaming && aiPrompt.streaming); as output) { <ng-template kendoAIPromptOutputBodyTemplate let-output> <p>{{output.output}}</p> </ng-template> } <kendo-aiprompt-messages [generateOutput]="message('aiAssistantApplyButtonText')" ></kendo-aiprompt-messages> </kendo-aiprompt> ` }] }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ContextService }, { type: i3.ColumnInfoService }, { type: i0.NgZone }, { type: i4.GridAIRequestResponseService }], propDecorators: { aiPrompt: [{ type: ViewChild, args: [AIPromptComponent] }] } });