diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html index f2b47dab2..66e408b39 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.html @@ -12,23 +12,20 @@
-
Copilot
+
Copilot
- @for (comment of responses$ | async; track comment) { + @for (comment of conversation(); track comment) {
{{ comment.date | date: 'sophisticatedDate' }}
- - -
-
{{ comment.text }}
+
{{ comment.text }}
} diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.scss b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.scss index 702bc576e..b36407be4 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.scss +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.scss @@ -84,7 +84,7 @@ ngx-monaco-editor { .right-container { display: flex; - width: 375px; + width: 750px; min-width: 375px; padding: 16px 24px 16px 24px; @@ -96,3 +96,7 @@ ngx-monaco-editor { width: 100%; } } + +.text-auto { + text-wrap: auto; +} diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts index 6ccd48108..05080d64f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen/rules-screen.component.ts @@ -1,5 +1,5 @@ -import { AsyncPipe, NgIf, NgTemplateOutlet } from '@angular/common'; -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, inject, input, OnInit, signal } from '@angular/core'; +import { NgIf, NgTemplateOutlet } from '@angular/common'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, inject, input, OnInit, signal, viewChild } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormsModule } from '@angular/forms'; import { MatIcon } from '@angular/material/icon'; @@ -17,8 +17,8 @@ import { CopilotService } from '@services/copilot.service'; import { EditorThemeService } from '@services/editor-theme.service'; import { PermissionsService } from '@services/permissions.service'; import { DatePipe } from '@shared/pipes/date.pipe'; -import { BehaviorSubject, firstValueFrom } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; +import { firstValueFrom } from 'rxjs'; +import { map } from 'rxjs/operators'; import { RulesService } from '../../../services/rules.service'; import { rulesScreenTranslations } from '../../../translations/rules-screen-translations'; import ICodeEditor = monaco.editor.ICodeEditor; @@ -38,6 +38,21 @@ interface UploadResponse { deprecatedWarnings: SyntaxError[]; } +export const SentenceTypes = { + question: 'question', + answer: 'answer', +} as const; + +export type SentenceType = keyof typeof SentenceTypes; + +interface Sentence { + text: string | null; + date: string; + type: SentenceType; +} + +const endingSentence: Sentence = { text: null, date: new Date().toISOString(), type: SentenceTypes.answer }; + const RULE_VALIDATION_TIMEOUT = 2000; @Component({ @@ -52,7 +67,6 @@ const RULE_VALIDATION_TIMEOUT = 2000; IconButtonComponent, NgIf, TranslateModule, - AsyncPipe, NgTemplateOutlet, CircleButtonComponent, DatePipe, @@ -68,11 +82,13 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv #ruleValidationTimeout: number = null; readonly #copilotService = inject(CopilotService); readonly #currentUser = getCurrentUser(); + readonly #conversation = signal([endingSentence]); protected readonly collapsed = signal(true); protected readonly IqserTooltipPositions = IqserTooltipPositions; readonly dossierTemplateId = input.required(); readonly translations = rulesScreenTranslations; readonly iconButtonTypes = IconButtonTypes; + readonly inputWithAction = viewChild(InputWithActionComponent); readonly editorOptions: IStandaloneEditorConstructionOptions = { theme: 'vs', language: 'java', @@ -87,7 +103,7 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv readonly type = input.required(); readonly numberOfErrors = computed(() => this.#errors().filter(e => !e.warning).length); readonly numberOfWarnings = computed(() => this.#errors().filter(e => e.warning).length); - readonly responses$ = new BehaviorSubject<{ text: string; date: string }[]>([]); + readonly conversation = computed(() => this.#conversation().filter(r => !!r.text)); constructor( readonly permissionsService: PermissionsService, @@ -104,11 +120,18 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv .pipe( takeUntilDestroyed(), map(res => res?.token), - filter(Boolean), ) - .subscribe(response => { - console.log('WS response: ' + response); - this.responses$.next([...this.responses$.value, { text: response, date: new Date().toISOString() }]); + .subscribe(token => { + console.log('WS token: ' + token); + if (token === null) { + console.log(this.#conversation()); + this.#conversation.update(responses => [...responses, { ...endingSentence }]); + return; + } + this.#conversation.update(responses => { + const last = responses.pop(); + return [...responses, { ...last, text: (last.text ?? '') + token }]; + }); }); this.#copilotService.send('manageradmin'); @@ -135,7 +158,15 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv } add(question: string) { - console.log(question); + this.#conversation.update(responses => { + const last = responses.pop(); + last.text = question; + last.type = SentenceTypes.question; + last.date = new Date().toISOString(); + return [...responses, last, { ...endingSentence }]; + }); + console.log(this.#conversation()); + this.inputWithAction().reset(); this.#copilotService.send(question); }