diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html index b278a9855..f35b02351 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html @@ -27,8 +27,8 @@ @@ -83,7 +83,6 @@ [diffEditorText]="diffEditorText" [initialEntries]="initialEntries" [showDiffEditor]="compare && showDiffEditor" - (enableSaveButton)="onEnableSaveButton($event)" >
@@ -97,7 +96,6 @@ (action)="saveDictionary.emit()" [label]="'dictionary-overview.save-changes' | translate" [type]="iconButtonTypes.primary" - [disabled]="!saveButtonEnabled()" icon="iqser:check" >
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 679c8aa95..7f97a508e 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 @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, signal, SimpleChanges, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core'; import { Debounce, IconButtonTypes, List, LoadingService } from '@iqser/common-ui'; import { firstValueFrom, Observable, of } from 'rxjs'; import { catchError, map, take, tap } from 'rxjs/operators'; @@ -26,9 +26,6 @@ const HELP_MODE_KEYS = { styleUrls: ['./dictionary-manager.component.scss'], }) export class DictionaryManagerComponent implements OnChanges { - readonly iconButtonTypes = IconButtonTypes; - readonly saveButtonEnabled = signal(true); - @Input() type: DictionaryType = 'dictionary'; @Input() entityType?: string; @Input() withFloatingActions = true; @@ -39,6 +36,9 @@ export class DictionaryManagerComponent implements OnChanges { @Input() isLeavingPage = false; @Output() readonly saveDictionary = new EventEmitter(); @ViewChild(EditorComponent) readonly editor: EditorComponent; + + readonly iconButtonTypes = IconButtonTypes; + currentMatch = 0; findMatches: FindMatch[] = []; diffEditorText = ''; @@ -212,10 +212,6 @@ export class DictionaryManagerComponent implements OnChanges { } } - onEnableSaveButton(value: boolean) { - this.saveButtonEnabled.set(value); - } - private _applySearchDecorations() { this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, []) || []; diff --git a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts index ad0c13928..b59f54434 100644 --- a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { Debounce, List, LoadingService, OnChange } from '@iqser/common-ui'; import { EditorThemeService } from '@services/editor-theme.service'; import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions; @@ -30,7 +30,6 @@ export class EditorComponent implements OnInit, OnChanges { @Input() diffEditorText: string; @Input() @OnChange('revert') initialEntries: List; @Input() canEdit = false; - @Output() enableSaveButton = new EventEmitter(); /** * Used as [modified] input on diff editor @@ -53,10 +52,18 @@ export class EditorComponent implements OnInit, OnChanges { return this.currentEntries.toString() !== this.initialEntries.toString(); } - private get _currentEntriesCount(): number { + get #currentEntriesCount(): number { return this.currentEntries.length; } + @Debounce() + codeEditorTextChanged() { + const newDecorations = this.#getDecorations(); + this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations); + this.diffValue = this.value; + this._loadingService.stop(); + } + ngOnChanges(changes: SimpleChanges) { if (changes.diffEditorText) { this._diffEditor?.getOriginalEditor().setValue(this.diffEditorText); @@ -79,26 +86,17 @@ export class EditorComponent implements OnInit, OnChanges { onDiffEditorInit(editor: IDiffEditor): void { this._diffEditor = editor; this.codeEditor = editor.getModifiedEditor(); - this._addMarginButtons(); - this._diffEditor.getOriginalEditor().onMouseDown(event => this._handleMarginButtonClick(event)); + this.#addMarginButtons(); + this._diffEditor.getOriginalEditor().onMouseDown(event => this.#handleMarginButtonClick(event)); this._diffEditor.getModifiedEditor().onDidChangeModelContent(() => { this.value = this._diffEditor.getModel().modified.getValue(); }); - this._setTheme(); + this.#setTheme(); } onCodeEditorInit(editor: ICodeEditor): void { this.codeEditor = editor; - this._setTheme(); - } - - @Debounce() - codeEditorTextChanged() { - const newDecorations = this.currentEntries.filter(entry => this._isNew(entry)).map(entry => this._getDecoration(entry)); - this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations); - this.diffValue = this.value; - this._loadingService.stop(); - this.enableSaveButton.emit(true); + this.#setTheme(); } revert() { @@ -109,28 +107,44 @@ export class EditorComponent implements OnInit, OnChanges { onPaste() { this._loadingService.start(); - this.enableSaveButton.emit(false); } - private _defineThemes(): void { + #getDecorations() { + const currentEntries = this.currentEntries; + const newDecorations: IModelDeltaDecoration[] = []; + + for (let index = 0; index < currentEntries.length; ++index) { + const entry = currentEntries.at(index); + if (!this.#isNew(entry)) { + continue; + } + + const line = index + 1; + newDecorations.push(this.#getDecoration(entry, line)); + } + + return newDecorations; + } + + #defineThemes(): void { for (const theme of this._editorThemeService.themes) { (window as any).monaco.editor.defineTheme(theme, this._editorThemeService.configurations[theme]); } } - private _setTheme(): void { - this._defineThemes(); + #setTheme(): void { + this.#defineThemes(); (window as any).monaco.editor.setTheme(this._editorThemeService.getTheme(this.canEdit)); } - private _handleMarginButtonClick(event: IEditorMouseEvent) { + #handleMarginButtonClick(event: IEditorMouseEvent) { const isMarginButtonClick = event.target.detail.glyphMarginWidth && event.target.detail.glyphMarginWidth !== 0; if (isMarginButtonClick) { - this._addContentFromOriginalAtLine(event.target.position.lineNumber); + this.#addContentFromOriginalAtLine(event.target.position.lineNumber); } } - private _addContentFromOriginalAtLine(lineNumber: number) { + #addContentFromOriginalAtLine(lineNumber: number) { const lineContent = this._diffEditor.getOriginalEditor().getModel().getLineContent(lineNumber) + '\n'; const lineChanges = this._diffEditor.getLineChanges(); let targetLineNumber = lineNumber; @@ -141,13 +155,13 @@ export class EditorComponent implements OnInit, OnChanges { break; } } - const prefix = - targetLineNumber > this._currentEntriesCount && this.currentEntries[this._currentEntriesCount - 1] !== '' ? '\n' : ''; + const currentEntriesCount = this.#currentEntriesCount; + const prefix = targetLineNumber > currentEntriesCount && this.currentEntries[currentEntriesCount - 1] !== '' ? '\n' : ''; const range = new monaco.Range(targetLineNumber, 1, targetLineNumber, 1); this._diffEditor.getModifiedEditor().executeEdits(null, [{ range, text: prefix + lineContent, forceMoveMarkers: true }]); } - private _addMarginButtons() { + #addMarginButtons() { let glyphDecorations = []; this._diffEditor.onDidUpdateDiff(() => { /** @@ -164,12 +178,11 @@ export class EditorComponent implements OnInit, OnChanges { }); } - private _isNew(entry: string): boolean { + #isNew(entry: string): boolean { return this.initialEntries.indexOf(entry) < 0 && entry?.trim().length > 0; } - private _getDecoration(entry: string): IModelDeltaDecoration { - const line = this.currentEntries.indexOf(entry) + 1; + #getDecoration(entry: string, line: number): IModelDeltaDecoration { const cssClass = entry.length < MIN_WORD_LENGTH ? 'too-short-marker' : 'changed-row-marker'; const range = new monaco.Range(line, 1, line, 1);