rule-node-config.advanced-settings
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss
new file mode 100644
index 0000000000..033e82b0b1
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.scss
@@ -0,0 +1,9 @@
+:host ::ng-deep {
+ tb-markdown-editor {
+ .markdown-content.tb-edit-mode {
+ &:not(.tb-fullscreen) {
+ padding-bottom: 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.ts
index c0b94fd8d7..284d44f9dc 100644
--- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.ts
+++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-note-editor.component.ts
@@ -14,44 +14,92 @@
/// limitations under the License.
///
-import { Component, inject, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Component, DestroyRef, inject, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { MatExpansionPanel } from '@angular/material/expansion';
import { FormBuilder, Validators } from '@angular/forms';
-import { FcRuleNote } from '@shared/models/rule-node.models';
+import {
+ FC_RULE_NOTE_DEFAULT_APPLY_MARKDOWN_STYLE as DEFAULT_APPLY_MARKDOWN_STYLE,
+ FC_RULE_NOTE_DEFAULT_BACKGROUND_COLOR as DEFAULT_BACKGROUND_COLOR,
+ FC_RULE_NOTE_DEFAULT_BORDER_WIDTH as DEFAULT_BORDER_WIDTH,
+ FcRuleNote
+} from '@shared/models/rule-node.models';
+import { isNotEmptyStr } from '@core/utils';
+import tinycolor from 'tinycolor2';
@Component({
- selector: 'tb-rule-note-editor',
- templateUrl: './rule-note-editor.component.html',
- standalone: false
+ selector: 'tb-rule-note-editor',
+ templateUrl: './rule-note-editor.component.html',
+ styleUrls: ['./rule-note-editor.component.scss'],
+ standalone: false
})
-export class RuleNoteEditorComponent implements OnChanges {
+export class RuleNoteEditorComponent implements OnChanges, OnInit {
@Input()
note: FcRuleNote;
- private fb = inject(FormBuilder)
+ @ViewChild('advancedPanel') advancedPanel: MatExpansionPanel;
+
+ private fb = inject(FormBuilder);
+ private destroyRef = inject(DestroyRef);
noteForm = this.fb.group({
content: ['', Validators.maxLength(65536)],
- backgroundColor: ['#FFF9C4'],
- applyDefaultMarkdownStyle: [true],
+ backgroundColor: [DEFAULT_BACKGROUND_COLOR],
+ borderColor: [tinycolor(DEFAULT_BACKGROUND_COLOR).darken(20).toString()],
+ borderWidth: [DEFAULT_BORDER_WIDTH, [Validators.min(0)]],
+ applyDefaultMarkdownStyle: [DEFAULT_APPLY_MARKDOWN_STYLE],
markdownCss: ['', Validators.maxLength(65536)]
});
+ ngOnInit(): void {
+ this.noteForm.get('backgroundColor').valueChanges
+ .pipe(takeUntilDestroyed(this.destroyRef))
+ .subscribe(color => {
+ const borderControl = this.noteForm.get('borderColor');
+ if (borderControl.pristine) {
+ borderControl.setValue(this.borderColorFrom(color), { emitEvent: false });
+ }
+ });
+ }
+
ngOnChanges(changes: SimpleChanges): void {
if (changes.note) {
this.updatedForm();
}
}
+ private borderColorFrom(bg: string): string {
+ return tinycolor(bg || DEFAULT_BACKGROUND_COLOR).darken(20).toString();
+ }
+
private updatedForm(): void {
+ const bg = this.note?.backgroundColor || DEFAULT_BACKGROUND_COLOR;
this.noteForm.setValue({
content: this.note?.content || '',
- backgroundColor: this.note?.backgroundColor || '#FFF9C4',
- applyDefaultMarkdownStyle: this.note?.applyDefaultMarkdownStyle ?? true,
+ backgroundColor: bg,
+ borderColor: this.note?.borderColor || this.borderColorFrom(bg),
+ borderWidth: this.note?.borderWidth ?? DEFAULT_BORDER_WIDTH,
+ applyDefaultMarkdownStyle: this.note?.applyDefaultMarkdownStyle ?? DEFAULT_APPLY_MARKDOWN_STYLE,
markdownCss: this.note?.markdownCss || ''
- })
+ });
+ const shouldExpand = this.hasNonDefaultAdvancedSettings(bg);
setTimeout(() => {
+ if (shouldExpand) {
+ this.advancedPanel?.open();
+ } else {
+ this.advancedPanel?.close();
+ }
this.noteForm.markAsPristine();
}, 0);
}
+
+ private hasNonDefaultAdvancedSettings(bg: string): boolean {
+ const note = this.note;
+ if (!note) return false;
+ return (note.borderColor != null && note.borderColor !== this.borderColorFrom(bg))
+ || (note.borderWidth != null && note.borderWidth !== DEFAULT_BORDER_WIDTH)
+ || note.applyDefaultMarkdownStyle === false
+ || isNotEmptyStr(note.markdownCss);
+ }
}
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss
index 1bdbae1280..0236e2f85d 100644
--- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss
+++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss
@@ -193,14 +193,15 @@
border: solid 2px rgba(0, 0, 0, 0.35);
}
}
+ }
- fc-note {
- &.fc-selected:not(.fc-edit) {
- box-shadow: 0 0 0 3px #f00;
- }
- &.fc-selected.fc-edit {
- box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.35);
- }
+ .fc-note {
+ border-radius: 8px;
+ &.fc-selected:not(.fc-edit) {
+ box-shadow: 0 0 0 3px #f00;
+ }
+ &.fc-selected.fc-edit {
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.35);
}
}
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts
index ee0f1fd72f..60217a04d9 100644
--- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts
+++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts
@@ -170,7 +170,7 @@ export class RuleChainPageComponent extends PageComponent
editingNote: FcRuleNote = null;
isEditingNote = false;
- editingNoteId: string = null;
+ editingNoteIndex = -1;
hotKeys: Hotkey[] = [];
@@ -682,7 +682,7 @@ export class RuleChainPageComponent extends PageComponent
}
});
}
- this.ruleChainModel.notes = this.ruleChainMetaData.notes || [];
+ this.ruleChainModel.notes = deepClone(this.ruleChainMetaData.notes) || [];
if (this.ruleChainCanvas) {
this.ruleChainCanvas.adjustCanvasSize(true);
}
@@ -1365,7 +1365,7 @@ export class RuleChainPageComponent extends PageComponent
icon: 'sticky_note_2',
title: this.translate.instant('rulechain.note'),
subtitle: (() => {
- const plain = (note.content || '').replace(/[#*_`>\[\]!\\~]/g, '').trim();
+ const plain = (note.content || '').replace(/[#*_`>[\]!\\~]/g, '').trim();
return plain.length > 24 ? plain.substring(0, 24) + '…' : plain;
})(),
menuItems: []
@@ -1414,30 +1414,27 @@ export class RuleChainPageComponent extends PageComponent
this.isEditingRuleNodeLink = false;
this.editingRuleNodeLink = null;
this.isEditingNote = true;
- this.editingNoteId = note.id;
+ this.editingNoteIndex = this.ruleChainModel.notes.indexOf(note);
this.editingNote = deepClone(note);
}
saveNote(): void {
this.ruleNoteComponent.noteForm.markAsPristine();
Object.assign(this.editingNote, this.ruleNoteComponent.noteForm.value);
- const idx = this.ruleChainModel.notes.findIndex(n => n.id === this.editingNoteId);
- this.ruleChainModel.notes[idx] = this.editingNote;
+ this.ruleChainModel.notes[this.editingNoteIndex] = this.editingNote;
this.editingNote = deepClone(this.editingNote);
- this.isDirty = true;
this.onModelChanged();
}
onRevertNoteEdit(): void {
this.ruleNoteComponent.noteForm.markAsPristine();
- const note = this.ruleChainModel.notes.find(n => n.id === this.editingNoteId);
+ const note = this.ruleChainModel.notes[this.editingNoteIndex];
this.editingNote = deepClone(note);
}
onEditNoteClosed(): void {
this.editingNote = null;
this.isEditingNote = false;
- this.editingNoteId = null;
}
onDetailsDrawerClosed() {
@@ -1721,7 +1718,7 @@ export class RuleChainPageComponent extends PageComponent
this.ruleChain.version = savedRuleChainMetaData.version;
this.ruleChainMetaData = savedRuleChainMetaData;
if (!this.ruleChainMetaData.notes) {
- this.ruleChainMetaData.notes = this.ruleChainModel.notes || [];
+ this.ruleChainMetaData.notes = deepClone(this.ruleChainModel.notes) || [];
}
if (this.isImport) {
this.isDirtyValue = false;
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulenote.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulenote.component.html
index f0db4f82d6..a14b30dcb0 100644
--- a/ui-ngx/src/app/modules/home/pages/rulechain/rulenote.component.html
+++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulenote.component.html
@@ -28,12 +28,13 @@
}
@if (note?.content) {