From 00dd7963c99f104d4ccad37f471277472148f569 Mon Sep 17 00:00:00 2001 From: George Date: Tue, 5 Sep 2023 19:43:20 +0300 Subject: [PATCH 1/3] DM-408, add error highlighting for rule edits --- .../rules-screen/rules-screen.component.ts | 63 +++++++++++++++++-- apps/red-ui/src/styles.scss | 5 ++ 2 files changed, 62 insertions(+), 6 deletions(-) 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 ef81e18c5..a3020e91b 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 @@ -13,27 +13,35 @@ 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: './rules-screen.component.html', styleUrls: ['./rules-screen.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { - @ViewChild('fileInput') - private _fileInput: ElementRef; - private _codeEditor: ICodeEditor; - private _decorations: string[] = []; - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); 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[] = []; + private _errorGlyphs: string[] = []; + readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); constructor( readonly permissionsService: PermissionsService, @@ -92,9 +100,12 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { ).then( async () => { await this._initialize(); + this._removeErrorMarkers(); this._toaster.success(_('rules-screen.success.generic')); }, - () => { + error => { + const errors = error.error as SyntaxError[] | undefined; + this._drawErrorMarkers(errors); this._loadingService.stop(); this._toaster.error(_('rules-screen.error.generic')); }, @@ -104,6 +115,7 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { revert(): void { this.currentLines = this.initialLines; this._decorations = this._codeEditor?.deltaDecorations(this._decorations, []) || []; + this._removeErrorMarkers(); this._changeDetectorRef.detectChanges(); this._loadingService.stop(); } @@ -142,6 +154,45 @@ export class RulesScreenComponent implements OnInit, ComponentCanDeactivate { } 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 = this._codeEditor.deltaDecorations(this._errorGlyphs, glyphs); + (window as any).monaco.editor.setModelMarkers(model, model.id, markers); + } + + private _removeErrorMarkers() { + const model = this._codeEditor?.getModel(); + if (!model) { + return; + } + (window as any).monaco.editor.setModelMarkers(model, model.id, []); + this._errorGlyphs = this._codeEditor?.deltaDecorations(this._errorGlyphs, []) || []; + } + private async _initialize() { this._loadingService.start(); await firstValueFrom(this._rulesService.download(this.#dossierTemplateId)).then( diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss index d72aa65ab..43bd48938 100644 --- a/apps/red-ui/src/styles.scss +++ b/apps/red-ui/src/styles.scss @@ -39,6 +39,11 @@ src: url('./assets/styles/fonts/Inter-VariableFont.ttf') format('truetype'); } +.error-glyph-margin { + background: url('./assets/icons/general/alert-circle.svg') no-repeat center; + background-size: 80%; +} + @include common-variables.configureLight( $iqser-primary: vars.$primary, $iqser-primary-rgb: common-functions.hexToRgb(vars.$primary), From 841cf2e50c37571dff9acbdf2724ef7d27d132d1 Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Wed, 6 Sep 2023 17:29:11 +0300 Subject: [PATCH 2/3] DM-413: enabled bulk edit only for skipped and annotations. --- .../app/models/file/annotation.permissions.ts | 3 ++ .../edit-annotation-dialog.component.html | 33 +++++++++++++++---- .../edit-annotation-dialog.component.scss | 14 ++++++++ .../edit-annotation-dialog.component.ts | 14 +++++--- .../services/annotation-actions.service.ts | 6 ++-- .../pdf-annotation-actions.service.ts | 12 +++---- apps/red-ui/src/assets/i18n/scm/en.json | 5 +-- 7 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.scss diff --git a/apps/red-ui/src/app/models/file/annotation.permissions.ts b/apps/red-ui/src/app/models/file/annotation.permissions.ts index 16eef7da4..d88d42868 100644 --- a/apps/red-ui/src/app/models/file/annotation.permissions.ts +++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts @@ -29,6 +29,7 @@ export class AnnotationPermissions { canResizeAnnotation = true; canRecategorizeAnnotation = true; canForceHint = true; + canEditAnnotations = true; static forUser( isApprover: boolean, @@ -58,6 +59,7 @@ export class AnnotationPermissions { permissions.canChangeLegalBasis = canChangeLegalBasis(annotation, canAddRedaction); permissions.canRecategorizeAnnotation = canRecategorizeAnnotation(annotation, canAddRedaction); permissions.canResizeAnnotation = canResizeAnnotation(annotation, canAddRedaction); + permissions.canEditAnnotations = annotation.isSkipped || annotation.isRedacted; summedPermissions._merge(permissions); } @@ -77,6 +79,7 @@ export class AnnotationPermissions { result.canRemoveOnlyHere = permissions.reduce((acc, next) => acc && next.canRemoveOnlyHere, true); result.canRemoveRedaction = permissions.reduce((acc, next) => acc && next.canRemoveRedaction, true); result.canUndo = permissions.reduce((acc, next) => acc && next.canUndo, true); + result.canEditAnnotations = permissions.reduce((acc, next) => acc && next.canEditAnnotations, true); return result; } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html index 10baea1b0..f680ef1c2 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.html @@ -3,16 +3,26 @@
-
- - {{ redactedText }} +
+ + +
    +
  • {{ text }}
  • +
+
- - + {{ displayedDictionaryLabel }}