diff --git a/angular.json b/angular.json
index 0ac3d1def..fb22eefd4 100644
--- a/angular.json
+++ b/angular.json
@@ -48,20 +48,10 @@
"input": "apps/red-ui/src/assets/",
"output": "/assets/"
},
- {
- "glob": "**/*",
- "input": "node_modules/ace-builds/src-min/",
- "output": "/assets/ace-builds"
- },
"apps/red-ui/src/manifest.webmanifest"
],
"styles": ["apps/red-ui/src/styles.scss"],
- "scripts": [
- "node_modules/@pdftron/webviewer/webviewer.min.js",
- "node_modules/ace-builds/src-min/ace.js",
- "node_modules/ace-builds/src-min/mode-java.js",
- "node_modules/ace-builds/src-min/theme-eclipse.js"
- ],
+ "scripts": ["node_modules/@pdftron/webviewer/webviewer.min.js"],
"vendorChunk": true,
"extractLicenses": false,
"buildOptimizer": false,
diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts
index aa408141d..1ca904ec7 100644
--- a/apps/red-ui/src/app/app.module.ts
+++ b/apps/red-ui/src/app/app.module.ts
@@ -29,8 +29,6 @@ import { PlatformLocation } from '@angular/common';
import { BASE_HREF } from './tokens';
import { MONACO_PATH, MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
-// declare let ace;
-
export function httpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
}
@@ -112,14 +110,8 @@ const components = [
bootstrap: [AppComponent]
})
export class AppModule {
- constructor(
- // @Inject(BASE_HREF) private readonly _baseHref: string,
- private readonly _router: Router,
- private readonly _route: ActivatedRoute
- ) {
+ constructor(private readonly _router: Router, private readonly _route: ActivatedRoute) {
this._configureKeyCloakRouteHandling();
-
- // ace.config.set('basePath', _baseHref + '/assets/ace-builds/');
}
private _configureKeyCloakRouteHandling() {
diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts
index a4e541468..42e561b77 100644
--- a/apps/red-ui/src/app/modules/admin/admin.module.ts
+++ b/apps/red-ui/src/app/modules/admin/admin.module.ts
@@ -15,7 +15,6 @@ import { UserListingScreenComponent } from './screens/user-listing/user-listing-
import { WatermarkScreenComponent } from './screens/watermark/watermark-screen.component';
import { AdminBreadcrumbsComponent } from './components/breadcrumbs/admin-breadcrumbs.component';
import { RuleSetActionsComponent } from './components/rule-set-actions/rule-set-actions.component';
-import { AceEditorModule } from 'ng2-ace-editor';
import { ColorPickerModule } from 'ngx-color-picker';
import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
import { AddEditRuleSetDialogComponent } from './dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component';
@@ -33,6 +32,7 @@ import { ConfirmDeleteUsersDialogComponent } from './dialogs/confirm-delete-user
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component';
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
+import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
const dialogs = [
AddEditRuleSetDialogComponent,
@@ -81,9 +81,9 @@ const components = [
CommonModule,
SharedModule,
AdminRoutingModule,
- AceEditorModule,
NgxChartsModule,
- ColorPickerModule
+ ColorPickerModule,
+ MonacoEditorModule
]
})
export class AdminModule {}
diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html
index dcac0f4c7..c04706a24 100644
--- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html
+++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html
@@ -20,18 +20,11 @@
0;
+ onCodeEditorInit(editor: ICodeEditor) {
+ this._codeEditor = editor;
+ (window as any).monaco.editor.defineTheme('redaction', {
+ base: 'vs',
+ inherit: true,
+ rules: [],
+ colors: {
+ 'editor.lineHighlightBackground': '#f4f5f7'
+ }
+ });
+ (window as any).monaco.editor.setTheme('redaction');
}
- textChanged($event: any) {
+ get hasChanges(): boolean {
+ return this._decorations.length > 0;
+ }
+
+ get codeEditorText() {
+ return this.currentLines.join('\n');
+ }
+
+ set codeEditorText($event: any) {
this.currentLines = $event.split('\n');
- this.changedLines = [];
- this.activeEditMarkers.forEach((am) => {
- this.editorComponent.getEditor().getSession().removeMarker(am);
- });
- this.activeEditMarkers = [];
+ this.codeEditorTextChanged();
+ }
- for (let i = 0; i < this.currentLines.length; i++) {
- const currentEntry = this.currentLines[i];
- if (this.initialLines.indexOf(currentEntry) < 0) {
- this.changedLines.push(i);
- }
- }
+ @debounce()
+ codeEditorTextChanged() {
+ const newDecorations = this.currentLines
+ .filter((entry) => this._isNew(entry))
+ .map((entry) => this._makeDecorationFor(entry));
- const range = ace.require('ace/range').Range;
- for (const i of this.changedLines) {
- const entry = this.currentLines[i];
- if (entry?.trim().length > 0) {
- // only mark non-empty lines
- this.activeEditMarkers.push(
- this.editorComponent
- .getEditor()
- .getSession()
- .addMarker(new range(i, 0, i, 1), 'changed-row-marker', 'fullLine')
- );
- }
- }
+ this._decorations = this._codeEditor.deltaDecorations(this._decorations, newDecorations);
+ }
+
+ 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;
}
async save(): Promise {
this.processing = true;
this._rulesControllerService
.uploadRules({
- rules: this.editorComponent.getEditor().getValue(),
+ rules: this._codeEditor.getModel().getValue(),
ruleSetId: this._appStateService.activeRuleSetId
})
.subscribe(
@@ -107,14 +124,13 @@ export class RulesScreenComponent extends ComponentHasChanges {
}
revert(): void {
- this.initialLines = this.rules.split('\n');
- this.editorComponent.getEditor().setValue(this.rules);
- this.editorComponent.getEditor().clearSelection();
+ this.currentLines = this.initialLines;
+ this._decorations = this._codeEditor?.deltaDecorations(this._decorations, []) || [];
this.processing = false;
}
download(): void {
- const content = this.editorComponent.getEditor().getValue();
+ const content = this._codeEditor.getModel().getValue();
const blob = new Blob([content], {
type: 'text/plain;charset=utf-8'
});
@@ -127,7 +143,7 @@ export class RulesScreenComponent extends ComponentHasChanges {
if (file) {
fileReader.onload = () => {
- this.editorComponent.getEditor().setValue(fileReader.result);
+ this._codeEditor.getModel().setValue(fileReader.result as string);
this._fileInput.nativeElement.value = null;
};
fileReader.readAsText(file);
@@ -137,12 +153,10 @@ export class RulesScreenComponent extends ComponentHasChanges {
private _initialize() {
this._rulesControllerService.downloadRules(this._appStateService.activeRuleSetId).subscribe(
(rules) => {
- this.rules = rules.rules;
+ this.currentLines = this.initialLines = rules.rules.split('\n');
this.revert();
},
- () => {
- this.processing = false;
- }
+ () => (this.processing = false)
);
}
}
diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts
index 1f65abcba..7c7cb1e1c 100644
--- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts
+++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts
@@ -153,7 +153,7 @@ export class DictionaryManagerComponent implements OnChanges {
private _getMatches(text: string): FindMatch[] {
const model = this._codeEditor?.getModel();
- return model.findMatches(text, false, false, false, null, false) || [];
+ return model?.findMatches(text, false, false, false, null, false) || [];
}
get codeEditorText(): string {
diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts
index 36380dcea..c70bd00e7 100644
--- a/apps/red-ui/src/app/modules/shared/shared.module.ts
+++ b/apps/red-ui/src/app/modules/shared/shared.module.ts
@@ -33,7 +33,6 @@ import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { SelectComponent } from './components/select/select.component';
import { NavigateLastProjectsScreenDirective } from './directives/navigate-last-projects-screen.directive';
import { DictionaryManagerComponent } from './components/dictionary-manager/dictionary-manager.component';
-import { AceEditorModule } from 'ng2-ace-editor';
import { SideNavComponent } from '@shared/components/side-nav/side-nav.component';
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
@@ -63,6 +62,7 @@ const components = [
RoundCheckboxComponent,
SelectComponent,
SideNavComponent,
+ DictionaryManagerComponent,
...buttons
];
@@ -84,9 +84,9 @@ const modules = [
];
@NgModule({
- declarations: [...components, ...utils, DictionaryManagerComponent],
- imports: [CommonModule, ...modules, AceEditorModule, MonacoEditorModule],
- exports: [...modules, ...components, ...utils, DictionaryManagerComponent],
+ declarations: [...components, ...utils],
+ imports: [CommonModule, ...modules, MonacoEditorModule],
+ exports: [...modules, ...components, ...utils],
providers: [
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{
diff --git a/apps/red-ui/src/assets/ace-editor/theme-redaction.js b/apps/red-ui/src/assets/ace-editor/theme-redaction.js
deleted file mode 100644
index 38fb52867..000000000
--- a/apps/red-ui/src/assets/ace-editor/theme-redaction.js
+++ /dev/null
@@ -1,3 +0,0 @@
-ace.define('ace/theme/redaction', [], function (exports, object) {
- object.cssClass = 'ace-redaction';
-});
diff --git a/apps/red-ui/src/assets/styles/red-editor.scss b/apps/red-ui/src/assets/styles/red-editor.scss
index 920726438..acd3cf62a 100644
--- a/apps/red-ui/src/assets/styles/red-editor.scss
+++ b/apps/red-ui/src/assets/styles/red-editor.scss
@@ -16,72 +16,8 @@
z-index: 40;
}
-.ace-redaction {
- color: $accent;
-
- .ace_gutter {
- background: $grey-2;
- color: $grey-7;
- border-right: none;
- }
-
- .ace_gutter-cell:after {
- content: '.';
- }
-
- .ace_active-line {
- background: $grey-6;
- }
-
- .ace_print-margin {
- width: 0;
- background: $white;
- }
-
- .ace_cursor {
- color: $grey-5;
- }
-
- .ace_marker-layer .ace_selection {
- background: $grey-4;
- }
-
- .ace_multiselect .ace_selection.ace_start {
- box-shadow: 0 0 3px 0 $white;
- }
-
- .ace_gutter-active-line {
- background-color: $grey-6;
- }
-
- .ace_marker-layer .ace_selected-word {
- border: 1px solid $grey-4;
- }
-
- .ace_invisible {
- color: $grey-4;
- }
-
- &[ng-reflect-read-only='true'] {
- background-color: $grey-2;
-
- *:not(.ace_scrollbar) {
- pointer-events: none;
- }
- }
-}
-
.editor-container {
width: 100%;
-
- ace-editor {
- width: 100%;
- height: 100%;
- box-sizing: border-box;
- border: 1px solid $grey-5;
- border-radius: 8px;
- background-color: $white;
- }
}
.changes-box {
diff --git a/package.json b/package.json
index b5ab2a7b5..4b40789e7 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,6 @@
"keycloak-js": "13.0.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
- "ng2-ace-editor": "^0.3.9",
"ngx-color-picker": "^11.0.0",
"ngx-toastr": "^13.2.1",
"papaparse": "^5.3.0",
diff --git a/yarn.lock b/yarn.lock
index fe9e2baf1..43d2d1cb4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3354,11 +3354,6 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
mime-types "~2.1.24"
negotiator "0.6.2"
-ace-builds@^1.4.2:
- version "1.4.12"
- resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.12.tgz#888efa386e36f4345f40b5233fcc4fe4c588fae7"
- integrity sha512-G+chJctFPiiLGvs3+/Mly3apXTcfgE45dT5yp12BcWZ1kUs+gm0qd3/fv4gsz6fVag4mM0moHVpjHDIgph6Psg==
-
acorn-globals@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
@@ -4078,11 +4073,6 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
-brace@^0.11.1:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58"
- integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg=
-
braces@^2.3.1, braces@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -9563,14 +9553,6 @@ ng-packagr@12.0.0:
sass "^1.32.8"
stylus "^0.54.8"
-ng2-ace-editor@^0.3.9:
- version "0.3.9"
- resolved "https://registry.yarnpkg.com/ng2-ace-editor/-/ng2-ace-editor-0.3.9.tgz#5ae68712e9ca49591eda31df8fe02eca1c3634e1"
- integrity sha512-e8Q4YCirlL/OEiekewmzupG+zV3prYsiYmQnRzQzd0wNgsPjOLOdb0it7cCbzFfIXKGyIIHKTW5584WxPr2LnQ==
- dependencies:
- ace-builds "^1.4.2"
- brace "^0.11.1"
-
ngx-color-picker@^11.0.0:
version "11.0.0"
resolved "https://registry.yarnpkg.com/ngx-color-picker/-/ngx-color-picker-11.0.0.tgz#c1e5468505953bc579bf21014a135808820ea753"