@masterteam/dashboard-builder 0.0.39 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -20217,6 +20217,8 @@ class FilterValueField {
|
|
|
20217
20217
|
placeholder = input('Enter value or select template...', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
20218
20218
|
/** Extra properties from chart config */
|
|
20219
20219
|
extraProperties = input([], ...(ngDevMode ? [{ debugName: "extraProperties" }] : /* istanbul ignore next */ []));
|
|
20220
|
+
/** Render the field as read-only (non-editable). */
|
|
20221
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
20220
20222
|
/** Internal state */
|
|
20221
20223
|
value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
20222
20224
|
disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
@@ -20473,13 +20475,13 @@ class FilterValueField {
|
|
|
20473
20475
|
this.disabled.set(isDisabled);
|
|
20474
20476
|
}
|
|
20475
20477
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FilterValueField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20476
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FilterValueField, isStandalone: true, selector: "mt-filter-value-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, extraProperties: { classPropertyName: "extraProperties", publicName: "extraProperties", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
20478
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FilterValueField, isStandalone: true, selector: "mt-filter-value-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, extraProperties: { classPropertyName: "extraProperties", publicName: "extraProperties", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block" }, providers: [
|
|
20477
20479
|
{
|
|
20478
20480
|
provide: NG_VALUE_ACCESSOR,
|
|
20479
20481
|
useExisting: forwardRef(() => FilterValueField),
|
|
20480
20482
|
multi: true,
|
|
20481
20483
|
},
|
|
20482
|
-
], viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Label -->\r\n @if (label()) {\r\n <label class=\"block text-sm font-medium text-color mb-1\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <!-- Input Group with Popover Trigger -->\r\n <p-inputgroup>\r\n <input\r\n type=\"text\"\r\n pInputText\r\n class=\"w-full\"\r\n [value]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n [disabled]=\"disabled()\"\r\n [placeholder]=\"placeholder()\"\r\n />\r\n <p-inputgroup-addon class=\"!p-0\">\r\n <mt-button\r\n icon=\"arrow.chevron-down\"\r\n variant=\"text\"\r\n [disabled]=\"disabled()\"\r\n size=\"small\"\r\n (click)=\"togglePopover($event)\"\r\n />\r\n </p-inputgroup-addon>\r\n </p-inputgroup>\r\n\r\n <!-- Popover Panel -->\r\n <p-popover #popover appendTo=\"body\" [style]=\"{ width: '360px' }\">\r\n <div class=\"flex flex-col gap-3\">\r\n <!-- Tabs -->\r\n @if (tabOptions().length > 0) {\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions()\" size=\"small\" />\r\n }\r\n\r\n <!-- Options Grid -->\r\n <div class=\"max-h-64 overflow-y-auto\">\r\n <div class=\"grid grid-cols-2 gap-2\">\r\n @for (option of currentTabOptions; track option.value) {\r\n <div\r\n class=\"col-span-1\"\r\n [class.col-span-2]=\"option.isDate && isOptionSelected(option)\"\r\n >\r\n <div\r\n class=\"border rounded-lg transition-all cursor-pointer\"\r\n [class.border-primary-500]=\"isOptionSelected(option)\"\r\n [class.bg-primary-50]=\"isOptionSelected(option)\"\r\n [class.border-surface-200]=\"!isOptionSelected(option)\"\r\n [class.hover:border-primary-300]=\"!isOptionSelected(option)\"\r\n >\r\n <!-- Option Button -->\r\n <div\r\n class=\"px-3 py-2 text-sm flex items-center gap-2\"\r\n (click)=\"toggleOption(option)\"\r\n >\r\n @if (option.icon) {\r\n <mt-icon [icon]=\"option.icon\" class=\"text-muted-color\" />\r\n }\r\n <span class=\"flex-1 truncate\">{{ option.label }}</span>\r\n @if (isOptionSelected(option)) {\r\n <mt-icon icon=\"general.check\" class=\"text-primary-600\" />\r\n }\r\n </div>\r\n\r\n <!-- Date Modifier (shown when date option is selected) -->\r\n @if (option.isDate && isOptionSelected(option)) {\r\n <div\r\n class=\"px-3 py-2 border-t border-surface-200 bg-surface-50 rounded-b-lg\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <!-- Sign Toggle -->\r\n <mt-button\r\n [label]=\"option.modifier?.isPositive ? '+' : '-'\"\r\n [variant]=\"\r\n option.modifier?.isPositive ? 'outlined' : 'outlined'\r\n \"\r\n size=\"small\"\r\n [class.!border-green-500]=\"option.modifier?.isPositive\"\r\n [class.!text-green-600]=\"option.modifier?.isPositive\"\r\n [class.!border-red-500]=\"!option.modifier?.isPositive\"\r\n [class.!text-red-600]=\"!option.modifier?.isPositive\"\r\n (click)=\"toggleSign(option, $event)\"\r\n />\r\n\r\n <!-- Count Input -->\r\n <mt-number-field\r\n class=\"w-20\"\r\n [ngModel]=\"option.modifier?.count\"\r\n (ngModelChange)=\"updateCount(option, $event)\"\r\n [min]=\"0\"\r\n [showButtons]=\"false\"\r\n size=\"small\"\r\n />\r\n\r\n <!-- Unit Select -->\r\n <p-select\r\n [ngModel]=\"option.modifier?.unit\"\r\n (ngModelChange)=\"updateUnit(option, $event)\"\r\n [options]=\"unitOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n size=\"small\"\r\n class=\"w-24\"\r\n appendTo=\"body\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (currentTabOptions.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noOptionsAvailable\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i3.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
20484
|
+
], viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Label -->\r\n @if (label()) {\r\n <label class=\"block text-sm font-medium text-color mb-1\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <!-- Input Group with Popover Trigger -->\r\n <p-inputgroup>\r\n <input\r\n type=\"text\"\r\n pInputText\r\n class=\"w-full\"\r\n [value]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [placeholder]=\"placeholder()\"\r\n />\r\n <p-inputgroup-addon class=\"!p-0\">\r\n <mt-button\r\n icon=\"arrow.chevron-down\"\r\n variant=\"text\"\r\n [disabled]=\"disabled() || readonly()\"\r\n size=\"small\"\r\n (click)=\"togglePopover($event)\"\r\n />\r\n </p-inputgroup-addon>\r\n </p-inputgroup>\r\n\r\n <!-- Popover Panel -->\r\n <p-popover #popover appendTo=\"body\" [style]=\"{ width: '360px' }\">\r\n <div class=\"flex flex-col gap-3\">\r\n <!-- Tabs -->\r\n @if (tabOptions().length > 0) {\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions()\" size=\"small\" />\r\n }\r\n\r\n <!-- Options Grid -->\r\n <div class=\"max-h-64 overflow-y-auto\">\r\n <div class=\"grid grid-cols-2 gap-2\">\r\n @for (option of currentTabOptions; track option.value) {\r\n <div\r\n class=\"col-span-1\"\r\n [class.col-span-2]=\"option.isDate && isOptionSelected(option)\"\r\n >\r\n <div\r\n class=\"border rounded-lg transition-all cursor-pointer\"\r\n [class.border-primary-500]=\"isOptionSelected(option)\"\r\n [class.bg-primary-50]=\"isOptionSelected(option)\"\r\n [class.border-surface-200]=\"!isOptionSelected(option)\"\r\n [class.hover:border-primary-300]=\"!isOptionSelected(option)\"\r\n >\r\n <!-- Option Button -->\r\n <div\r\n class=\"px-3 py-2 text-sm flex items-center gap-2\"\r\n (click)=\"toggleOption(option)\"\r\n >\r\n @if (option.icon) {\r\n <mt-icon [icon]=\"option.icon\" class=\"text-muted-color\" />\r\n }\r\n <span class=\"flex-1 truncate\">{{ option.label }}</span>\r\n @if (isOptionSelected(option)) {\r\n <mt-icon icon=\"general.check\" class=\"text-primary-600\" />\r\n }\r\n </div>\r\n\r\n <!-- Date Modifier (shown when date option is selected) -->\r\n @if (option.isDate && isOptionSelected(option)) {\r\n <div\r\n class=\"px-3 py-2 border-t border-surface-200 bg-surface-50 rounded-b-lg\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <!-- Sign Toggle -->\r\n <mt-button\r\n [label]=\"option.modifier?.isPositive ? '+' : '-'\"\r\n [variant]=\"\r\n option.modifier?.isPositive ? 'outlined' : 'outlined'\r\n \"\r\n size=\"small\"\r\n [class.!border-green-500]=\"option.modifier?.isPositive\"\r\n [class.!text-green-600]=\"option.modifier?.isPositive\"\r\n [class.!border-red-500]=\"!option.modifier?.isPositive\"\r\n [class.!text-red-600]=\"!option.modifier?.isPositive\"\r\n (click)=\"toggleSign(option, $event)\"\r\n />\r\n\r\n <!-- Count Input -->\r\n <mt-number-field\r\n class=\"w-20\"\r\n [ngModel]=\"option.modifier?.count\"\r\n (ngModelChange)=\"updateCount(option, $event)\"\r\n [min]=\"0\"\r\n [showButtons]=\"false\"\r\n size=\"small\"\r\n />\r\n\r\n <!-- Unit Select -->\r\n <p-select\r\n [ngModel]=\"option.modifier?.unit\"\r\n (ngModelChange)=\"updateUnit(option, $event)\"\r\n [options]=\"unitOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n size=\"small\"\r\n class=\"w-24\"\r\n appendTo=\"body\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (currentTabOptions.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noOptionsAvailable\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: InputGroupModule }, { kind: "component", type: i3.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "ngmodule", type: InputGroupAddonModule }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i6.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
20483
20485
|
}
|
|
20484
20486
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FilterValueField, decorators: [{
|
|
20485
20487
|
type: Component,
|
|
@@ -20504,11 +20506,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
20504
20506
|
},
|
|
20505
20507
|
], host: {
|
|
20506
20508
|
class: 'block',
|
|
20507
|
-
}, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Label -->\r\n @if (label()) {\r\n <label class=\"block text-sm font-medium text-color mb-1\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <!-- Input Group with Popover Trigger -->\r\n <p-inputgroup>\r\n <input\r\n type=\"text\"\r\n pInputText\r\n class=\"w-full\"\r\n [value]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n [disabled]=\"disabled()\"\r\n [placeholder]=\"placeholder()\"\r\n />\r\n <p-inputgroup-addon class=\"!p-0\">\r\n <mt-button\r\n icon=\"arrow.chevron-down\"\r\n variant=\"text\"\r\n [disabled]=\"disabled()\"\r\n size=\"small\"\r\n (click)=\"togglePopover($event)\"\r\n />\r\n </p-inputgroup-addon>\r\n </p-inputgroup>\r\n\r\n <!-- Popover Panel -->\r\n <p-popover #popover appendTo=\"body\" [style]=\"{ width: '360px' }\">\r\n <div class=\"flex flex-col gap-3\">\r\n <!-- Tabs -->\r\n @if (tabOptions().length > 0) {\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions()\" size=\"small\" />\r\n }\r\n\r\n <!-- Options Grid -->\r\n <div class=\"max-h-64 overflow-y-auto\">\r\n <div class=\"grid grid-cols-2 gap-2\">\r\n @for (option of currentTabOptions; track option.value) {\r\n <div\r\n class=\"col-span-1\"\r\n [class.col-span-2]=\"option.isDate && isOptionSelected(option)\"\r\n >\r\n <div\r\n class=\"border rounded-lg transition-all cursor-pointer\"\r\n [class.border-primary-500]=\"isOptionSelected(option)\"\r\n [class.bg-primary-50]=\"isOptionSelected(option)\"\r\n [class.border-surface-200]=\"!isOptionSelected(option)\"\r\n [class.hover:border-primary-300]=\"!isOptionSelected(option)\"\r\n >\r\n <!-- Option Button -->\r\n <div\r\n class=\"px-3 py-2 text-sm flex items-center gap-2\"\r\n (click)=\"toggleOption(option)\"\r\n >\r\n @if (option.icon) {\r\n <mt-icon [icon]=\"option.icon\" class=\"text-muted-color\" />\r\n }\r\n <span class=\"flex-1 truncate\">{{ option.label }}</span>\r\n @if (isOptionSelected(option)) {\r\n <mt-icon icon=\"general.check\" class=\"text-primary-600\" />\r\n }\r\n </div>\r\n\r\n <!-- Date Modifier (shown when date option is selected) -->\r\n @if (option.isDate && isOptionSelected(option)) {\r\n <div\r\n class=\"px-3 py-2 border-t border-surface-200 bg-surface-50 rounded-b-lg\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <!-- Sign Toggle -->\r\n <mt-button\r\n [label]=\"option.modifier?.isPositive ? '+' : '-'\"\r\n [variant]=\"\r\n option.modifier?.isPositive ? 'outlined' : 'outlined'\r\n \"\r\n size=\"small\"\r\n [class.!border-green-500]=\"option.modifier?.isPositive\"\r\n [class.!text-green-600]=\"option.modifier?.isPositive\"\r\n [class.!border-red-500]=\"!option.modifier?.isPositive\"\r\n [class.!text-red-600]=\"!option.modifier?.isPositive\"\r\n (click)=\"toggleSign(option, $event)\"\r\n />\r\n\r\n <!-- Count Input -->\r\n <mt-number-field\r\n class=\"w-20\"\r\n [ngModel]=\"option.modifier?.count\"\r\n (ngModelChange)=\"updateCount(option, $event)\"\r\n [min]=\"0\"\r\n [showButtons]=\"false\"\r\n size=\"small\"\r\n />\r\n\r\n <!-- Unit Select -->\r\n <p-select\r\n [ngModel]=\"option.modifier?.unit\"\r\n (ngModelChange)=\"updateUnit(option, $event)\"\r\n [options]=\"unitOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n size=\"small\"\r\n class=\"w-24\"\r\n appendTo=\"body\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (currentTabOptions.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noOptionsAvailable\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n</ng-container>\r\n" }]
|
|
20509
|
+
}, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Label -->\r\n @if (label()) {\r\n <label class=\"block text-sm font-medium text-color mb-1\">\r\n {{ label() }}\r\n </label>\r\n }\r\n\r\n <!-- Input Group with Popover Trigger -->\r\n <p-inputgroup>\r\n <input\r\n type=\"text\"\r\n pInputText\r\n class=\"w-full\"\r\n [value]=\"value()\"\r\n (input)=\"onInputChange($any($event.target).value)\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [placeholder]=\"placeholder()\"\r\n />\r\n <p-inputgroup-addon class=\"!p-0\">\r\n <mt-button\r\n icon=\"arrow.chevron-down\"\r\n variant=\"text\"\r\n [disabled]=\"disabled() || readonly()\"\r\n size=\"small\"\r\n (click)=\"togglePopover($event)\"\r\n />\r\n </p-inputgroup-addon>\r\n </p-inputgroup>\r\n\r\n <!-- Popover Panel -->\r\n <p-popover #popover appendTo=\"body\" [style]=\"{ width: '360px' }\">\r\n <div class=\"flex flex-col gap-3\">\r\n <!-- Tabs -->\r\n @if (tabOptions().length > 0) {\r\n <mt-tabs [(active)]=\"activeTab\" [options]=\"tabOptions()\" size=\"small\" />\r\n }\r\n\r\n <!-- Options Grid -->\r\n <div class=\"max-h-64 overflow-y-auto\">\r\n <div class=\"grid grid-cols-2 gap-2\">\r\n @for (option of currentTabOptions; track option.value) {\r\n <div\r\n class=\"col-span-1\"\r\n [class.col-span-2]=\"option.isDate && isOptionSelected(option)\"\r\n >\r\n <div\r\n class=\"border rounded-lg transition-all cursor-pointer\"\r\n [class.border-primary-500]=\"isOptionSelected(option)\"\r\n [class.bg-primary-50]=\"isOptionSelected(option)\"\r\n [class.border-surface-200]=\"!isOptionSelected(option)\"\r\n [class.hover:border-primary-300]=\"!isOptionSelected(option)\"\r\n >\r\n <!-- Option Button -->\r\n <div\r\n class=\"px-3 py-2 text-sm flex items-center gap-2\"\r\n (click)=\"toggleOption(option)\"\r\n >\r\n @if (option.icon) {\r\n <mt-icon [icon]=\"option.icon\" class=\"text-muted-color\" />\r\n }\r\n <span class=\"flex-1 truncate\">{{ option.label }}</span>\r\n @if (isOptionSelected(option)) {\r\n <mt-icon icon=\"general.check\" class=\"text-primary-600\" />\r\n }\r\n </div>\r\n\r\n <!-- Date Modifier (shown when date option is selected) -->\r\n @if (option.isDate && isOptionSelected(option)) {\r\n <div\r\n class=\"px-3 py-2 border-t border-surface-200 bg-surface-50 rounded-b-lg\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <!-- Sign Toggle -->\r\n <mt-button\r\n [label]=\"option.modifier?.isPositive ? '+' : '-'\"\r\n [variant]=\"\r\n option.modifier?.isPositive ? 'outlined' : 'outlined'\r\n \"\r\n size=\"small\"\r\n [class.!border-green-500]=\"option.modifier?.isPositive\"\r\n [class.!text-green-600]=\"option.modifier?.isPositive\"\r\n [class.!border-red-500]=\"!option.modifier?.isPositive\"\r\n [class.!text-red-600]=\"!option.modifier?.isPositive\"\r\n (click)=\"toggleSign(option, $event)\"\r\n />\r\n\r\n <!-- Count Input -->\r\n <mt-number-field\r\n class=\"w-20\"\r\n [ngModel]=\"option.modifier?.count\"\r\n (ngModelChange)=\"updateCount(option, $event)\"\r\n [min]=\"0\"\r\n [showButtons]=\"false\"\r\n size=\"small\"\r\n />\r\n\r\n <!-- Unit Select -->\r\n <p-select\r\n [ngModel]=\"option.modifier?.unit\"\r\n (ngModelChange)=\"updateUnit(option, $event)\"\r\n [options]=\"unitOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n size=\"small\"\r\n class=\"w-24\"\r\n appendTo=\"body\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (currentTabOptions.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noOptionsAvailable\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n</ng-container>\r\n" }]
|
|
20508
20510
|
}], ctorParameters: () => [], propDecorators: { popover: [{
|
|
20509
20511
|
type: ViewChild,
|
|
20510
20512
|
args: ['popover']
|
|
20511
|
-
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], extraProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraProperties", required: false }] }] } });
|
|
20513
|
+
}], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], extraProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraProperties", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }] } });
|
|
20512
20514
|
|
|
20513
20515
|
/**
|
|
20514
20516
|
* Selection Configuration Component
|
|
@@ -20711,10 +20713,20 @@ class SelectionConfiguration {
|
|
|
20711
20713
|
}
|
|
20712
20714
|
// ==================== ControlValueAccessor ====================
|
|
20713
20715
|
writeValue(value) {
|
|
20714
|
-
|
|
20716
|
+
// The parent binds [ngModel]="selections()" + (ngModelChange)="selections.set(...)",
|
|
20717
|
+
// so every value we emit comes straight back here. Rebuilding the form array on
|
|
20718
|
+
// such an echo re-fires valueChanges -> emitValue -> onChange -> writeValue in an
|
|
20719
|
+
// infinite loop (the UI "lock"), and also destroys input focus mid-typing. Skip
|
|
20720
|
+
// the rebuild when the incoming value already matches the current form.
|
|
20721
|
+
if (JSON.stringify(value ?? []) === JSON.stringify(this.getCleanValue())) {
|
|
20722
|
+
return;
|
|
20723
|
+
}
|
|
20724
|
+
this.selectionsArray.clear({ emitEvent: false });
|
|
20715
20725
|
if (value?.length) {
|
|
20716
20726
|
value.forEach((sel) => {
|
|
20717
|
-
this.selectionsArray.push(this.createSelectionFormGroup(sel)
|
|
20727
|
+
this.selectionsArray.push(this.createSelectionFormGroup(sel), {
|
|
20728
|
+
emitEvent: false,
|
|
20729
|
+
});
|
|
20718
20730
|
});
|
|
20719
20731
|
}
|
|
20720
20732
|
this.prefetchPropertyItems();
|
|
@@ -20874,9 +20886,23 @@ class SelectionConfiguration {
|
|
|
20874
20886
|
const serviceName = selection?.get('service')?.value;
|
|
20875
20887
|
return this.getGroupedModulesForService(serviceName);
|
|
20876
20888
|
}
|
|
20889
|
+
/**
|
|
20890
|
+
* Per-selector cache so the template binding `[ngModel]="getSelectorValues(i)"`
|
|
20891
|
+
* returns the SAME array reference for the same selector string. Returning a
|
|
20892
|
+
* fresh array on every change-detection pass makes the `mt-multi-select-field`
|
|
20893
|
+
* CVA re-run `writeValue()` -> signal set -> mark dirty -> another pass ->
|
|
20894
|
+
* infinite change detection (the UI freeze on Add). `splitCombinedSelector`
|
|
20895
|
+
* is pure, so caching by its string input is always correct.
|
|
20896
|
+
*/
|
|
20897
|
+
selectorValuesCache = new Map();
|
|
20877
20898
|
getSelectorValues(selectionIndex) {
|
|
20878
|
-
const
|
|
20879
|
-
|
|
20899
|
+
const selector = this.selectionsArray.at(selectionIndex)?.get('selector')?.value ?? '';
|
|
20900
|
+
let cached = this.selectorValuesCache.get(selector);
|
|
20901
|
+
if (!cached) {
|
|
20902
|
+
cached = this.splitCombinedSelector(selector);
|
|
20903
|
+
this.selectorValuesCache.set(selector, cached);
|
|
20904
|
+
}
|
|
20905
|
+
return cached;
|
|
20880
20906
|
}
|
|
20881
20907
|
// ==================== Filter Actions ====================
|
|
20882
20908
|
addFilter(selectionIndex) {
|
|
@@ -21080,17 +21106,19 @@ class SelectionConfiguration {
|
|
|
21080
21106
|
return viewType === 'lookup' || viewType === 'status';
|
|
21081
21107
|
}
|
|
21082
21108
|
// ==================== Helpers ====================
|
|
21083
|
-
|
|
21109
|
+
/** Build the outward ISelection[] value with UI-only fields stripped. */
|
|
21110
|
+
getCleanValue() {
|
|
21084
21111
|
const rawValue = this.selectionsArray.value;
|
|
21085
|
-
|
|
21086
|
-
const cleanValue = rawValue.map((sel) => ({
|
|
21112
|
+
return rawValue.map((sel) => ({
|
|
21087
21113
|
id: sel.id,
|
|
21088
21114
|
service: sel.service,
|
|
21089
21115
|
selector: sel.selector,
|
|
21090
21116
|
selectorName: sel.selectorName,
|
|
21091
21117
|
filters: sel.filters,
|
|
21092
21118
|
}));
|
|
21093
|
-
|
|
21119
|
+
}
|
|
21120
|
+
emitValue() {
|
|
21121
|
+
this.onChange(this.getCleanValue());
|
|
21094
21122
|
}
|
|
21095
21123
|
isSelectionStructureLocked(selectionId) {
|
|
21096
21124
|
return this.structureLocked() || this.isFixedSelection(selectionId);
|
|
@@ -21113,7 +21141,7 @@ class SelectionConfiguration {
|
|
|
21113
21141
|
useExisting: forwardRef(() => SelectionConfiguration),
|
|
21114
21142
|
multi: true,
|
|
21115
21143
|
},
|
|
21116
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [disabled]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
21144
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties", "readonly"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
21117
21145
|
}
|
|
21118
21146
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SelectionConfiguration, decorators: [{
|
|
21119
21147
|
type: Component,
|
|
@@ -21142,7 +21170,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
21142
21170
|
useExisting: forwardRef(() => SelectionConfiguration),
|
|
21143
21171
|
multi: true,
|
|
21144
21172
|
},
|
|
21145
|
-
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [disabled]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [disabled]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n" }]
|
|
21173
|
+
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n" }]
|
|
21146
21174
|
}], ctorParameters: () => [], propDecorators: { structureLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "structureLocked", required: false }] }], workspaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "workspaceId", required: false }] }], modulesProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "modulesProperties", required: false }] }], propertiesFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertiesFlat", required: false }] }], moduleChange: [{ type: i0.Output, args: ["moduleChange"] }] } });
|
|
21147
21175
|
|
|
21148
21176
|
const RELATIONSHIP_PROPERTIES = [
|