diff options
Diffstat (limited to 'usecaseui-portal/src/app/views')
27 files changed, 850 insertions, 314 deletions
diff --git a/usecaseui-portal/src/app/views/maas/build/application-management.component.html b/usecaseui-portal/src/app/views/maas/build/application-management.component.html index 53e112be..cd4c13de 100644 --- a/usecaseui-portal/src/app/views/maas/build/application-management.component.html +++ b/usecaseui-portal/src/app/views/maas/build/application-management.component.html @@ -27,27 +27,27 @@ > <thead> <tr> - <th nzWidth="9%" style="font-size: 20px;">No</th> - <th nzWidth="12%" style="font-size: 20px;">Application Name</th> - <th nzWidth="13%" style="font-size: 20px;">Application Description</th> - <th nzWidth="11%" style="font-size: 20px;">Application Type</th> - <th nzWidth="11%" style="font-size: 20px;">Operator</th> - <th nzWidth="11%" style="font-size: 20px;">MaaS</th> - <th nzWidth="11%" style="font-size: 20px;">Knowledge Base</th> - <th nzWidth="11%" style="font-size: 20px;">Large Model</th> - <th nzWidth="11%" style="font-size: 20px;">{{"i18nTextDefine_Action" | translate}}</th> + <th nzWidth="9%" class="head-column">No</th> + <th nzWidth="12%" class="head-column">Application Name</th> + <th nzWidth="13%" class="head-column">Application Description</th> + <th nzWidth="11%" class="head-column">Application Type</th> + <th nzWidth="11%" class="head-column">Operator</th> + <th nzWidth="11%" class="head-column">MaaS</th> + <th nzWidth="11%" class="head-column">Knowledge Base</th> + <th nzWidth="11%" class="head-column">Large Model</th> + <th nzWidth="11%" class="head-column">{{"i18nTextDefine_Action" | translate}}</th> </tr> </thead> <tbody> <tr *ngFor="let data of basicTable.data; let i = index"> - <td>{{i+1}}</td> - <td>{{data.applicationName}}</td> - <td>{{data.applicationDescription}}</td> - <td>{{data.applicationType}}</td> - <td>{{data.operatorName}}</td> - <td>{{data.maaSPlatformName}}</td> - <td>{{data.knowledgeBaseName}}</td> - <td>{{data.largeModelName}}</td> + <td class="column">{{i+1}}</td> + <td class="column">{{data.applicationName}}</td> + <td class="column">{{data.applicationDescription}}</td> + <td class="column">{{data.applicationType}}</td> + <td class="column">{{data.operatorName}}</td> + <td class="column">{{data.maaSPlatformName}}</td> + <td class="column">{{data.knowledgeBaseName}}</td> + <td class="column">{{data.largeModelName}}</td> <td> <i class="anticon anticon-menu-fold" (click)="displayApplicationDetails(data)"></i> <i class="anticon anticon-edit" (click)="edit(data)"></i> @@ -58,6 +58,5 @@ </tbody> </nz-table> </div> -<app-create-application-management *ngIf="createModalShow" [showModal]="createModalShow" (modalOpreation)="createModalClose($event)" [existedNames]="existedNames"></app-create-application-management> -<app-application-detail *ngIf="applicationShow" [showModal]="applicationShow" (modalOpreation)="applicationDetailClose()" [applicationDetail]="applicationDetail"></app-application-detail> -<app-edit-application *ngIf="editModalShow" [showModal]="editModalShow" (modalOpreation)="editModalClose($event)" [applicationId]="applicationId"></app-edit-application>
\ No newline at end of file +<app-create-application-management *ngIf="createModalShow || editModalShow" [showModal]="createModalShow || editModalShow" (modalOpreation)="createModalClose($event)" [existedNames]="existedNames" [isEdit]="editModalShow" [applicationId]="applicationId"></app-create-application-management> +<app-application-detail *ngIf="applicationShow" [showModal]="applicationShow" (modalOpreation)="applicationDetailClose()" [applicationDetail]="applicationDetail"></app-application-detail>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/build/application-management.component.less b/usecaseui-portal/src/app/views/maas/build/application-management.component.less index beefd0f9..7d78a838 100644 --- a/usecaseui-portal/src/app/views/maas/build/application-management.component.less +++ b/usecaseui-portal/src/app/views/maas/build/application-management.component.less @@ -14,6 +14,14 @@ margin-top: 7px; } } + .head-column { + font-size: 20px; + word-break: break-word; + } + + .column { + word-break: break-word; + } .anticon-edit,.anticon-delete,.anticon-menu-fold{ font-size: 18px; margin-right: 10px; diff --git a/usecaseui-portal/src/app/views/maas/build/application-management.component.ts b/usecaseui-portal/src/app/views/maas/build/application-management.component.ts index 00c0c405..e00e91f3 100644 --- a/usecaseui-portal/src/app/views/maas/build/application-management.component.ts +++ b/usecaseui-portal/src/app/views/maas/build/application-management.component.ts @@ -51,6 +51,7 @@ export class ApplicationManagementComponent implements OnInit { createModalClose($event: modalClose): void { this.createModalShow = false; + this.editModalShow = false; if ($event.cancel) { return; } @@ -86,7 +87,7 @@ export class ApplicationManagementComponent implements OnInit { this.applicationDetail = data.result_body; }, () => { - this.message.error('Failed to obtain knowledge base data'); + this.message.error('Failed to obtain application data'); } ) } @@ -97,7 +98,7 @@ export class ApplicationManagementComponent implements OnInit { } showDeleteConfirm(data: Application): void { - this.modalService.error({ + this.modalService.confirm({ nzTitle: this.translate.instant('maas.deleteTitle'), nzContent: this.translate.instant('maas.application.deleteApplicationContent'), nzOkText: 'Yes', @@ -108,12 +109,4 @@ export class ApplicationManagementComponent implements OnInit { }); } - editModalClose($event: modalClose): void { - this.editModalShow = false; - if ($event.cancel) { - return; - } - this.getAllApplicationData() - } - }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.html b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.html index 5a5bb445..5824f706 100644 --- a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.html +++ b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.html @@ -39,8 +39,8 @@ </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="8" nzFor="applicationType" nzRequired>Application Type</nz-form-label> - <nz-form-control [nzSpan]="12"> - <nz-select name="applicationType" + <nz-form-control [nzSpan]="12" [ngClass]="{'disabled-item': isEdit}"> + <nz-select name="applicationType" [ngClass]="{'disabled-input': isEdit}" nzPlaceHolder="Select Application Type" formControlName="applicationType"> <nz-option nzValue="Knowledge Assistant" nzLabel="Knowledge Assistant"></nz-option> </nz-select> @@ -51,8 +51,8 @@ </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="8" nzFor="selectedOperator" nzRequired>Operator Name</nz-form-label> - <nz-form-control [nzSpan]="12"> - <nz-select name="selectedOperator" + <nz-form-control [nzSpan]="12" [ngClass]="{'disabled-item': isEdit}"> + <nz-select name="selectedOperator" [ngClass]="{'disabled-input': isEdit}" nzPlaceHolder="Select Operator" formControlName="selectedOperator" (ngModelChange)="handleOperatorChange($event)"> <nz-option *ngFor="let operator of operators" [nzValue]="operator" @@ -65,11 +65,11 @@ </nz-form-item> <nz-form-item> <nz-form-label [nzSpan]="8" nzFor="selectedPlatform" nzRequired>MaaS Platform Name</nz-form-label> - <nz-form-control [nzSpan]="12"> - <nz-select name="selectedPlatform" + <nz-form-control [nzSpan]="12" [ngClass]="{'disabled-item': isEdit}"> + <nz-select name="selectedPlatform" [ngClass]="{'disabled-input': isEdit}" nzPlaceHolder="Select Platform" formControlName="selectedPlatform" (ngModelChange)="handleMaasChange($event)"> - <nz-option *ngFor="let platform of filteredPlatforms" [nzValue]="platform" + <nz-option *ngFor="let platform of filteredPlatforms" [nzValue]="platform.maaSPlatformId" [nzLabel]="platform.maaSPlatformName"></nz-option> </nz-select> <nz-form-explain *ngIf="validateForm.get('selectedPlatform').dirty && validateForm.get('selectedPlatform').errors"> @@ -82,7 +82,7 @@ <nz-form-control [nzSpan]="12"> <nz-select name="selectedModel" nzPlaceHolder="Select Model" formControlName="selectedModel"> - <nz-option *ngFor="let model of filteredModels" [nzValue]="model" [nzLabel]="model.modelName"></nz-option> + <nz-option *ngFor="let model of filteredModels" [nzValue]="model.modelId" [nzLabel]="model.modelName"></nz-option> </nz-select> <nz-form-explain *ngIf="validateForm.get('selectedModel').dirty && validateForm.get('selectedModel').errors"> Please select model! @@ -94,7 +94,7 @@ <nz-form-control [nzSpan]="12"> <nz-select name="selectKnowledgeBase" nzPlaceHolder="Select KnowLedge Base" formControlName="selectKnowledgeBase"> - <nz-option *ngFor="let knowledgeBase of knowledgeBases" [nzValue]="knowledgeBase" + <nz-option *ngFor="let knowledgeBase of knowledgeBases" [nzValue]="knowledgeBase.knowledgeBaseId" [nzLabel]="knowledgeBase.knowledgeBaseName"></nz-option> </nz-select> <nz-form-explain *ngIf="validateForm.get('selectKnowledgeBase').dirty && validateForm.get('selectKnowledgeBase').errors"> diff --git a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.less b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.less index 9156f1f9..f8fea30c 100644 --- a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.less +++ b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.less @@ -1,11 +1,3 @@ -// .ant-select { -// width: 200px; -// } - -// .ant-input { -// width: 300px; -// } - .input-wrapper { display: flex; align-items: center; @@ -47,9 +39,25 @@ position: relative; } +.disabled-input ::ng-deep .ant-select-selection{ + color: #00000040; + background-color: #f5f5f5; + border-color: #d9d9d9; + box-shadow: none; + opacity: 1; +} + #charCount { position: absolute; top: 9px; right: 15px; line-height: 20px; +} + +.disabled-input { + pointer-events: none; +} + +.disabled-item { + cursor: not-allowed; }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.ts b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.ts index a4dba970..0ee40d7b 100644 --- a/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.ts +++ b/usecaseui-portal/src/app/views/maas/build/create-application-management/create-application-management.component.ts @@ -5,6 +5,7 @@ import { MaasApi } from '@src/app/api/maas.api'; import { KnowledgeBase, MaaSPlatform, ModelInformation, Operators } from '../../knowledge-base-management/knowledge-base.type'; import { Subject } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; +import { Application } from '../application.type'; @Component({ selector: 'app-create-application-management', @@ -12,7 +13,22 @@ import { debounceTime } from 'rxjs/operators'; styleUrls: ['./create-application-management.component.less'] }) export class CreateApplicationManagementComponent implements OnInit { + @Input() applicationId: string; title = 'Add Application'; + isEdit_ = false; + @Input() + set isEdit(v: boolean) { + if (v) { + this.title = 'Edit Application'; + } else { + this.title = 'Add Application'; + } + this.isEdit_ = v; + } + + get isEdit() { + return this.isEdit_; + } validateForm: FormGroup; @Input() showModal: boolean; @Output() modalOpreation = new EventEmitter(); @@ -26,6 +42,7 @@ export class CreateApplicationManagementComponent implements OnInit { @ViewChild('myTextarea') myTextarea: ElementRef; @ViewChild('charCount') charCount: ElementRef; @Input() existedNames: string[] = []; + application: Application; constructor( private myhttp: MaasApi, @@ -33,10 +50,42 @@ export class CreateApplicationManagementComponent implements OnInit { private fb: FormBuilder ) { } - ngOnInit() { - this.fetchOperators(); + async ngOnInit() { this.initFormData(); - this.submitSubject.pipe(debounceTime(6000)).subscribe(() => this.executeSubmit()); + await this.fetchOperators(); + if (this.isEdit) { + await this.fetchApplication(); + } + this.submitSubject.pipe(debounceTime(3000)).subscribe(() => this.executeSubmit()); + } + + async fetchApplication(): Promise<void> { + try { + const response = await this.myhttp.getApplicationById(this.applicationId).toPromise(); + if (response.result_header.result_code !== 200) { + this.message.error('get application error'); + return; + } + this.application = response.result_body; + + this.validateForm.patchValue({ + name: this.application.applicationName, + description: this.application.applicationDescription, + applicationType: this.application.applicationType, + selectedOperator: this.operators.find(i => i.operatorId === this.application.operatorId), + selectedPlatform: this.application.maaSPlatformId, + selectedModel: this.application.largeModelId, + selectKnowledgeBase: this.application.knowledgeBaseId, + prompt: this.application.prompt, + openingRemarks: this.application.openingRemarks, + temperature: this.application.temperature, + top_p: this.application.top_p, + temperatureSlider: this.application.temperature, + top_pSlider: this.application.top_p + }); + } catch (error) { + this.message.error('Failed to obtain knowledge base data'); + } } nameDuplicateValidator = (control: FormControl): { [s: string]: boolean } => { @@ -49,7 +98,7 @@ export class CreateApplicationManagementComponent implements OnInit { initFormData() { this.validateForm = this.fb.group({ - name: [null, [Validators.required, this.nameDuplicateValidator]], + name: this.isEdit ? [null, [Validators.required]] : [null, [Validators.required, this.nameDuplicateValidator]], description: [null], applicationType: [null, [Validators.required]], selectedOperator: [null, [Validators.required]], @@ -65,15 +114,13 @@ export class CreateApplicationManagementComponent implements OnInit { }); } - fetchOperators(): void { - this.myhttp.getOperators().subscribe( - (response) => { - this.operators = response.result_body; - }, - () => { - this.message.error('Failed to fetch operators'); - } - ); + async fetchOperators(): Promise<void> { + try { + const response = await this.myhttp.getOperators().toPromise(); + this.operators = response.result_body; + } catch (error) { + this.message.error('Failed to fetch operators'); + } } handleOperatorChange(value: Operators): void { @@ -87,10 +134,11 @@ export class CreateApplicationManagementComponent implements OnInit { this.validateForm.get('selectKnowledgeBase').setValue(null); } - handleMaasChange(value: MaaSPlatform): void { - if (value) { - this.filteredModels = value.modelList; - this.fetchKnowledgeBase(value); + handleMaasChange(maaSPlatformId: string): void { + if (maaSPlatformId) { + const filteredPlatformsByMaas = this.filteredPlatforms.find(i => i.maaSPlatformId === maaSPlatformId) + this.filteredModels = filteredPlatformsByMaas ? filteredPlatformsByMaas.modelList : []; + this.fetchKnowledgeBase(maaSPlatformId); } else { this.filteredModels = []; } @@ -98,8 +146,8 @@ export class CreateApplicationManagementComponent implements OnInit { this.validateForm.get('selectKnowledgeBase').setValue(null); } - fetchKnowledgeBase(value): void { - this.myhttp.fetchKnowledgeBaseByMaasId(value.maaSPlatformId).subscribe( + fetchKnowledgeBase(maaSPlatformId: string): void { + this.myhttp.fetchKnowledgeBaseByMaasId(maaSPlatformId).subscribe( (response) => { this.knowledgeBases = response.result_body; }, @@ -124,44 +172,54 @@ export class CreateApplicationManagementComponent implements OnInit { this.showModal = true; return; } - - this.myhttp.createApplication(this.constructBody()).subscribe( + const url = this.isEdit ? this.myhttp.url.updateApplication : this.myhttp.url.createApplicationUrl; + this.myhttp.createApplication(url, this.constructBody()).subscribe( (response) => { - this.showModal = false; - this.modalOpreation.emit({ "cancel": false }); if (response.result_header.result_code === 200) { - this.message.success('Created successfully'); + this.showModal = false; + this.modalOpreation.emit({ "cancel": false }); + this.message.success('Operate successfully'); } else { this.message.error(response.result_header.result_message); } }, () => { this.showModal = false; - this.message.error('Created failed'); + this.message.error('Operate failed'); } ) } constructBody() { + const filteredPlatformById = this.filteredPlatforms.find(i => i.maaSPlatformId === this.validateForm.value.selectedPlatform); + const maaSPlatformName = filteredPlatformById ? filteredPlatformById.maaSPlatformName : ''; + const filteredModelById = this.filteredModels.find(i => i.modelId === this.validateForm.value.selectedModel); + const largeModelName = filteredModelById ? filteredModelById.modelName : ''; + const filteredKnowledgebaseById = this.knowledgeBases.find(i => i.knowledgeBaseId === this.validateForm.value.selectKnowledgeBase); + const knowledgeBaseName = filteredKnowledgebaseById ? filteredKnowledgebaseById.knowledgeBaseName : ''; + const requestBody = { applicationName: this.validateForm.value.name, applicationDescription: this.validateForm.value.description, applicationType: this.validateForm.value.applicationType, operatorName: this.validateForm.value.selectedOperator.operatorName, operatorId: this.validateForm.value.selectedOperator.operatorId, - maaSPlatformId: this.validateForm.value.selectedPlatform.maaSPlatformId, - maaSPlatformName: this.validateForm.value.selectedPlatform.maaSPlatformName, - knowledgeBaseId: this.validateForm.value.selectKnowledgeBase.knowledgeBaseId, - knowledgeBaseName: this.validateForm.value.selectKnowledgeBase.knowledgeBaseName, - largeModelId: this.validateForm.value.selectedModel.modelId, - largeModelName: this.validateForm.value.selectedModel.modelName, + maaSPlatformId: this.validateForm.value.selectedPlatform, + maaSPlatformName, + knowledgeBaseId: this.validateForm.value.selectKnowledgeBase, + knowledgeBaseName, + largeModelId: this.validateForm.value.selectedModel, + largeModelName, prompt: this.validateForm.value.prompt, temperature: this.validateForm.value.temperature, top_p: this.validateForm.value.top_p, openingRemarks: this.validateForm.value.openingRemarks + } + if (this.isEdit) { + requestBody['applicationId'] = this.applicationId; + } + return requestBody; } - return requestBody; -} submitForm(): void { for (let i in this.validateForm.controls) { diff --git a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.html b/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.html deleted file mode 100644 index d2fb553b..00000000 --- a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.html +++ /dev/null @@ -1,18 +0,0 @@ -<nz-modal [(nzVisible)]="showModal" [nzTitle]="title" (nzOnCancel)="handleCancel()" - (nzOnOk)="submitForm()" nzWidth="648px" nzHeight="800px"> - <form nz-form [formGroup]="validateForm" (ngSubmit)="checkForm()"> - <nz-form-item> - <nz-form-label [nzSpan]="8" nzFor="name" nzRequired>Application Name</nz-form-label> - <nz-form-control [nzSpan]="12"> - <input nz-input formControlName="name" placeholder="Please input application name" /> - <nz-form-explain *ngIf="validateForm.get('name').dirty && validateForm.get('name').errors">Please input application name</nz-form-explain> - </nz-form-control> - </nz-form-item> - <nz-form-item> - <nz-form-label [nzSpan]="8" nzFor="description">Application Description</nz-form-label> - <nz-form-control [nzSpan]="12"> - <textarea rows="2" formControlName="description" nz-input></textarea> - </nz-form-control> - </nz-form-item> - </form> -</nz-modal>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.less b/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.less deleted file mode 100644 index e69de29b..00000000 --- a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.less +++ /dev/null diff --git a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.spec.ts b/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.spec.ts deleted file mode 100644 index 40fc6bd5..00000000 --- a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { EditApplicationComponent } from './edit-application.component'; - -describe('EditApplicationComponent', () => { - let component: EditApplicationComponent; - let fixture: ComponentFixture<EditApplicationComponent>; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ EditApplicationComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(EditApplicationComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.ts b/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.ts deleted file mode 100644 index 380cd5ff..00000000 --- a/usecaseui-portal/src/app/views/maas/build/edit-application/edit-application.component.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MaasApi } from '@src/app/api/maas.api'; -import { NzMessageService } from 'ng-zorro-antd'; -import { Application } from '../application.type'; - -@Component({ - selector: 'app-edit-application', - templateUrl: './edit-application.component.html', - styleUrls: ['./edit-application.component.less'] -}) -export class EditApplicationComponent implements OnInit { - title = 'Edit Application'; - @Input() showModal: boolean; - @Input() applicationId: string; - @Output() modalOpreation = new EventEmitter(); - validateForm: FormGroup; - defalutApplication: Application = { - 'applicationId': '', - 'applicationName': '', - 'applicationDescription': '', - 'applicationType': '', - 'operatorId': '', - 'operatorName': '', - 'maaSPlatformId': '', - 'maaSPlatformName': '', - 'knowledgeBaseName': '', - 'knowledgeBaseId': '', - 'largeModelName': '', - 'largeModelId': '', - 'prompt': '', - 'temperature': 3, - 'top_p': 3, - 'openingRemarks': '', - } - application: Application = this.defalutApplication; - constructor( - private myhttp: MaasApi, - private message: NzMessageService, - private fb: FormBuilder, - ) { } - - ngOnInit() { - this.validateForm = this.fb.group({ - name: [this.application.applicationName, [Validators.required]], - description: [this.application.applicationDescription], - }); - this.fetchApplication(); - } - - checkForm(): void { - for (const i in this.validateForm.controls) { - this.validateForm.controls[i].markAsDirty(); - this.validateForm.controls[i].updateValueAndValidity(); - } - } - - submitForm(): void { - this.checkForm(); - this.create(); - } - - fetchApplication(): void { - this.myhttp.getApplicationById(this.applicationId) - .subscribe( - (response) => { - if (response.result_header.result_code !== 200) { - this.message.error('get application error'); - return; - } - this.application = response.result_body; - this.validateForm.patchValue({ - name: this.application.applicationName, - description: this.application.applicationDescription - }); - }, - () => { - this.message.error('Failed to obtain knowledge base data'); - } - ) - } - - handleCancel(): void { - this.showModal = false; - this.modalOpreation.emit({ 'cancel': true }); - } - - create() { - const metaData = { - ...this.application, - applicationName: this.validateForm.get('name').value, - applicationDescription: this.validateForm.get('description').value, - }; - this.myhttp.updateApplication(metaData).subscribe( - (response) => { - if (response.result_header.result_code === 200) { - this.message.success('update knowledge base successfully'); - } else { - this.message.error(response.result_header.result_message); - } - this.modalOpreation.emit({ 'cancel': false }); - }, - (error) => { - console.log('Upload failed', error); - } - ); - } - -} diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.html b/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.html index 78773c0a..1931220f 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.html +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.html @@ -61,7 +61,8 @@ <nz-form-control [nzSpan]="12"> <nz-upload [(nzFileList)]="fileList" [nzBeforeUpload]="beforeUpload"> <button nz-button> - <i class="anticon anticon-upload"></i><span>Select File</span> + <i class="anticon anticon-upload"></i> + <span>Select File</span> </button> </nz-upload> </nz-form-control> diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.ts index 2757137b..aefe2066 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/create-knowledge-base/create-knowledge-base.component.ts @@ -35,7 +35,7 @@ export class CreateKnowledgeBaseComponent implements OnInit { name: [null, [Validators.required]], description: [null], selectedOperator: [null, [Validators.required]], - selectedPlatform: [null, [Validators.required]], + selectedPlatform: [null, [Validators.required]] }); } fetchOperators(): void { diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.html b/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.html index feee9b8f..e181ee5c 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.html +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.html @@ -4,8 +4,7 @@ <nz-form-item> <nz-form-label [nzSpan]="8" nzFor="name" nzRequired>Knowledge Base Name</nz-form-label> <nz-form-control [nzSpan]="12"> - <input nz-input formControlName="name" placeholder="Please input knowledge base name" /> - <nz-form-explain *ngIf="validateForm.get('name').dirty && validateForm.get('name').errors">Please input knowledge base name</nz-form-explain> + <input nz-input class="disabled-input" formControlName="name" placeholder="Please input knowledge base name"/> </nz-form-control> </nz-form-item> <nz-form-item> diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.ts index 3a71d800..00b65dfe 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component.ts @@ -23,7 +23,7 @@ export class EditKnowledgeBaseComponent implements OnInit { maaSPlatformName: '', maaSPlatformId: '', updateTime: '', - filesName: [], + fileList: [], operatorId: '' } knowledgeBase: KnowledgeBase = this.defalutKnowledgeBase; diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.html b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.html index b491df86..419bb6b3 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.html +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.html @@ -15,7 +15,7 @@ --> <nz-modal [(nzVisible)]="showModal" nzTitle="Knowledge Base Detail" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()" nzWidth="56%" nzHeight="800px" class="intent-management-modal"> - <app-descriptions> + <app-descriptions *ngIf="knowledgeBaseDetail else LoadingTmp"> <app-descriptions-item nzTitle="Knowledge Base Name">{{knowledgeBaseDetail.knowledgeBaseName}} </app-descriptions-item> <app-descriptions-item nzTitle="Operator Name">{{knowledgeBaseDetail.operatorName}} @@ -25,11 +25,35 @@ <app-descriptions-item nzTitle="Update Time"> {{knowledgeBaseDetail.updateTime}} </app-descriptions-item> - <app-descriptions-item nzTitle="Files Name"> - {{knowledgeBaseService.getFiles(knowledgeBaseDetail)}} - </app-descriptions-item> <app-descriptions-item [nzSpan]="3" nzTitle="Knowledge Base Description">{{knowledgeBaseDetail.knowledgeBaseDescription}} </app-descriptions-item> + <app-descriptions-item [nzSpan]="3" nzTitle="Files Name"> + <div class="upload-file"> + <nz-upload [nzAction]="url" [(nzFileList)]="fileList" (nzChange)="handleChange($event)" nzName="files" [nzData]="nzdata"> + <button nz-button> + <i class="anticon anticon-upload"></i> + <span>Select File</span> + </button> + </nz-upload> + <div *ngFor="let file of displayFiles" + class="ant-upload-list-item ant-upload-list-item- ng-trigger ng-trigger-itemState ng-star-inserted" [ngClass]="{'ant-upload-list-item-error': file.status === 'error'}"> + <div class="ant-upload-list-item-info"> + <span class="ng-tns-c15-6 ng-star-inserted"> + <i class="anticon anticon-paper-clip ng-star-inserted"></i> + <span class="ant-upload-list-item-name ng-tns-c15-6 ng-star-inserted" + title="fastgpt_README.md">{{file.fileName}}</span> + </span> + </div> + <i class="anticon anticon-cross ng-tns-c15-6 ng-star-inserted" title="Remove file" + (click)="removedFile(file)"></i> + </div> + </div> + </app-descriptions-item> </app-descriptions> + <ng-template #LoadingTmp> + <div class="loading"> + <nz-spin class="upload-loading" [nzSize]="'large'"></nz-spin> + </div> + </ng-template> </nz-modal>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.less b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.less index e69de29b..9447ad74 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.less +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.less @@ -0,0 +1,14 @@ +.upload-file { + width: 100%; +} + +.upload-loading { + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.loading { + position: relative; + height: 37px; +} diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.ts index 49b9de4a..a9b0adaa 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-detail/knowledge-base-detail.component.ts @@ -1,21 +1,56 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { KnowledgeBase } from '../knowledge-base.type'; import { KnowledgeBaseService } from '../knowledge-base.service'; +import { MaasApi } from '@src/app/api/maas.api'; +import { NzMessageService } from 'ng-zorro-antd'; +import { forkJoin } from 'rxjs/observable/forkJoin'; +import { of } from 'rxjs/observable/of'; +import { catchError } from 'rxjs/operators'; +import { MaasService } from '../../maas-service.service'; @Component({ selector: 'app-knowledge-base-detail', templateUrl: './knowledge-base-detail.component.html', styleUrls: ['./knowledge-base-detail.component.less'] }) export class KnowledgeBaseDetailComponent implements OnInit { - constructor( - public knowledgeBaseService: KnowledgeBaseService + public knowledgeBaseService: KnowledgeBaseService, + public myhttp: MaasApi, + private maasServie: MaasService, + private message: NzMessageService, ) { } @Input() showModal: boolean; - @Input() knowledgeBaseDetail: KnowledgeBase; + displayFiles = []; + init = true; + data: KnowledgeBase ; + set knowledgeBaseDetail(v: KnowledgeBase) { + if(v) { + this.displayFiles = v.fileList.slice().reverse(); + this.data = v; + } + } + get knowledgeBaseDetail() { + return this.data; + } + @Input() id = ''; + fileList: File[] = []; @Output() modalOpreation = new EventEmitter(); - + removedFiles:string[] = []; + url = `${(window as any).baseUrl}${this.myhttp.url.uploadFile}`; + ngOnInit() { + this.displayKnowledgeDetails(this.id); + } + + displayKnowledgeDetails(id: string) { + this.myhttp.getKnowledgeBaseById(id).subscribe( + (response) => { + this.knowledgeBaseDetail = response.result_body; + }, + () => { + this.message.error('Failed to obtain knowledge base data'); + } + ); } handleCancel(): void { @@ -27,4 +62,55 @@ export class KnowledgeBaseDetailComponent implements OnInit { this.showModal = false; this.modalOpreation.emit(); } + + handleChange({ file}): void { + const status = file.status; + if (status === 'done') { + this.fileList = []; + if (file.response.result_header.result_code === 200) { + this.message.success(`${file.name} upload successfully.`); + this.displayKnowledgeDetails(this.id); + } else { + this.displayFiles.unshift({fileId: this.maasServie.generateUniqueId, fileName: file.name, status: 'error'}); + } + } else if (status === 'error') { + this.fileList = []; + this.displayFiles.unshift({fileId: this.maasServie.generateUniqueId, fileName: file.name, status: 'error'}); + this.message.error(`${file.name} file upload failed.`); + } else if (status === 'removed') { + console.log('file event removed!'); + } + } + + nzdata = () => { + const metaData = JSON.stringify({ + knowledgeBaseId: this.knowledgeBaseDetail.knowledgeBaseId + }); + return {metaData} + } + + removedFile({fileId, status, fileName}) { + if (status === 'error') { + this.displayFiles = this.displayFiles.filter(file => file.fileId !== fileId); + this.message.success(`${fileName} delete successfully.`); + return; + } + this.myhttp.removeFile(fileId).pipe( + ).subscribe( + (response) => { + if (response.result_header.result_code === 200) { + this.displayFiles = this.displayFiles.filter(file => file.fileId !== fileId); + this.message.success(`${fileName} delete successfully.`); + } + }, + () => { + this.message.success(`${fileName} delete failed.`); + } + ) + } + + beforeUpload = (): boolean => { + return true; + } + }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.html b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.html index eb7c232a..703bc04a 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.html +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.html @@ -45,8 +45,8 @@ <app-create-knowledge-base *ngIf="createModalShow" [showModal]="createModalShow" (modalOpreation)="createModalClose($event)"></app-create-knowledge-base> <app-knowledge-base-detail *ngIf="knowledgeBaseShow" [showModal]="knowledgeBaseShow" - (modalOpreation)="knowledgeBaseDetailClose()" - [knowledgeBaseDetail]="knowledgeBaseDetail"></app-knowledge-base-detail> + (modalOpreation)="knowledgeBaseDetailClose()" [id]="knowledgeBaseId" + ></app-knowledge-base-detail> <app-edit-knowledge-base *ngIf="editKnowledgeBaseShow" [showModal]="editKnowledgeBaseShow" [knowledgeBaseId]="knowledgeBaseId" (modalOpreation)="editKnowledgeBaseModuleClose($event)"></app-edit-knowledge-base>
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.ts index 26b672cc..e6c96189 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base-management.component.ts @@ -77,16 +77,8 @@ export class KnowledgeBaseManagementComponent implements OnInit { } displayKnowledgeDetails(data): void { + this.knowledgeBaseId = data.knowledgeBaseId; this.knowledgeBaseShow = true; - this.myhttp.getKnowledgeBaseById(data.knowledgeBaseId) - .subscribe( - (data) => { - this.knowledgeBaseDetail = data.result_body; - }, - () => { - this.message.error('Failed to obtain knowledge base data'); - } - ) } editKnowedgeBase(data: KnowledgeBase) { @@ -101,7 +93,8 @@ export class KnowledgeBaseManagementComponent implements OnInit { nzOkText: 'Yes', nzOkType: 'danger', nzOnOk: () => this.deleteKnowledgeBase(data), - nzCancelText: 'No' + nzCancelText: 'No', + nzIconType: 'warning', }); } diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.service.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.service.ts index f7d91b1c..84f27181 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.service.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.service.ts @@ -3,9 +3,5 @@ import { KnowledgeBase } from './knowledge-base.type'; @Injectable() export class KnowledgeBaseService { - constructor() { } - getFiles(v: KnowledgeBase) { - return v.filesName ? v.filesName.join(',') : ''; - } } diff --git a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.type.ts b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.type.ts index b9ec432d..ac273a96 100644 --- a/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.type.ts +++ b/usecaseui-portal/src/app/views/maas/knowledge-base-management/knowledge-base.type.ts @@ -4,12 +4,15 @@ export type KnowledgeBase = { operatorName: string, maaSPlatformName: string, updateTime: string, - filesName: Array<string>, operatorId: string, maaSPlatformId: string, - knowledgeBaseId: string + knowledgeBaseId: string, + fileList: Array<File>, +} +export type File = { + fileId: string, + fileName: string } - export type KnowledgeBaseResponse = Response<KnowledgeBase> export type KnowledgeBasesResponse = Response<Array<KnowledgeBase>> diff --git a/usecaseui-portal/src/app/views/maas/maas.module.ts b/usecaseui-portal/src/app/views/maas/maas.module.ts index 8c666903..726ecf11 100644 --- a/usecaseui-portal/src/app/views/maas/maas.module.ts +++ b/usecaseui-portal/src/app/views/maas/maas.module.ts @@ -12,10 +12,11 @@ import { KnowledgeBaseDetailComponent } from './knowledge-base-management/knowle import { SharedModule } from '@src/app/shared/module/sharded.module'; import { MaasApi } from '@src/app/api/maas.api'; import { EditKnowledgeBaseComponent } from './knowledge-base-management/edit-knowledge-base/edit-knowledge-base.component'; -import { EditApplicationComponent } from './build/edit-application/edit-application.component'; import { MaasService } from './maas-service.service'; import { KnowledgeBaseService } from './knowledge-base-management/knowledge-base.service'; - +import { MarkdownModule } from 'ngx-markdown'; +import { ClipboardModule } from 'ngx-clipboard'; +import { CodeBlockDirective } from './use/code-block.directive'; @NgModule({ providers: [ MaasApi, @@ -24,7 +25,9 @@ import { KnowledgeBaseService } from './knowledge-base-management/knowledge-base ], imports: [ SharedModule, - MaasRoutingModule + MaasRoutingModule, + MarkdownModule.forChild(), + ClipboardModule ], declarations: [ ApplicationManagementComponent, @@ -37,7 +40,7 @@ import { KnowledgeBaseService } from './knowledge-base-management/knowledge-base CreateKnowledgeBaseComponent, KnowledgeBaseDetailComponent, EditKnowledgeBaseComponent, - EditApplicationComponent + CodeBlockDirective ] }) export class MaasModule { } diff --git a/usecaseui-portal/src/app/views/maas/use/code-block.directive.spec.ts b/usecaseui-portal/src/app/views/maas/use/code-block.directive.spec.ts new file mode 100644 index 00000000..296e9a53 --- /dev/null +++ b/usecaseui-portal/src/app/views/maas/use/code-block.directive.spec.ts @@ -0,0 +1,8 @@ +import { CodeBlockDirective } from './code-block.directive'; + +describe('CodeBlockDirective', () => { + it('should create an instance', () => { + const directive = new CodeBlockDirective(); + expect(directive).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts b/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts new file mode 100644 index 00000000..08efe92c --- /dev/null +++ b/usecaseui-portal/src/app/views/maas/use/code-block.directive.ts @@ -0,0 +1,41 @@ +import { Directive, ElementRef, Renderer2, Input } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { NzMessageService } from 'ng-zorro-antd'; +import { ClipboardService } from 'ngx-clipboard'; + +@Directive({ + selector: '[appCodeBlock]' +}) +export class CodeBlockDirective { + @Input() set appCodeBlock(status: string) { + if (status === 'finished') { + setTimeout(() => { + this.setCopyButton(); + }, 0); + + } + } + + constructor(private el: ElementRef, private renderer: Renderer2, private clipboardService: ClipboardService, + private message: NzMessageService, private translate: TranslateService + ) { } + + setCopyButton() { + const preElements = this.el.nativeElement.querySelectorAll('pre'); + + preElements.forEach(pre => { + const codeElement = pre.querySelector('code'); + const copyButtonExists = pre.querySelector('button.copy-button'); + if (codeElement && !copyButtonExists) { + const copyButton = this.renderer.createElement('button'); + this.renderer.addClass(copyButton, 'copy-button'); + this.renderer.setProperty(copyButton, 'innerHTML', 'Copy'); + this.renderer.listen(copyButton, 'click', () => { + this.clipboardService.copyFromContent(codeElement.innerText); + this.message.success(this.translate.instant('maas.copy_to_clipboard')); + }); + this.renderer.insertBefore(pre, copyButton, codeElement); + } + }); + } +} diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.html b/usecaseui-portal/src/app/views/maas/use/use-application.component.html index f8c65794..25c39f7b 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.html +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.html @@ -34,7 +34,7 @@ </div> </div> <div class="question-container"> - <span class="question-text">{{ chat.question }}</span> + <markdown class="question-text" [data]="chat.question"></markdown> </div> </div> <br> @@ -45,8 +45,11 @@ [nz-tooltip]="'maas.copy' | translate"></span> </div> <span class="answer-text"> - <span class="answer" [ngClass]="{'hidden-cursor': chat.status==='finished'}" #answerText - id="answerText">{{chat.answer}}</span> + <markdown appCodeBlock="{{chat.status}}" class="markdown answer-markdown" [ngClass]="{'hidden-cursor': chat.status==='finished'}" *ngIf="chat.answer else default" [data]="chat.answer"></markdown> + <ng-template #default> + <span class="answer default" [ngClass]="{'hidden-cursor': chat.status==='finished'}" #answerText> + </span> + </ng-template> </span> </div> <br> @@ -54,7 +57,7 @@ </div> <div class="input-wrapper"> - <textarea nzAutosize nz-input [(ngModel)]="question" class="text-input question-input"></textarea> + <textarea #questionInput nzAutosize nz-input [(ngModel)]="question" class="text-input question-input" placeholder="{{'maas.questionPlaceholder' | translate}}" nzSize="small"></textarea> <div class="send-wrapper" [ngClass]="{'stop-wrapper': isGeneratingAnswer}"> <div class="icon" (click)="doAction()" [ngClass]="{'send-disabled': !isGeneratingAnswer &&!question, 'send-enabled': question && !isGeneratingAnswer, 'stop-generating': isGeneratingAnswer}" diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.less b/usecaseui-portal/src/app/views/maas/use/use-application.component.less index c2f926fb..d57a6900 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.less +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.less @@ -9,15 +9,11 @@ } .fixed-select-wrapper { - position: fixed; - top: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; + padding: 20px 0 0 100px; } .chat-container { - margin: 60px 0; + margin: 20px 0; padding: 0 100px; } @@ -43,59 +39,65 @@ display: flex; border-radius: 8px; overflow: hidden; - border: 1px solid #fff; margin-right: 8px; height: 24px; margin-top:3px; } -.question-icon-actions span:not(:first-child) { - border-left: 1px solid #fff; -} - .question-action { width: 24px; padding-top: 4px; } .question-container { - margin: 8px 0; + border-radius: 8px; + background-color: white; } .question-text { - background-color: white; font-size: 16px; - padding: 10px; - border-radius: 8px; } .answer-action { height: 24px; width: 24px; - border: 1px solid #fff; border-radius: 8px; padding-top: 3px; } -#answerText { +.answer { font-size: 16px; - padding: 10px; white-space: pre-line; width: auto; display: inline-block; position: relative; - min-height: 40px; } -.answer::after { +.answer::after{ + content: ''; + display: inline-block; + width: 2px; + height: 16px; + background-color: black; + position: absolute; + animation: blink 1s step-end infinite; + margin-top: -20px; +} + +.answer-markdown::after { content: ''; display: inline-block; - width: 1px; + width: 2px; height: 16px; background-color: black; position: absolute; animation: blink 1s step-end infinite; - margin-top: 5px; + margin-top: -10px; +} + +.answer-markdown { + font-size: 16px; + position: relative; } .hidden-cursor::after { @@ -103,10 +105,12 @@ } .answer-text { + max-width: 100%; margin: 8px 0; background-color: white; display: inline-block; border-radius: 8px; + padding: 8px; } .answer-container img, .answer-icon img, .question img{ @@ -219,4 +223,420 @@ 50% { background-color: black; } +} + +.copy-button { + position: absolute; + right: 0; + top: 0; + background-color: #485264; + color: white; + border: none; + padding: 5px 10px; + cursor: pointer; + border-radius: 3px; +} + +.default { + padding: 0 5px; +} + +:host ::ng-deep .question-text p, +:host ::ng-deep :host ::ng-deep .markdown p { + margin: 8px; +} + +:host ::ng-deep .markdown ul, +:host ::ng-deep .markdown ol { + padding-left: 14px; +} + +:host ::ng-deep .markdown > *:first-child { + margin-top: 0 !important; +} +:host ::ng-deep .markdown > *:last-child { + margin-bottom: 0 !important; +} +:host ::ng-deep .markdown a.absent { + color: #cc0000; +} +:host ::ng-deep .markdown a.anchor { + bottom: 0; + cursor: pointer; + display: block; + left: 0; + margin-left: -30px; + padding-left: 30px; + position: absolute; + top: 0; +} +:host ::ng-deep .markdown h1, +:host ::ng-deep .markdown h2, +:host ::ng-deep .markdown h3, +:host ::ng-deep .markdown h4, +:host ::ng-deep .markdown h5, +:host ::ng-deep .markdown h6 { + cursor: text; + font-weight: bold; + margin: 10px 0; + padding: 0; + position: relative; +} +:host ::ng-deep .markdown h1 .mini-icon-link, +:host ::ng-deep .markdown h2 .mini-icon-link, +:host ::ng-deep .markdown h3 .mini-icon-link, +:host ::ng-deep .markdown h4 .mini-icon-link, +:host ::ng-deep .markdown h5 .mini-icon-link, +:host ::ng-deep .markdown h6 .mini-icon-link { + display: none; +} +:host ::ng-deep .markdown h1:hover a.anchor, +:host ::ng-deep .markdown h2:hover a.anchor, +:host ::ng-deep .markdown h3:hover a.anchor, +:host ::ng-deep .markdown h4:hover a.anchor, +:host ::ng-deep .markdown h5:hover a.anchor, +:host ::ng-deep .markdown h6:hover a.anchor { + line-height: 1; + margin-left: -22px; + padding-left: 0; + text-decoration: none; + top: 15%; +} +:host ::ng-deep .markdown h1:hover a.anchor .mini-icon-link, +:host ::ng-deep .markdown h2:hover a.anchor .mini-icon-link, +:host ::ng-deep .markdown h3:hover a.anchor .mini-icon-link, +:host ::ng-deep .markdown h4:hover a.anchor .mini-icon-link, +:host ::ng-deep .markdown h5:hover a.anchor .mini-icon-link, +:host ::ng-deep .markdown h6:hover a.anchor .mini-icon-link { + display: inline-block; +} +:host ::ng-deep .markdown h1 tt, +:host ::ng-deep .markdown h1 code, +:host ::ng-deep .markdown h2 tt, +:host ::ng-deep .markdown h2 code, +:host ::ng-deep .markdown h3 tt, +:host ::ng-deep .markdown h3 code, +:host ::ng-deep .markdown h4 tt, +:host ::ng-deep .markdown h4 code, +:host ::ng-deep .markdown h5 tt, +:host ::ng-deep .markdown h5 code, +:host ::ng-deep .markdown h6 tt, +:host ::ng-deep .markdown h6 code { + font-size: inherit; +} +:host ::ng-deep .markdown h1 { + font-size: 1.75rem; +} +:host ::ng-deep .markdown h2 { + font-size: 1.5rem; +} +:host ::ng-deep .markdown h3 { + font-size: 1.25rem; +} +:host ::ng-deep .markdown h4 { + font-size: 1rem; +} +:host ::ng-deep .markdown h5 { + font-size: 14px; +} +:host ::ng-deep .markdown h6 { + font-size: 12px; +} +:host ::ng-deep .markdown p, +:host ::ng-deep .markdown blockquote, +:host ::ng-deep .markdown ul, +:host ::ng-deep .markdown ol, +:host ::ng-deep .markdown dl, +:host ::ng-deep .markdown table, +:host ::ng-deep .markdown pre { + margin: 14px 0; +} +:host ::ng-deep .markdown > h2:first-child, +:host ::ng-deep .markdown > h1:first-child, +:host ::ng-deep .markdown > h1:first-child + h2, +:host ::ng-deep .markdown > h3:first-child, +:host ::ng-deep .markdown > h4:first-child, +:host ::ng-deep .markdown > h5:first-child, +:host ::ng-deep .markdown > h6:first-child { + margin-top: 0; + padding-top: 0; +} +:host ::ng-deep .markdown a:first-child h1, +:host ::ng-deep .markdown a:first-child h2, +:host ::ng-deep .markdown a:first-child h3, +:host ::ng-deep .markdown a:first-child h4, +:host ::ng-deep .markdown a:first-child h5, +:host ::ng-deep .markdown a:first-child h6 { + margin-top: 0; + padding-top: 0; +} +:host ::ng-deep .markdown h1 + p, +:host ::ng-deep .markdown h2 + p, +:host ::ng-deep .markdown h3 + p, +:host ::ng-deep .markdown h4 + p, +:host ::ng-deep .markdown h5 + p, +:host ::ng-deep .markdown h6 + p { + margin-top: 0; +} +:host ::ng-deep .markdown li p.first { + display: inline-block; +} +:host ::ng-deep .markdown ul, +:host ::ng-deep .markdown ol { + padding-left: 2em; +} +:host ::ng-deep .markdown ul.no-list, +:host ::ng-deep .markdown ol.no-list { + list-style-type: none; + padding: 0; +} +:host ::ng-deep .markdown ul li > *:first-child, +:host ::ng-deep .markdown ol li > *:first-child { + margin-top: 0; +} +:host ::ng-deep .markdown ul, +:host ::ng-deep .markdown ol { + padding-left: 14px; +} +:host ::ng-deep .markdown dl { + padding: 0; +} +:host ::ng-deep .markdown dl dt { + font-size: 14px; + font-style: italic; + font-weight: bold; + margin: 15px 0 5px; + padding: 0; +} +:host ::ng-deep .markdown dl dt:first-child { + padding: 0; +} +:host ::ng-deep .markdown dl dt > *:first-child { + margin-top: 0; +} +:host ::ng-deep .markdown dl dt > *:last-child { + margin-bottom: 0; +} +:host ::ng-deep .markdown dl dd { + margin: 0 0 15px; + padding: 0 15px; +} +:host ::ng-deep .markdown dl dd > *:first-child { + margin-top: 0; +} +:host ::ng-deep .markdown dl dd > *:last-child { + margin-bottom: 0; +} +:host ::ng-deep .markdown blockquote { + border-left: 4px solid #dddddd; + color: #777777; + padding: 0 15px; +} +:host ::ng-deep .markdown blockquote > *:first-child { + margin-top: 0; +} +:host ::ng-deep .markdown blockquote > *:last-child { + margin-bottom: 0; +} +:host ::ng-deep .markdown table { + width: 100%; +} +:host ::ng-deep .markdown table th { + font-weight: bold; +} +:host ::ng-deep .markdown table th, +:host ::ng-deep .markdown table td { + padding: 6px 13px; +} +:host ::ng-deep .markdown table tr { + background-color: #ffffff; +} +:host ::ng-deep .markdown table tr:nth-child(2n) { + background-color: #f0f0f0; +} +:host ::ng-deep .markdown img { + max-width: 100%; +} +:host ::ng-deep .markdown span.frame { + display: block; + overflow: hidden; +} +:host ::ng-deep .markdown span.frame > span { + border: 1px solid #dddddd; + display: block; + float: left; + margin: 13px 0 0; + overflow: hidden; + padding: 7px; + width: auto; +} +:host ::ng-deep .markdown span.frame span img { + display: block; + float: left; +} +:host ::ng-deep .markdown span.frame span span { + clear: both; + color: #333333; + display: block; + padding: 5px 0 0; +} +:host ::ng-deep .markdown span.align-center { + clear: both; + display: block; + overflow: hidden; +} +:host ::ng-deep .markdown span.align-center > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: center; +} +:host ::ng-deep .markdown span.align-center span img { + margin: 0 auto; + text-align: center; +} +:host ::ng-deep .markdown span.align-right { + clear: both; + display: block; + overflow: hidden; +} +:host ::ng-deep .markdown span.align-right > span { + display: block; + margin: 13px 0 0; + overflow: hidden; + text-align: right; +} +:host ::ng-deep .markdown span.align-right span img { + margin: 0; + text-align: right; +} +:host ::ng-deep .markdown span.float-left { + display: block; + float: left; + margin-right: 13px; + overflow: hidden; +} +:host ::ng-deep .markdown span.float-left span { + margin: 13px 0 0; +} +:host ::ng-deep .markdown span.float-right { + display: block; + float: right; + margin-left: 13px; + overflow: hidden; +} +:host ::ng-deep .markdown span.float-right > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: right; +} +:host ::ng-deep .markdown code, +:host ::ng-deep .markdown tt { + border: 1px solid #dee0e2; + background-color: #f4f6f8; + border-radius: 3px; + margin: 0 2px; + padding: 0 5px; +} +:host ::ng-deep .markdown pre > code { + background: none repeat scroll 0 0 transparent; + border: medium none; + margin: 0; + padding: 0; +} +:host ::ng-deep .markdown .highlight pre, +:host ::ng-deep .markdown pre { + border: 1px solid #cccccc; + border-radius: 3px 3px 3px 3px; + font-size: 14px; + line-height: 19px; + overflow: auto; + padding: 6px 10px; +} +:host ::ng-deep .markdown pre code, +:host ::ng-deep .markdown pre tt { + background-color: transparent !important; + border: medium none; +} +:host ::ng-deep .markdown hr { + margin: 10px 0; + border-color: #C4CBD7; +} +:host ::ng-deep .markdown { + tab-size: 4; + word-spacing: normal; + width: 100%; + font-size: 14px; + + * { + word-break: break-word; + } + + pre { + display: block; + width: 100%; + padding: 15px; + margin: 0; + border: none; + border-radius: 0; + // background-color: gray !important; + overflow-x: auto; + color: gray; + position: relative; + } + + pre code { + width: 100%; + } + + a { + text-decoration: underline; + color: #2B5FD9; + } + + table { + border-collapse: separate; + border-spacing: 0px; + color: #383F50; + + thead tr:first-child th { + border-bottom-width: 1px; + border-left-width: 1px; + border-top-width: 1px; + border-color: #ccc; + background-color: rgba(236, 236, 241, 0.2); + overflow: hidden; + + &:first-child { + border-top-left-radius: 0.375rem; + } + &:last-child { + border-right-width: 1px; + border-top-right-radius: 0.375rem; + } + } + + td { + border-bottom-width: 1px; + border-left-width: 1px; + border-color: #ccc; + + &:last-of-type { + border-right-width: 1px; + } + } + + tbody tr:last-child { + overflow: hidden; + td { + &:first-child { + border-bottom-left-radius: 0.375rem; + } + &:last-child { + border-bottom-right-radius: 0.375rem; + } + } + } + } }
\ No newline at end of file diff --git a/usecaseui-portal/src/app/views/maas/use/use-application.component.ts b/usecaseui-portal/src/app/views/maas/use/use-application.component.ts index e73463d6..f0ce4f7e 100644 --- a/usecaseui-portal/src/app/views/maas/use/use-application.component.ts +++ b/usecaseui-portal/src/app/views/maas/use/use-application.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, OnInit, Renderer2, ViewChild } from '@angular/core'; +import { Component, ElementRef, OnInit, Renderer2, ViewChild, OnDestroy } from '@angular/core'; import { NzMessageService } from 'ng-zorro-antd'; import { SSE } from "sse.js"; import { ActivatedRoute } from '@angular/router'; @@ -12,8 +12,7 @@ export type Chat = { question: string, answer: string, questionId: string, statu templateUrl: './use-application.component.html', styleUrls: ['./use-application.component.less'] }) -export class UseApplicationComponent implements OnInit { - +export class UseApplicationComponent implements OnInit, OnDestroy { question: string; communicationMessage: string; chatHistory: Chat[] = []; @@ -26,6 +25,9 @@ export class UseApplicationComponent implements OnInit { isGeneratingAnswer: boolean = false; stopGenerating = this.translate.instant('maas.stopGenerating'); questionId = ''; + @ViewChild('questionInput') questionInput: ElementRef; + private keydownListener: () => void; + perHight = 21; constructor( private message: NzMessageService, private route: ActivatedRoute, @@ -35,14 +37,21 @@ export class UseApplicationComponent implements OnInit { private renderer: Renderer2 ) { } - ngOnInit() { - this.fetchAllApplication(); + async ngOnInit() { + await this.fetchAllApplication(); this.route.queryParams.subscribe(params => { this.queryParams = params; - this.selectedName = this.queryParams.id; + this.selectedName = this.queryParams.id || this.selectedName; }); + this.keydownListener = this.renderer.listen(this.questionInput.nativeElement, 'keydown', this.handleKeyDown.bind(this)); } + ngOnDestroy() { + if (this.keydownListener) { + this.keydownListener(); + } + } + close() { if (this.currentSSE) { this.currentSSE.close(); @@ -102,20 +111,17 @@ export class UseApplicationComponent implements OnInit { chat.answer += event.data.replace(/__SPACE__/g, ' '); } - fetchAllApplication(): void { - this.myhttp.getAllApplication() - .subscribe( - (data) => { - this.options = data.result_body.map(item => ({ - nzValue: item.applicationId, - nzLabel: item.applicationName - })); - this.selectedName = this.options.length > 0 ? this.options[0].nzValue : ''; - }, - () => { - this.message.error('Failed to obtain intent data'); - } - ) + async fetchAllApplication(): Promise<void> { + try { + const data = await this.myhttp.getAllApplication().toPromise(); + this.options = data.result_body.map(item => ({ + nzValue: item.applicationId, + nzLabel: item.applicationName + })); + this.selectedName = this.options.length > 0 ? this.options[0].nzValue : ''; + } catch { + this.message.error('Failed to obtain intent data'); + } } async copy(content: string): Promise<void> { @@ -130,4 +136,29 @@ export class UseApplicationComponent implements OnInit { deleteQuestion(questionId: string): void { this.chatHistory = this.chatHistory.filter(item => item.questionId !== questionId); } + + handleKeyDown(event: KeyboardEvent) { + if (event.key === 'Enter') { + if (event.shiftKey || event.ctrlKey || event.altKey) { + const TextareaDom = this.questionInput.nativeElement; + const height = parseInt(TextareaDom.style.height.split('px')[0], 10) + this.perHight; + TextareaDom.style.height = `${height}px`; + if(event.ctrlKey || event.altKey) { + const index = TextareaDom.selectionStart; + const val = TextareaDom.value; + TextareaDom.value = `${val.slice(0, index)}\n${val.slice(index)}`; + TextareaDom.selectionStart = index + 1; + TextareaDom.selectionEnd = index + 1; + } + } else { + event.preventDefault(); + if (this.isGeneratingAnswer) { + this.message.warning(this.translate.instant('maas.is_chatting')); + } else { + this.doAction(); + } + + } + } + } } |