copilot ws implementation, wip
This commit is contained in:
parent
59ce4177d2
commit
e41ac70dfe
@ -1,22 +1,24 @@
|
||||
import { CompositeRouteGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui';
|
||||
import { RedRoleGuard } from '@users/red-role.guard';
|
||||
import { EntitiesListingScreenComponent } from './screens/entities-listing/entities-listing-screen.component';
|
||||
import { ENVIRONMENT_INITIALIZER, inject } from '@angular/core';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { DefaultColorsScreenComponent } from './screens/default-colors/default-colors-screen.component';
|
||||
import { UserListingScreenComponent } from './screens/user-listing/user-listing-screen.component';
|
||||
import { DigitalSignatureScreenComponent } from './screens/digital-signature/digital-signature-screen.component';
|
||||
import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
import { templateExistsWhenEnteringAdmin } from '@guards/dossier-template-exists.guard';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { entityExistsGuard } from '@guards/entity-exists-guard.service';
|
||||
import { PermissionsGuard } from '@guards/permissions-guard';
|
||||
import { CompositeRouteGuard, IqserPermissionsGuard, IqserRoutes } from '@iqser/common-ui';
|
||||
import { IqserAuthGuard } from '@iqser/common-ui/lib/users';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@red/domain';
|
||||
import { CopilotService } from '@services/copilot.service';
|
||||
import { RedRoleGuard } from '@users/red-role.guard';
|
||||
import { Roles } from '@users/roles';
|
||||
import { BaseAdminScreenComponent } from './base-admin-screen/base-admin-screen.component';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@red/domain';
|
||||
import { templateExistsWhenEnteringAdmin } from '@guards/dossier-template-exists.guard';
|
||||
import { entityExistsGuard } from '@guards/entity-exists-guard.service';
|
||||
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
|
||||
import { PermissionsGuard } from '@guards/permissions-guard';
|
||||
import { Roles } from '@users/roles';
|
||||
import { IqserAuthGuard } from '@iqser/common-ui/lib/users';
|
||||
import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { DefaultColorsScreenComponent } from './screens/default-colors/default-colors-screen.component';
|
||||
import { DigitalSignatureScreenComponent } from './screens/digital-signature/digital-signature-screen.component';
|
||||
import { EntitiesListingScreenComponent } from './screens/entities-listing/entities-listing-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
import { UserListingScreenComponent } from './screens/user-listing/user-listing-screen.component';
|
||||
import { AdminDialogService } from './services/admin-dialog.service';
|
||||
import { AuditService } from './services/audit.service';
|
||||
import { DigitalSignatureService } from './services/digital-signature.service';
|
||||
@ -78,7 +80,22 @@ const dossierTemplateIdRoutes: IqserRoutes = [
|
||||
},
|
||||
type: 'ENTITY',
|
||||
},
|
||||
providers: [RulesService],
|
||||
providers: [
|
||||
RulesService,
|
||||
{
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
multi: true,
|
||||
useFactory: () => {
|
||||
const service = inject(CopilotService);
|
||||
return () => {
|
||||
setTimeout(() => {
|
||||
service.connect('/api/llm/llm-websocket');
|
||||
console.log('Copilot ready');
|
||||
}, 2000);
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'component-rules',
|
||||
|
||||
@ -1,9 +1,57 @@
|
||||
<div class="header-container">
|
||||
<div [translate]="translations[this.type]['title']" class="heading-l"></div>
|
||||
<div [translate]="translations[this.type]['warning-text']" class="error"></div>
|
||||
<div [translate]="translations[type()]['title']" class="heading-l"></div>
|
||||
<div [translate]="translations[type()]['warning-text']" class="error"></div>
|
||||
</div>
|
||||
|
||||
<ngx-monaco-editor (init)="onCodeEditorInit($event)" [(ngModel)]="codeEditorText" [options]="editorOptions"></ngx-monaco-editor>
|
||||
<div class="flex" style="height: 100%">
|
||||
<ngx-monaco-editor (init)="onCodeEditorInit($event)" [(ngModel)]="codeEditorText" [options]="editorOptions"></ngx-monaco-editor>
|
||||
|
||||
<div [class.collapsed]="collapsed()" class="right-container flex-column">
|
||||
<div class="collapsed-wrapper">
|
||||
<ng-container *ngTemplateOutlet="collapsible; context: { action: 'expand', tooltip: ('copilot' | translate) }"></ng-container>
|
||||
<div class="all-caps-label" translate="dossier-details.title"></div>
|
||||
</div>
|
||||
|
||||
<div class="header-wrapper flex mt-8">
|
||||
<div class="heading-xl flex-1" id="dossierDetailsDossierName">Copilot</div>
|
||||
<ng-container *ngTemplateOutlet="collapsible; context: { action: 'collapse', tooltip: ('copilot' | translate) }"></ng-container>
|
||||
</div>
|
||||
|
||||
<div class="mt-24">
|
||||
@for (comment of responses$ | async; track comment) {
|
||||
<div class="comment">
|
||||
<div class="comment-details-wrapper">
|
||||
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
|
||||
{{ comment.date | date: 'sophisticatedDate' }}
|
||||
</div>
|
||||
|
||||
<!-- <div class="comment-actions">-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
|
||||
<div>{{ comment.text }}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<iqser-input-with-action
|
||||
(action)="add($event)"
|
||||
[placeholder]="'comments.add-comment' | translate"
|
||||
autocomplete="off"
|
||||
icon="iqser:collapse"
|
||||
width="full"
|
||||
></iqser-input-with-action>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #collapsible let-action="action" let-tooltip="tooltip">
|
||||
<iqser-circle-button
|
||||
(action)="collapsed.set(!collapsed())"
|
||||
[icon]="'iqser:' + action"
|
||||
[tooltipPosition]="IqserTooltipPositions.before"
|
||||
[tooltip]="tooltip"
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
<div *ngIf="changed && permissionsService.canEditRules() && !isLeaving" class="changes-box">
|
||||
<div (click)="goToErrors()" *ngIf="numberOfErrors() || numberOfWarnings()" class="errors">
|
||||
@ -13,15 +61,15 @@
|
||||
<span
|
||||
*ngIf="numberOfErrors()"
|
||||
[translateParams]="{ errors: numberOfErrors() }"
|
||||
[translate]="translations[this.type]['errors-found']"
|
||||
[translate]="translations[type()]['errors-found']"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
*ngIf="numberOfWarnings()"
|
||||
[translateParams]="{ warnings: numberOfWarnings() }"
|
||||
[translate]="translations[this.type]['warnings-found']"
|
||||
class="warning"
|
||||
[class.only-warning]="!numberOfErrors()"
|
||||
[translateParams]="{ warnings: numberOfWarnings() }"
|
||||
[translate]="translations[type()]['warnings-found']"
|
||||
class="warning"
|
||||
></span>
|
||||
</div>
|
||||
</span>
|
||||
@ -30,11 +78,11 @@
|
||||
<div class="actions">
|
||||
<iqser-icon-button
|
||||
(action)="save()"
|
||||
[label]="translations[this.type]['save-changes'] | translate"
|
||||
[label]="translations[type()]['save-changes'] | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:check"
|
||||
></iqser-icon-button>
|
||||
|
||||
<div (click)="revert()" [translate]="translations[this.type]['revert-changes']" class="all-caps-label cancel"></div>
|
||||
<div (click)="revert()" [translate]="translations[type()]['revert-changes']" class="all-caps-label cancel"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -81,3 +81,18 @@ ngx-monaco-editor {
|
||||
gap: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-container {
|
||||
display: flex;
|
||||
width: 375px;
|
||||
min-width: 375px;
|
||||
padding: 16px 24px 16px 24px;
|
||||
|
||||
&.has-scrollbar:hover {
|
||||
padding-right: 13px;
|
||||
}
|
||||
|
||||
redaction-dossier-details {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, OnInit, signal } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { IconButtonComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { RulesService } from '../../../services/rules.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_TEMPLATE_ID, DroolsKeywords, IRules } from '@red/domain';
|
||||
import { EditorThemeService } from '@services/editor-theme.service';
|
||||
import { AsyncPipe, NgForOf, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, inject, input, OnInit, signal } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { InputWithActionComponent } from '@common-ui/inputs/input-with-action/input-with-action.component';
|
||||
import { TenantsService } from '@common-ui/tenants';
|
||||
import { getCurrentUser } from '@common-ui/users';
|
||||
import { NamePipe } from '@common-ui/users/name.pipe';
|
||||
import { ComponentCanDeactivate } from '@guards/can-deactivate.guard';
|
||||
import { Debounce, getParam } from '@iqser/common-ui/lib/utils';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { Debounce, IqserTooltipPositions } from '@iqser/common-ui/lib/utils';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DroolsKeywords, IRules } from '@red/domain';
|
||||
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 { RulesService } from '../../../services/rules.service';
|
||||
import { rulesScreenTranslations } from '../../../translations/rules-screen-translations';
|
||||
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
interface SyntaxError {
|
||||
line: number;
|
||||
@ -38,11 +45,35 @@ const RULE_VALIDATION_TIMEOUT = 2000;
|
||||
styleUrls: ['./rules-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [MonacoEditorModule, MatIcon, FormsModule, IconButtonComponent, NgIf, TranslateModule],
|
||||
imports: [
|
||||
MonacoEditorModule,
|
||||
MatIcon,
|
||||
FormsModule,
|
||||
IconButtonComponent,
|
||||
NgIf,
|
||||
TranslateModule,
|
||||
AsyncPipe,
|
||||
NgTemplateOutlet,
|
||||
CircleButtonComponent,
|
||||
DatePipe,
|
||||
InputWithActionComponent,
|
||||
NamePipe,
|
||||
NgForOf,
|
||||
MatTooltip,
|
||||
],
|
||||
})
|
||||
export default class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
||||
readonly #errorGlyphs = signal<string[]>([]);
|
||||
#codeEditor: ICodeEditor;
|
||||
#decorations: string[] = [];
|
||||
readonly #errors = signal<SyntaxError[]>([]);
|
||||
#ruleValidationTimeout: number = null;
|
||||
readonly #copilotService = inject(CopilotService);
|
||||
readonly #currentUser = getCurrentUser();
|
||||
protected readonly collapsed = signal(true);
|
||||
protected readonly IqserTooltipPositions = IqserTooltipPositions;
|
||||
readonly dossierTemplateId = input.required<string>();
|
||||
readonly translations = rulesScreenTranslations;
|
||||
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly editorOptions: IStandaloneEditorConstructionOptions = {
|
||||
theme: 'vs',
|
||||
@ -55,15 +86,33 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
initialLines: string[] = [];
|
||||
currentLines: string[] = [];
|
||||
isLeaving = false;
|
||||
readonly type: IRules['ruleFileType'];
|
||||
readonly #errorGlyphs = signal<string[]>([]);
|
||||
readonly type = input.required<IRules['ruleFileType']>();
|
||||
readonly numberOfErrors = computed(() => this.#errors().filter(e => !e.warning).length);
|
||||
readonly numberOfWarnings = computed(() => this.#errors().filter(e => e.warning).length);
|
||||
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||
#codeEditor: ICodeEditor;
|
||||
#decorations: string[] = [];
|
||||
#errors = signal<SyntaxError[]>([]);
|
||||
#ruleValidationTimeout: number = null;
|
||||
readonly responses$ = new BehaviorSubject<{ text: string; date: string }[]>([]);
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _rulesService: RulesService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _editorThemeService: EditorThemeService,
|
||||
) {
|
||||
const username = this.#currentUser.username;
|
||||
const tenant = inject(TenantsService).activeTenantId;
|
||||
this.#copilotService
|
||||
.listen('/user/' + username + '/queue/' + tenant + '/rules-copilot')
|
||||
.pipe(takeUntilDestroyed())
|
||||
.subscribe(response => {
|
||||
console.log('WS response: ' + response);
|
||||
});
|
||||
|
||||
this.#copilotService.publish({
|
||||
destination: '/app/rules-copilot',
|
||||
body: JSON.stringify({ prompts: ['manageradmin'] }),
|
||||
});
|
||||
}
|
||||
|
||||
set isLeavingPage(isLeaving: boolean) {
|
||||
this.isLeaving = isLeaving;
|
||||
@ -85,16 +134,13 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
this.#closeProblemsView();
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _rulesService: RulesService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _editorThemeService: EditorThemeService,
|
||||
private readonly _route: ActivatedRoute,
|
||||
) {
|
||||
this.type = this._route.snapshot.data.type;
|
||||
add(question: string) {
|
||||
console.log(question);
|
||||
this.responses$.next([...this.responses$.value, { text: question, date: new Date().toISOString() }]);
|
||||
this.#copilotService.publish({
|
||||
destination: '/app/rules-copilot',
|
||||
body: JSON.stringify({ prompts: [question] }),
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -142,12 +188,20 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
await this.#uploadRules();
|
||||
}
|
||||
|
||||
revert(): void {
|
||||
this.currentLines = this.initialLines;
|
||||
this.#decorations = this.#codeEditor?.deltaDecorations(this.#decorations, []) || [];
|
||||
this.#removeErrorMarkers();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async #uploadRules(dryRun = false) {
|
||||
return firstValueFrom(
|
||||
this._rulesService.uploadRules({
|
||||
rules: this.#getValue(),
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
ruleFileType: this.type,
|
||||
dossierTemplateId: this.dossierTemplateId(),
|
||||
ruleFileType: this.type(),
|
||||
dryRun,
|
||||
}),
|
||||
).then(
|
||||
@ -156,7 +210,7 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
this.#drawErrorMarkers(errors);
|
||||
if (!dryRun) {
|
||||
await this.#initialize();
|
||||
this._toaster.success(rulesScreenTranslations[this.type]['success.generic']);
|
||||
this._toaster.success(rulesScreenTranslations[this.type()]['success.generic']);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
@ -173,20 +227,12 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
this.#drawErrorMarkers(errors);
|
||||
this._loadingService.stop();
|
||||
if (!dryRun) {
|
||||
this._toaster.error(rulesScreenTranslations[this.type]['error.generic']);
|
||||
this._toaster.error(rulesScreenTranslations[this.type()]['error.generic']);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
revert(): void {
|
||||
this.currentLines = this.initialLines;
|
||||
this.#decorations = this.#codeEditor?.deltaDecorations(this.#decorations, []) || [];
|
||||
this.#removeErrorMarkers();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
#mapErrors(response: UploadResponse, dryRun = false) {
|
||||
const warnings = response.deprecatedWarnings.map(w => ({ ...w, warning: true }));
|
||||
if (dryRun) {
|
||||
@ -296,7 +342,7 @@ export default class RulesScreenComponent implements OnInit, ComponentCanDeactiv
|
||||
|
||||
async #initialize() {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._rulesService.download(this.#dossierTemplateId, this.type)).then(
|
||||
await firstValueFrom(this._rulesService.download(this.dossierTemplateId(), this.type())).then(
|
||||
rules => {
|
||||
this.currentLines = this.initialLines = rules.rules.split('\n');
|
||||
this.revert();
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
import { Component, ElementRef, HostListener, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
CustomError,
|
||||
ErrorService,
|
||||
HasScrollbarDirective,
|
||||
IqserListingModule,
|
||||
IqserPermissionsService,
|
||||
ListingComponent,
|
||||
@ -16,6 +18,7 @@ import {
|
||||
} from '@iqser/common-ui';
|
||||
import { NestedFilter } from '@iqser/common-ui/lib/filtering';
|
||||
import { getParam, OnAttach, OnDetach, shareLast } from '@iqser/common-ui/lib/utils';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import {
|
||||
Dossier,
|
||||
DOSSIER_ID,
|
||||
@ -26,6 +29,7 @@ import {
|
||||
WorkflowFileStatus,
|
||||
} from '@red/domain';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { DossierAttributesService } from '@services/entity-services/dossier-attributes.service';
|
||||
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
|
||||
@ -33,6 +37,7 @@ import { FileAttributesService } from '@services/entity-services/file-attributes
|
||||
import { FilesMapService } from '@services/files/files-map.service';
|
||||
import { FilesService } from '@services/files/files.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.component';
|
||||
import { FileUploadModel } from '@upload-download/model/file-upload.model';
|
||||
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
|
||||
import { FileUploadService } from '@upload-download/services/file-upload.service';
|
||||
@ -42,17 +47,13 @@ import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { convertFiles, Files, handleFileDrop } from '@utils/index';
|
||||
import { merge, Observable } from 'rxjs';
|
||||
import { filter, skip, switchMap, tap } from 'rxjs/operators';
|
||||
import { DossierOverviewBulkActionsComponent } from '../components/bulk-actions/dossier-overview-bulk-actions.component';
|
||||
import { DossierDetailsComponent } from '../components/dossier-details/dossier-details.component';
|
||||
import { DossierOverviewScreenHeaderComponent } from '../components/screen-header/dossier-overview-screen-header.component';
|
||||
import { TableItemComponent } from '../components/table-item/table-item.component';
|
||||
import { WorkflowItemComponent } from '../components/workflow-item/workflow-item.component';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { BulkActionsService } from '../services/bulk-actions.service';
|
||||
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
||||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
import { DossierOverviewScreenHeaderComponent } from '../components/screen-header/dossier-overview-screen-header.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { WorkflowItemComponent } from '../components/workflow-item/workflow-item.component';
|
||||
import { DossierDetailsComponent } from '../components/dossier-details/dossier-details.component';
|
||||
import { DossierOverviewBulkActionsComponent } from '../components/bulk-actions/dossier-overview-bulk-actions.component';
|
||||
import { TableItemComponent } from '../components/table-item/table-item.component';
|
||||
import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
@ -70,6 +71,7 @@ import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.
|
||||
DossierOverviewBulkActionsComponent,
|
||||
TableItemComponent,
|
||||
TypeFilterComponent,
|
||||
HasScrollbarDirective,
|
||||
],
|
||||
})
|
||||
export default class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnAttach, OnDetach, OnDestroy {
|
||||
|
||||
@ -6,6 +6,7 @@ import { AnnotationActionsService } from './services/annotation-actions.service'
|
||||
import { AnnotationProcessingService } from './services/annotation-processing.service';
|
||||
import { AnnotationReferencesService } from './services/annotation-references.service';
|
||||
import { AnnotationsListingService } from './services/annotations-listing.service';
|
||||
import { ComponentLogFilterService } from './services/component-log-filter.service';
|
||||
import { DocumentInfoService } from './services/document-info.service';
|
||||
import { ExcludedPagesService } from './services/excluded-pages.service';
|
||||
import { FileDataService } from './services/file-data.service';
|
||||
@ -16,7 +17,6 @@ import { PdfProxyService } from './services/pdf-proxy.service';
|
||||
import { SkippedService } from './services/skipped.service';
|
||||
import { StampService } from './services/stamp.service';
|
||||
import { ViewModeService } from './services/view-mode.service';
|
||||
import { ComponentLogFilterService } from './services/component-log-filter.service';
|
||||
|
||||
export const filePreviewScreenProviders = [
|
||||
FilterService,
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { IqserRoutes } from '@iqser/common-ui';
|
||||
import { FilePreviewScreenComponent } from './file-preview-screen.component';
|
||||
import { ENVIRONMENT_INITIALIZER, inject } from '@angular/core';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { IqserRoutes } from '@iqser/common-ui';
|
||||
import { WebSocketService } from '@services/web-socket.service';
|
||||
import { FileAssignService } from '../shared-dossiers/services/file-assign.service';
|
||||
import { FilePreviewScreenComponent } from './file-preview-screen.component';
|
||||
import { DocumentUnloadedGuard } from './services/document-unloaded.guard';
|
||||
import { FilePreviewDialogService } from './services/file-preview-dialog.service';
|
||||
import { ManualRedactionService } from './services/manual-redaction.service';
|
||||
import { TablesService } from './services/tables.service';
|
||||
import { FileAssignService } from '../shared-dossiers/services/file-assign.service';
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -13,6 +15,22 @@ export default [
|
||||
component: FilePreviewScreenComponent,
|
||||
pathMatch: 'full',
|
||||
canDeactivate: [PendingChangesGuard, DocumentUnloadedGuard],
|
||||
providers: [FilePreviewDialogService, ManualRedactionService, DocumentUnloadedGuard, TablesService, FileAssignService],
|
||||
providers: [
|
||||
FilePreviewDialogService,
|
||||
ManualRedactionService,
|
||||
DocumentUnloadedGuard,
|
||||
TablesService,
|
||||
FileAssignService,
|
||||
{
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
multi: true,
|
||||
useFactory: () => {
|
||||
const service = inject(WebSocketService);
|
||||
return () => {
|
||||
setTimeout(() => service.connect('/redaction-gateway-v1/websocket'), 2000);
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies IqserRoutes;
|
||||
|
||||
11
apps/red-ui/src/app/services/copilot.service.ts
Normal file
11
apps/red-ui/src/app/services/copilot.service.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { WebSocketService } from '@services/web-socket.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class CopilotService extends WebSocketService {
|
||||
get topicPrefix(): string {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { DestroyRef, inject, Injectable } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { TenantsService } from '@common-ui/tenants';
|
||||
import { log } from '@common-ui/utils';
|
||||
import { getConfig } from '@iqser/common-ui';
|
||||
@ -16,17 +17,21 @@ export class WebSocketService extends RxStomp {
|
||||
readonly #logger = inject(NGXLogger);
|
||||
readonly #config = getConfig();
|
||||
readonly #tenantService = inject(TenantsService);
|
||||
readonly #destroyRef = inject(DestroyRef);
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
setTimeout(() => this.connect(), 1000);
|
||||
}
|
||||
|
||||
get topicPrefix() {
|
||||
return '/topic/' + this.#tenantService.activeTenantId + '/';
|
||||
}
|
||||
|
||||
watch(opts: IWatchParams): Observable<IMessage>;
|
||||
watch(destination: string, headers?: StompHeaders): Observable<IMessage>;
|
||||
watch(opts: string | IWatchParams, headers?: StompHeaders): Observable<IMessage> {
|
||||
if (typeof opts === 'string') {
|
||||
return super.watch('/topic/' + this.#tenantService.activeTenantId + '/' + opts, headers);
|
||||
return super.watch(this.topicPrefix + opts, headers);
|
||||
}
|
||||
|
||||
return super.watch(opts);
|
||||
@ -36,13 +41,15 @@ export class WebSocketService extends RxStomp {
|
||||
return this.watch(topic).pipe(map(msg => JSON.parse(msg.body)));
|
||||
}
|
||||
|
||||
private connect() {
|
||||
connect(url: string) {
|
||||
const headers = { Authorization: 'Bearer ' + localStorage.getItem('token') };
|
||||
console.log(headers);
|
||||
this.configure({
|
||||
debug: (msg: string) => this.#logger.debug(msg),
|
||||
brokerURL: this.#config.API_URL + '/redaction-gateway-v1/websocket',
|
||||
brokerURL: this.#config.API_URL + url,
|
||||
connectHeaders: headers,
|
||||
});
|
||||
|
||||
this.connectionState$.pipe(log('[WS] Connection state')).subscribe();
|
||||
this.webSocketErrors$.pipe(log('[WS] Errors')).subscribe();
|
||||
this.stompErrors$
|
||||
@ -52,6 +59,7 @@ export class WebSocketService extends RxStomp {
|
||||
console.error('Broker reported error: ' + frame.headers['message']);
|
||||
console.error('Additional details: ' + frame.body);
|
||||
}),
|
||||
takeUntilDestroyed(this.#destroyRef),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ADMIN_CONTACT_NAME": null,
|
||||
"ADMIN_CONTACT_URL": null,
|
||||
"API_URL": "https://dan2.iqser.cloud",
|
||||
"API_URL": "https://dan1.iqser.cloud",
|
||||
"APP_NAME": "RedactManager",
|
||||
"IS_DOCUMINE": false,
|
||||
"RULE_EDITOR_DEV_ONLY": false,
|
||||
@ -13,7 +13,7 @@
|
||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||
"OAUTH_CLIENT_ID": "redaction",
|
||||
"OAUTH_IDP_HINT": null,
|
||||
"OAUTH_URL": "https://dan2.iqser.cloud/auth",
|
||||
"OAUTH_URL": "https://dan1.iqser.cloud/auth",
|
||||
"RECENT_PERIOD_IN_HOURS": 24,
|
||||
"SELECTION_MODE": "structural",
|
||||
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit c331a61309dfa220a5c83228438bc138539d2045
|
||||
Subproject commit 17943f2e8dcab28450e9102d6e8b7a0b5f7227db
|
||||
Loading…
x
Reference in New Issue
Block a user