Merge branch 'DM-424/408' into 'master'
DM-424, add component rule screen + deps. DM-408, fix translations, close... Closes DM-424 See merge request redactmanager/red-ui!64
This commit is contained in:
commit
79d4cb1b8e
@ -61,6 +61,19 @@ const dossierTemplateIdRoutes: IqserRoutes = [
|
|||||||
},
|
},
|
||||||
loadChildren: () => import('./screens/rules/rules.module').then(m => m.RulesModule),
|
loadChildren: () => import('./screens/rules/rules.module').then(m => m.RulesModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'component-rules',
|
||||||
|
component: BaseDossierTemplateScreenComponent,
|
||||||
|
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
|
||||||
|
data: {
|
||||||
|
routeGuards: [IqserAuthGuard, RedRoleGuard],
|
||||||
|
permissions: {
|
||||||
|
allow: [Roles.rules.read],
|
||||||
|
redirectTo: 'info',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loadChildren: () => import('./screens/component-rules/component-rules.module').then(m => m.ComponentRulesModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'file-attributes',
|
path: 'file-attributes',
|
||||||
component: BaseDossierTemplateScreenComponent,
|
component: BaseDossierTemplateScreenComponent,
|
||||||
|
|||||||
@ -57,6 +57,7 @@ import { DossierTemplateActionsComponent } from './shared/components/dossier-tem
|
|||||||
import { IqserUsersModule } from '@iqser/common-ui/lib/users';
|
import { IqserUsersModule } from '@iqser/common-ui/lib/users';
|
||||||
import { TenantPipe } from '@iqser/common-ui/lib/tenants';
|
import { TenantPipe } from '@iqser/common-ui/lib/tenants';
|
||||||
import { SelectComponent } from '@shared/components/select/select.component';
|
import { SelectComponent } from '@shared/components/select/select.component';
|
||||||
|
import { ComponentRulesService } from './services/component-rules.service';
|
||||||
|
|
||||||
const dialogs = [
|
const dialogs = [
|
||||||
AddEditCloneDossierTemplateDialogComponent,
|
AddEditCloneDossierTemplateDialogComponent,
|
||||||
@ -97,7 +98,7 @@ const components = [
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [...components],
|
declarations: [...components],
|
||||||
providers: [AdminDialogService, AuditService, DigitalSignatureService, RulesService, SmtpConfigService],
|
providers: [AdminDialogService, AuditService, DigitalSignatureService, RulesService, ComponentRulesService, SmtpConfigService],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { ComponentRulesScreenComponent } from './rules-screen/component-rules-screen.component';
|
||||||
|
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||||
|
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { IconButtonComponent } from '@iqser/common-ui';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
|
||||||
|
const routes = [{ path: '', component: ComponentRulesScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [ComponentRulesScreenComponent],
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes),
|
||||||
|
CommonModule,
|
||||||
|
MonacoEditorModule,
|
||||||
|
TranslateModule,
|
||||||
|
IconButtonComponent,
|
||||||
|
FormsModule,
|
||||||
|
MatIconModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ComponentRulesModule {}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<div class="header-container">
|
||||||
|
<div [translate]="'component-rules-screen.title'" class="heading-l"></div>
|
||||||
|
<div [translate]="'component-rules-screen.warning-text'" class="error"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ngx-monaco-editor (init)="onCodeEditorInit($event)" [(ngModel)]="codeEditorText" [options]="editorOptions"></ngx-monaco-editor>
|
||||||
|
|
||||||
|
<div *ngIf="changed && permissionsService.canEditRules() && !isLeaving" class="changes-box">
|
||||||
|
<div (click)="goToErrors()" *ngIf="numberOfErrors()" class="errors">
|
||||||
|
<span>
|
||||||
|
<mat-icon [svgIcon]="'iqser:alert-circle'" class="icon"></mat-icon>
|
||||||
|
<span [translateParams]="{ errors: numberOfErrors() }" [translate]="'component-rules-screen.errors-found'"></span>
|
||||||
|
</span>
|
||||||
|
<mat-icon [svgIcon]="'iqser:expand'" class="icon face-up"></mat-icon>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<iqser-icon-button
|
||||||
|
(action)="save()"
|
||||||
|
[label]="'component-rules-screen.save-changes' | translate"
|
||||||
|
[type]="iconButtonTypes.primary"
|
||||||
|
icon="iqser:check"
|
||||||
|
></iqser-icon-button>
|
||||||
|
|
||||||
|
<div (click)="revert()" [translate]="'component-rules-screen.revert-changes'" class="all-caps-label cancel"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
:host {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 15px 0 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx-monaco-editor {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
margin-left: 30px;
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
font-size: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.changes-box {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: start;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errors {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
scale: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
/* TODO: Update this to --iqser-error when added */
|
||||||
|
color: #dd4d50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.face-up {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,216 @@
|
|||||||
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, ElementRef, OnInit, signal, ViewChild } from '@angular/core';
|
||||||
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
|
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
import { DOSSIER_TEMPLATE_ID } from '@red/domain';
|
||||||
|
import { EditorThemeService } from '@services/editor-theme.service';
|
||||||
|
import { ComponentCanDeactivate } from '@guards/can-deactivate.guard';
|
||||||
|
import { Debounce, getParam } from '@iqser/common-ui/lib/utils';
|
||||||
|
import { ComponentRulesService } from '../../../services/component-rules.service';
|
||||||
|
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||||
|
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||||
|
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||||
|
|
||||||
|
interface SyntaxError {
|
||||||
|
line: number;
|
||||||
|
column: number;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './component-rules-screen.component.html',
|
||||||
|
styleUrls: ['./component-rules-screen.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class ComponentRulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
||||||
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
|
readonly editorOptions: IStandaloneEditorConstructionOptions = {
|
||||||
|
theme: 'vs',
|
||||||
|
language: 'java',
|
||||||
|
automaticLayout: true,
|
||||||
|
readOnly: !this.permissionsService.canEditRules(),
|
||||||
|
glyphMargin: true,
|
||||||
|
};
|
||||||
|
initialLines: string[] = [];
|
||||||
|
currentLines: string[] = [];
|
||||||
|
isLeaving = false;
|
||||||
|
@ViewChild('fileInput')
|
||||||
|
private _fileInput: ElementRef;
|
||||||
|
private _codeEditor: ICodeEditor;
|
||||||
|
private _decorations: string[] = [];
|
||||||
|
readonly #errorGlyphs = signal<string[]>([]);
|
||||||
|
readonly numberOfErrors = computed(() => this.#errorGlyphs().length);
|
||||||
|
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly permissionsService: PermissionsService,
|
||||||
|
private readonly _componentRulesService: ComponentRulesService,
|
||||||
|
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private readonly _toaster: Toaster,
|
||||||
|
private readonly _loadingService: LoadingService,
|
||||||
|
private readonly _editorThemeService: EditorThemeService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
set isLeavingPage(isLeaving: boolean) {
|
||||||
|
this.isLeaving = isLeaving;
|
||||||
|
this._changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
get changed(): boolean {
|
||||||
|
return this.currentLines.toString() !== this.initialLines.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
get codeEditorText() {
|
||||||
|
return this.currentLines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
set codeEditorText($event: any) {
|
||||||
|
this.currentLines = $event.split('\n');
|
||||||
|
this.codeEditorTextChanged();
|
||||||
|
this._closeProblemsView();
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
await this._initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCodeEditorInit(editor: ICodeEditor) {
|
||||||
|
this._codeEditor = editor;
|
||||||
|
for (const theme of this._editorThemeService.themes) {
|
||||||
|
(window as any).monaco.editor.defineTheme(theme, this._editorThemeService.configurations[theme]);
|
||||||
|
}
|
||||||
|
(window as any).monaco.editor.setTheme(this._editorThemeService.getTheme(true));
|
||||||
|
this._changeDetectorRef.detectChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce()
|
||||||
|
codeEditorTextChanged() {
|
||||||
|
const newDecorations = this.currentLines.filter(entry => this._isNew(entry)).map(entry => this._makeDecorationFor(entry));
|
||||||
|
this._decorations = this._codeEditor.deltaDecorations(this._decorations, newDecorations);
|
||||||
|
}
|
||||||
|
|
||||||
|
goToErrors() {
|
||||||
|
this._codeEditor.trigger(null, 'editor.action.marker.next', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(): Promise<void> {
|
||||||
|
this._loadingService.start();
|
||||||
|
this._removeErrorMarkers();
|
||||||
|
await firstValueFrom(
|
||||||
|
this._componentRulesService.uploadRules({
|
||||||
|
rules: this._codeEditor.getModel().getValue(),
|
||||||
|
dossierTemplateId: this.#dossierTemplateId,
|
||||||
|
}),
|
||||||
|
).then(
|
||||||
|
async () => {
|
||||||
|
await this._initialize();
|
||||||
|
this._toaster.success(_('component-rules-screen.success.generic'));
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
const errors = error.error as SyntaxError[] | undefined;
|
||||||
|
this._drawErrorMarkers(errors);
|
||||||
|
this._loadingService.stop();
|
||||||
|
this._toaster.error(_('component-rules-screen.error.generic'));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
revert(): void {
|
||||||
|
this.currentLines = this.initialLines;
|
||||||
|
this._decorations = this._codeEditor?.deltaDecorations(this._decorations, []) || [];
|
||||||
|
this._removeErrorMarkers();
|
||||||
|
this._changeDetectorRef.detectChanges();
|
||||||
|
this._loadingService.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
download(): void {
|
||||||
|
const content = this._codeEditor.getModel().getValue();
|
||||||
|
const blob = new Blob([content], {
|
||||||
|
type: 'text/plain;charset=utf-8',
|
||||||
|
});
|
||||||
|
saveAs(blob, 'rules.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
upload($event): void {
|
||||||
|
const file: File = $event.target.files[0];
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
fileReader.onload = () => {
|
||||||
|
this._codeEditor.getModel().setValue(fileReader.result as string);
|
||||||
|
this._fileInput.nativeElement.value = null;
|
||||||
|
};
|
||||||
|
fileReader.readAsText(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isNew(entry: string): boolean {
|
||||||
|
return this.initialLines.indexOf(entry) < 0 && entry?.trim().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _makeDecorationFor(entry: string): IModelDeltaDecoration {
|
||||||
|
const line = this.currentLines.indexOf(entry) + 1;
|
||||||
|
|
||||||
|
return {
|
||||||
|
range: new monaco.Range(line, 1, line, 1),
|
||||||
|
options: { isWholeLine: true, className: 'changed-row-marker' },
|
||||||
|
} as IModelDeltaDecoration;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _drawErrorMarkers(errors: SyntaxError[] | undefined) {
|
||||||
|
const model = this._codeEditor?.getModel();
|
||||||
|
if (!model || !errors?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const markers = [];
|
||||||
|
const glyphs = [];
|
||||||
|
errors
|
||||||
|
.filter(e => e.line > 0)
|
||||||
|
.forEach(e => {
|
||||||
|
const endColumn = model.getLineLength(e.line) + 1;
|
||||||
|
markers.push({
|
||||||
|
message: e.message,
|
||||||
|
severity: monaco.MarkerSeverity.Error,
|
||||||
|
startLineNumber: e.line,
|
||||||
|
startColumn: e.column,
|
||||||
|
endLineNumber: e.line,
|
||||||
|
endColumn,
|
||||||
|
});
|
||||||
|
glyphs.push({
|
||||||
|
range: new monaco.Range(e.line, e.column, e.line, endColumn),
|
||||||
|
options: {
|
||||||
|
glyphMarginClassName: 'error-glyph-margin',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.#errorGlyphs.set(this._codeEditor.deltaDecorations(this.#errorGlyphs(), glyphs));
|
||||||
|
(window as any).monaco.editor.setModelMarkers(model, model.id, markers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _closeProblemsView() {
|
||||||
|
this._codeEditor.trigger(null, 'closeMarkersNavigation', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _removeErrorMarkers() {
|
||||||
|
const model = this._codeEditor?.getModel();
|
||||||
|
if (!model) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(window as any).monaco.editor.setModelMarkers(model, model.id, []);
|
||||||
|
this.#errorGlyphs.set(this._codeEditor.deltaDecorations(this.#errorGlyphs(), []) || []);
|
||||||
|
this._closeProblemsView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _initialize() {
|
||||||
|
this._loadingService.start();
|
||||||
|
await firstValueFrom(this._componentRulesService.download(this.#dossierTemplateId)).then(
|
||||||
|
rules => {
|
||||||
|
this.currentLines = this.initialLines = rules.rules.split('\n');
|
||||||
|
this.revert();
|
||||||
|
},
|
||||||
|
() => this._loadingService.stop(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -51,7 +51,7 @@ ngx-monaco-editor {
|
|||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
/* TODO: Update this to --iqser-error when added */
|
/* TODO: Update this to --iqser-error when added */
|
||||||
color: var(--iqser-red-1);
|
color: #dd4d50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.face-up {
|
.face-up {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, signal, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, ElementRef, OnInit, signal, ViewChild } from '@angular/core';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
@ -25,7 +25,6 @@ interface SyntaxError {
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
||||||
readonly numberOfErrors = signal<number>(0);
|
|
||||||
readonly iconButtonTypes = IconButtonTypes;
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
readonly editorOptions: IStandaloneEditorConstructionOptions = {
|
readonly editorOptions: IStandaloneEditorConstructionOptions = {
|
||||||
theme: 'vs',
|
theme: 'vs',
|
||||||
@ -41,7 +40,8 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
|||||||
private _fileInput: ElementRef;
|
private _fileInput: ElementRef;
|
||||||
private _codeEditor: ICodeEditor;
|
private _codeEditor: ICodeEditor;
|
||||||
private _decorations: string[] = [];
|
private _decorations: string[] = [];
|
||||||
private _errorGlyphs: string[] = [];
|
readonly #errorGlyphs = signal<string[]>([]);
|
||||||
|
readonly numberOfErrors = computed(() => this.#errorGlyphs().length);
|
||||||
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -69,6 +69,7 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
|||||||
set codeEditorText($event: any) {
|
set codeEditorText($event: any) {
|
||||||
this.currentLines = $event.split('\n');
|
this.currentLines = $event.split('\n');
|
||||||
this.codeEditorTextChanged();
|
this.codeEditorTextChanged();
|
||||||
|
this._closeProblemsView();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@ -87,17 +88,16 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
|||||||
@Debounce()
|
@Debounce()
|
||||||
codeEditorTextChanged() {
|
codeEditorTextChanged() {
|
||||||
const newDecorations = this.currentLines.filter(entry => this._isNew(entry)).map(entry => this._makeDecorationFor(entry));
|
const newDecorations = this.currentLines.filter(entry => this._isNew(entry)).map(entry => this._makeDecorationFor(entry));
|
||||||
|
|
||||||
this._decorations = this._codeEditor.deltaDecorations(this._decorations, newDecorations);
|
this._decorations = this._codeEditor.deltaDecorations(this._decorations, newDecorations);
|
||||||
}
|
}
|
||||||
|
|
||||||
goToErrors() {
|
goToErrors() {
|
||||||
this._codeEditor.trigger('keyboard', 'editor.action.marker.next', null);
|
this._codeEditor.trigger(null, 'editor.action.marker.next', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(): Promise<void> {
|
async save(): Promise<void> {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
this.numberOfErrors.set(0);
|
this._removeErrorMarkers();
|
||||||
await firstValueFrom(
|
await firstValueFrom(
|
||||||
this._rulesService.uploadRules({
|
this._rulesService.uploadRules({
|
||||||
rules: this._codeEditor.getModel().getValue(),
|
rules: this._codeEditor.getModel().getValue(),
|
||||||
@ -106,7 +106,6 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
|||||||
).then(
|
).then(
|
||||||
async () => {
|
async () => {
|
||||||
await this._initialize();
|
await this._initialize();
|
||||||
this._removeErrorMarkers();
|
|
||||||
this._toaster.success(_('rules-screen.success.generic'));
|
this._toaster.success(_('rules-screen.success.generic'));
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
@ -186,19 +185,22 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.numberOfErrors.set(markers.length);
|
this.#errorGlyphs.set(this._codeEditor.deltaDecorations(this.#errorGlyphs(), glyphs));
|
||||||
this._errorGlyphs = this._codeEditor.deltaDecorations(this._errorGlyphs, glyphs);
|
|
||||||
(window as any).monaco.editor.setModelMarkers(model, model.id, markers);
|
(window as any).monaco.editor.setModelMarkers(model, model.id, markers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _closeProblemsView() {
|
||||||
|
this._codeEditor.trigger(null, 'closeMarkersNavigation', null);
|
||||||
|
}
|
||||||
|
|
||||||
private _removeErrorMarkers() {
|
private _removeErrorMarkers() {
|
||||||
const model = this._codeEditor?.getModel();
|
const model = this._codeEditor?.getModel();
|
||||||
if (!model) {
|
if (!model) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(window as any).monaco.editor.setModelMarkers(model, model.id, []);
|
(window as any).monaco.editor.setModelMarkers(model, model.id, []);
|
||||||
this._errorGlyphs = this._codeEditor?.deltaDecorations(this._errorGlyphs, []) || [];
|
this.#errorGlyphs.set(this._codeEditor.deltaDecorations(this.#errorGlyphs(), []) || []);
|
||||||
this.numberOfErrors.set(0);
|
this._closeProblemsView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _initialize() {
|
private async _initialize() {
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { GenericService } from '@iqser/common-ui';
|
||||||
|
import { IComponentRules } from '@red/domain';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ComponentRulesService extends GenericService<IComponentRules> {
|
||||||
|
protected readonly _defaultModelPath = 'rules';
|
||||||
|
|
||||||
|
download(dossierTemplateId: string) {
|
||||||
|
return this._getOne([dossierTemplateId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadRules(body: IComponentRules) {
|
||||||
|
return this._post<unknown>(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -33,10 +33,9 @@ export class AdminSideNavComponent implements OnInit {
|
|||||||
readonly translations = adminSideNavTranslations;
|
readonly translations = adminSideNavTranslations;
|
||||||
readonly currentUser = getCurrentUser<User>();
|
readonly currentUser = getCurrentUser<User>();
|
||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
|
prefix: string;
|
||||||
readonly isDocumine = this.#config.IS_DOCUMINE;
|
readonly isDocumine = this.#config.IS_DOCUMINE;
|
||||||
readonly canAccessRulesInDocumine = this.isDocumine && !this.#config.RULE_EDITOR_DEV_ONLY;
|
readonly canAccessRulesInDocumine = this.isDocumine && !this.#config.RULE_EDITOR_DEV_ONLY;
|
||||||
prefix: string;
|
|
||||||
|
|
||||||
readonly items: { readonly [key in AdminSideNavType]: NavItem[] } = {
|
readonly items: { readonly [key in AdminSideNavType]: NavItem[] } = {
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
@ -100,6 +99,14 @@ export class AdminSideNavComponent implements OnInit {
|
|||||||
label: _('admin-side-nav.rule-editor'),
|
label: _('admin-side-nav.rule-editor'),
|
||||||
show: (this.isIqserDevMode || this.canAccessRulesInDocumine) && this._permissionsService.has(Roles.rules.read),
|
show: (this.isIqserDevMode || this.canAccessRulesInDocumine) && this._permissionsService.has(Roles.rules.read),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
screen: 'component-rules',
|
||||||
|
label: _('admin-side-nav.component-rule-editor'),
|
||||||
|
show:
|
||||||
|
this.isDocumine &&
|
||||||
|
(this.isIqserDevMode || this.canAccessRulesInDocumine) &&
|
||||||
|
this._permissionsService.has(Roles.rules.read),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
screen: 'default-colors',
|
screen: 'default-colors',
|
||||||
label: _('admin-side-nav.default-colors'),
|
label: _('admin-side-nav.default-colors'),
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"ADMIN_CONTACT_URL": null,
|
"ADMIN_CONTACT_URL": null,
|
||||||
"API_URL": "https://dan.iqser.cloud",
|
"API_URL": "https://dan.iqser.cloud",
|
||||||
"APP_NAME": "RedactManager",
|
"APP_NAME": "RedactManager",
|
||||||
"IS_DOCUMINE": false,
|
"IS_DOCUMINE": true,
|
||||||
"RULE_EDITOR_DEV_ONLY": false,
|
"RULE_EDITOR_DEV_ONLY": false,
|
||||||
"AUTO_READ_TIME": 3,
|
"AUTO_READ_TIME": 3,
|
||||||
"BACKEND_APP_VERSION": "4.4.40",
|
"BACKEND_APP_VERSION": "4.4.40",
|
||||||
@ -18,8 +18,8 @@
|
|||||||
"SELECTION_MODE": "structural",
|
"SELECTION_MODE": "structural",
|
||||||
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
||||||
"ANNOTATIONS_THRESHOLD": 1000,
|
"ANNOTATIONS_THRESHOLD": 1000,
|
||||||
"THEME": "redact",
|
"THEME": "scm",
|
||||||
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/redact/",
|
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/scm/",
|
||||||
"AVAILABLE_NOTIFICATIONS_DAYS": 30,
|
"AVAILABLE_NOTIFICATIONS_DAYS": 30,
|
||||||
"AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60,
|
"AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60,
|
||||||
"NOTIFICATIONS_THRESHOLD": 1000,
|
"NOTIFICATIONS_THRESHOLD": 1000,
|
||||||
|
|||||||
@ -234,6 +234,7 @@
|
|||||||
},
|
},
|
||||||
"admin-side-nav": {
|
"admin-side-nav": {
|
||||||
"audit": "",
|
"audit": "",
|
||||||
|
"component-rule-editor": "",
|
||||||
"configurations": "",
|
"configurations": "",
|
||||||
"default-colors": "",
|
"default-colors": "",
|
||||||
"dictionary": "",
|
"dictionary": "",
|
||||||
@ -557,6 +558,19 @@
|
|||||||
"title": "Aktion bestätigen"
|
"title": "Aktion bestätigen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"component-rules-screen": {
|
||||||
|
"error": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"errors-found": "",
|
||||||
|
"revert-changes": "",
|
||||||
|
"save-changes": "",
|
||||||
|
"success": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"title": "",
|
||||||
|
"warning-text": ""
|
||||||
|
},
|
||||||
"configurations": "Einstellungen",
|
"configurations": "Einstellungen",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
|
|||||||
@ -234,6 +234,7 @@
|
|||||||
},
|
},
|
||||||
"admin-side-nav": {
|
"admin-side-nav": {
|
||||||
"audit": "Audit",
|
"audit": "Audit",
|
||||||
|
"component-rule-editor": "",
|
||||||
"configurations": "Configurations",
|
"configurations": "Configurations",
|
||||||
"default-colors": "Default Colors",
|
"default-colors": "Default Colors",
|
||||||
"dictionary": "Dictionary",
|
"dictionary": "Dictionary",
|
||||||
@ -557,6 +558,19 @@
|
|||||||
"title": "Confirm Action"
|
"title": "Confirm Action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"component-rules-screen": {
|
||||||
|
"error": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"errors-found": "",
|
||||||
|
"revert-changes": "",
|
||||||
|
"save-changes": "",
|
||||||
|
"success": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"title": "",
|
||||||
|
"warning-text": ""
|
||||||
|
},
|
||||||
"configurations": "Configurations",
|
"configurations": "Configurations",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
"archive": "Archive Dossier",
|
"archive": "Archive Dossier",
|
||||||
|
|||||||
@ -234,6 +234,7 @@
|
|||||||
},
|
},
|
||||||
"admin-side-nav": {
|
"admin-side-nav": {
|
||||||
"audit": "",
|
"audit": "",
|
||||||
|
"component-rule-editor": "",
|
||||||
"configurations": "",
|
"configurations": "",
|
||||||
"default-colors": "",
|
"default-colors": "",
|
||||||
"dictionary": "",
|
"dictionary": "",
|
||||||
@ -557,6 +558,19 @@
|
|||||||
"title": "Aktion bestätigen"
|
"title": "Aktion bestätigen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"component-rules-screen": {
|
||||||
|
"error": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"errors-found": "",
|
||||||
|
"revert-changes": "",
|
||||||
|
"save-changes": "",
|
||||||
|
"success": {
|
||||||
|
"generic": ""
|
||||||
|
},
|
||||||
|
"title": "",
|
||||||
|
"warning-text": ""
|
||||||
|
},
|
||||||
"configurations": "Einstellungen",
|
"configurations": "Einstellungen",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
"archive": "",
|
"archive": "",
|
||||||
|
|||||||
@ -234,6 +234,7 @@
|
|||||||
},
|
},
|
||||||
"admin-side-nav": {
|
"admin-side-nav": {
|
||||||
"audit": "Audit",
|
"audit": "Audit",
|
||||||
|
"component-rule-editor": "Component Rule Editor",
|
||||||
"configurations": "Configurations",
|
"configurations": "Configurations",
|
||||||
"default-colors": "Default Colors",
|
"default-colors": "Default Colors",
|
||||||
"dictionary": "Dictionary",
|
"dictionary": "Dictionary",
|
||||||
@ -557,6 +558,19 @@
|
|||||||
"title": "Confirm Action"
|
"title": "Confirm Action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"component-rules-screen": {
|
||||||
|
"error": {
|
||||||
|
"generic": "Something went wrong... Component rules update failed!"
|
||||||
|
},
|
||||||
|
"errors-found": "{errors, plural, one{An error} other{{errors} errors}} found in rules",
|
||||||
|
"revert-changes": "Revert",
|
||||||
|
"save-changes": "Save Changes",
|
||||||
|
"success": {
|
||||||
|
"generic": "Component rules updated!"
|
||||||
|
},
|
||||||
|
"title": "Component Rule Editor",
|
||||||
|
"warning-text": "Warning: experimental feature!"
|
||||||
|
},
|
||||||
"configurations": "Configurations",
|
"configurations": "Configurations",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
"archive": "Archive Dossier",
|
"archive": "Archive Dossier",
|
||||||
@ -2213,7 +2227,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"generic": "Something went wrong... Rules update failed!"
|
"generic": "Something went wrong... Rules update failed!"
|
||||||
},
|
},
|
||||||
"errors-found": "",
|
"errors-found": "{errors, plural, one{An error} other{{errors} errors}} found in rules",
|
||||||
"revert-changes": "Revert",
|
"revert-changes": "Revert",
|
||||||
"save-changes": "Save Changes",
|
"save-changes": "Save Changes",
|
||||||
"success": {
|
"success": {
|
||||||
|
|||||||
13
libs/red-domain/src/lib/shared/component-rules.ts
Normal file
13
libs/red-domain/src/lib/shared/component-rules.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Object containing a string of Drools rules.
|
||||||
|
*/
|
||||||
|
export interface IComponentRules {
|
||||||
|
/**
|
||||||
|
* The DossierTemplate Id for these rules
|
||||||
|
*/
|
||||||
|
dossierTemplateId?: string;
|
||||||
|
/**
|
||||||
|
* The actual string of rules.
|
||||||
|
*/
|
||||||
|
rules?: string;
|
||||||
|
}
|
||||||
@ -11,3 +11,4 @@ export * from './admin-side-nav-types';
|
|||||||
export * from './charts';
|
export * from './charts';
|
||||||
export * from './app-config';
|
export * from './app-config';
|
||||||
export * from './system-preferences';
|
export * from './system-preferences';
|
||||||
|
export * from './component-rules';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user