@masterteam/dashboard-builder 0.0.30 → 0.0.31

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.
@@ -10503,7 +10503,7 @@ class ChartSettingsDrawer {
10503
10503
  return componentName === 'header' || componentName === 'topbar';
10504
10504
  }
10505
10505
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ChartSettingsDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
10506
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ChartSettingsDrawer, isStandalone: true, selector: "mt-chart-settings-drawer", ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n @if (showDisplayTab()) {\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Chart Controls Tab -->\r\n <div [hidden]=\"activeTab() !== 'chartControls'\" class=\"flex flex-col gap-3\">\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultControlConfig()\"\r\n [showIconSettings]=\"isLayoutItem()\"\r\n [layoutComponent]=\"layoutComponentName()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <!-- Pass-4: schema-driven controls fill the gap for chart/item types\r\n that don't have a bespoke quick-control component. Every supported\r\n chart in the manifest has a control schema in the registry, so\r\n this branch always renders real controls instead of\r\n noSettingsAvailable. -->\r\n <mt-schema-control-renderer\r\n [schema]=\"schemaForItem()\"\r\n [persisted]=\"itemConfig()\"\r\n [capability]=\"capability()\"\r\n scope=\"advanced\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Advanced Override (JSON) \u2014 Pass-2 -->\r\n <div [hidden]=\"activeTab() !== 'advanced'\" class=\"flex flex-col gap-3\">\r\n @if (activeTab() === \"advanced\") {\r\n <ng-container>\r\n <p class=\"text-xs text-muted-color\">\r\n Edit the chart's clientConfig as JSON. Use this only when the UI\r\n controls don't expose the field you need. JSON is validated and\r\n merged into existing clientConfig (top-level keys overwrite).\r\n Invalid JSON is never persisted.\r\n </p>\r\n <textarea\r\n class=\"font-mono text-xs w-full p-2 rounded border border-surface-300 bg-surface-50\"\r\n rows=\"14\"\r\n spellcheck=\"false\"\r\n (focus)=\"initAdvancedJsonIfNeeded()\"\r\n [value]=\"advancedJsonDraft()\"\r\n (input)=\"onAdvancedJsonChange($any($event.target).value)\"\r\n ></textarea>\r\n @if (advancedJsonError()) {\r\n <p class=\"text-xs text-red-600\">{{ advancedJsonError() }}</p>\r\n }\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n [label]=\"'Apply JSON'\"\r\n icon=\"general.check\"\r\n size=\"small\"\r\n (onClick)=\"applyAdvancedJson()\"\r\n />\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass + ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\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.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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DisplaySettings, selector: "mt-display-settings", inputs: ["config", "chartType", "availableProperties", "selectedProperties", "lookups"], outputs: ["clientConfigChange"] }, { kind: "component", type: DefaultControlUi, selector: "mt-default-control-ui", inputs: ["showIconSettings", "layoutComponent"] }, { kind: "component", type: PieControlUi, selector: "mt-pie-control-ui" }, { kind: "component", type: BarControlUi, selector: "mt-bar-control-ui" }, { kind: "component", type: StackBarControlUi, selector: "mt-stack-bar-control-ui" }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10506
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ChartSettingsDrawer, isStandalone: true, selector: "mt-chart-settings-drawer", ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass + ' flex h-full min-h-0 flex-col p-0'\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\r\n class=\"sticky top-0 z-10 border-b border-surface-200 bg-surface-0 px-4 pb-3 pt-4\"\r\n >\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto px-4 pb-4 pt-3\">\r\n @if (showDisplayTab()) {\r\n <!-- Display Tab -->\r\n <div [hidden]=\"activeTab() !== 'display'\" class=\"flex flex-col gap-3\">\r\n <mt-display-settings\r\n [config]=\"itemConfig()\"\r\n [chartType]=\"resolvedChartType()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Chart Controls Tab -->\r\n <div [hidden]=\"activeTab() !== 'chartControls'\" class=\"flex flex-col gap-3\">\r\n @switch (manageType()) {\r\n @case (\"default\") {\r\n <mt-default-control-ui\r\n [ngModel]=\"defaultControlConfig()\"\r\n [showIconSettings]=\"isLayoutItem()\"\r\n [layoutComponent]=\"layoutComponentName()\"\r\n (ngModelChange)=\"onDefaultConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"pie\") {\r\n <mt-pie-control-ui\r\n [ngModel]=\"pieConfig()\"\r\n (ngModelChange)=\"onPieConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"bar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"barConfig()\"\r\n (ngModelChange)=\"onBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"stackBar\") {\r\n <mt-stack-bar-control-ui\r\n [ngModel]=\"stackBarConfig()\"\r\n (ngModelChange)=\"onStackBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @case (\"snapshotBar\") {\r\n <mt-bar-control-ui\r\n [ngModel]=\"snapshotBarConfig()\"\r\n (ngModelChange)=\"onSnapshotBarConfigChange($event)\"\r\n />\r\n }\r\n\r\n @default {\r\n <!-- Pass-4: schema-driven controls fill the gap for chart/item types\r\n that don't have a bespoke quick-control component. Every supported\r\n chart in the manifest has a control schema in the registry, so\r\n this branch always renders real controls instead of\r\n noSettingsAvailable. -->\r\n <mt-schema-control-renderer\r\n [schema]=\"schemaForItem()\"\r\n [persisted]=\"itemConfig()\"\r\n [capability]=\"capability()\"\r\n scope=\"advanced\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Advanced Override (JSON) \u2014 Pass-2 -->\r\n <div [hidden]=\"activeTab() !== 'advanced'\" class=\"flex flex-col gap-3\">\r\n @if (activeTab() === \"advanced\") {\r\n <ng-container>\r\n <p class=\"text-xs text-muted-color\">\r\n Edit the chart's clientConfig as JSON. Use this only when the UI\r\n controls don't expose the field you need. JSON is validated and\r\n merged into existing clientConfig (top-level keys overwrite).\r\n Invalid JSON is never persisted.\r\n </p>\r\n <textarea\r\n class=\"font-mono text-xs w-full p-2 rounded border border-surface-300 bg-surface-50\"\r\n rows=\"14\"\r\n spellcheck=\"false\"\r\n (focus)=\"initAdvancedJsonIfNeeded()\"\r\n [value]=\"advancedJsonDraft()\"\r\n (input)=\"onAdvancedJsonChange($any($event.target).value)\"\r\n ></textarea>\r\n @if (advancedJsonError()) {\r\n <p class=\"text-xs text-red-600\">{{ advancedJsonError() }}</p>\r\n }\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n [label]=\"'Apply JSON'\"\r\n icon=\"general.check\"\r\n size=\"small\"\r\n (onClick)=\"applyAdvancedJson()\"\r\n />\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div\r\n [class]=\"\r\n modal.footerClass + ' border-t border-surface-200 bg-surface-0 px-4 py-3'\r\n \"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n <mt-button [label]=\"t('apply')\" icon=\"general.check\" (onClick)=\"apply()\" />\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.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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DisplaySettings, selector: "mt-display-settings", inputs: ["config", "chartType", "availableProperties", "selectedProperties", "lookups"], outputs: ["clientConfigChange"] }, { kind: "component", type: DefaultControlUi, selector: "mt-default-control-ui", inputs: ["showIconSettings", "layoutComponent"] }, { kind: "component", type: PieControlUi, selector: "mt-pie-control-ui" }, { kind: "component", type: BarControlUi, selector: "mt-bar-control-ui" }, { kind: "component", type: StackBarControlUi, selector: "mt-stack-bar-control-ui" }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10507
10507
  }
10508
10508
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ChartSettingsDrawer, decorators: [{
10509
10509
  type: Component,
@@ -10967,7 +10967,7 @@ class FilterValueField {
10967
10967
  useExisting: forwardRef(() => FilterValueField),
10968
10968
  multi: true,
10969
10969
  },
10970
- ], 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 No options available\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", "size", "fluid", "disabled"], 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 });
10970
+ ], 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 No options available\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 });
10971
10971
  }
10972
10972
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FilterValueField, decorators: [{
10973
10973
  type: Component,
@@ -11824,7 +11824,7 @@ class SourceLinkConfiguration {
11824
11824
  useExisting: forwardRef(() => SourceLinkConfiguration),
11825
11825
  multi: true,
11826
11826
  },
11827
- ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('sourceLinks')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addSourceLink()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addSourceLink')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"sourceLinksForm\">\r\n <div formArrayName=\"sourceLinks\">\r\n @for (\r\n link of sourceLinksArray.controls;\r\n track trackByIndex(i);\r\n let i = $index;\r\n let first = $first\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]=\"link.invalid\"\r\n [class.border-surface-200]=\"!link.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Link Header with Type Tabs -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-3\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n\r\n <!-- Link Type Tabs (only show for non-first links) -->\r\n @if (!first) {\r\n <mt-tabs\r\n [active]=\"getLinkType(i)\"\r\n (activeChange)=\"onLinkTypeChange(i, $event)\"\r\n [options]=\"getLinkTypeOptions(i)\"\r\n size=\"small\"\r\n />\r\n } @else {\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n {{ t(\"selectionToSelection\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSourceLink(i)\"\r\n />\r\n </div>\r\n\r\n <!-- Source Selections based on link type -->\r\n @if (getLinkType(i) === \"selection\") {\r\n <!-- Selection to Selection Mode -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source1')\"\r\n formControlName=\"source1SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n } @else {\r\n <!-- Chained Mode: Previous Link to Selection -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source Link (previous link) -->\r\n <mt-select-field\r\n [label]=\"t('previousLink')\"\r\n formControlName=\"sourceLinkId\"\r\n [options]=\"getAvailableSourceLinks(i)\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"index\"\r\n [placeholder]=\"t('selectPreviousLink')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Link Properties -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Property -->\r\n <mt-select-field\r\n [label]=\"t('source1LinkProperty')\"\r\n formControlName=\"source1PropertyKey\"\r\n [options]=\"getSource1PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n\r\n <!-- Source 2 Property -->\r\n <mt-select-field\r\n [label]=\"t('source2LinkProperty')\"\r\n formControlName=\"source2PropertyKey\"\r\n [options]=\"getSource2PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Join Options -->\r\n <div class=\"flex items-center gap-6\">\r\n <mt-toggle-field\r\n [label]=\"t('isLeftJoin')\"\r\n formControlName=\"isLeftJoin\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('isFilterLinkage')\"\r\n formControlName=\"isFilterLinkage\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (sourceLinksArray.length === 0) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-link-01 text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSourceLinksConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSourceLink')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSourceLink()\"\r\n />\r\n </div>\r\n }\r\n </div>\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: "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: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
11827
+ ], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('sourceLinks')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addSourceLink()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addSourceLink')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"sourceLinksForm\">\r\n <div formArrayName=\"sourceLinks\">\r\n @for (\r\n link of sourceLinksArray.controls;\r\n track trackByIndex(i);\r\n let i = $index;\r\n let first = $first\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]=\"link.invalid\"\r\n [class.border-surface-200]=\"!link.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Link Header with Type Tabs -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-3\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n\r\n <!-- Link Type Tabs (only show for non-first links) -->\r\n @if (!first) {\r\n <mt-tabs\r\n [active]=\"getLinkType(i)\"\r\n (activeChange)=\"onLinkTypeChange(i, $event)\"\r\n [options]=\"getLinkTypeOptions(i)\"\r\n size=\"small\"\r\n />\r\n } @else {\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n {{ t(\"selectionToSelection\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSourceLink(i)\"\r\n />\r\n </div>\r\n\r\n <!-- Source Selections based on link type -->\r\n @if (getLinkType(i) === \"selection\") {\r\n <!-- Selection to Selection Mode -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source1')\"\r\n formControlName=\"source1SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n } @else {\r\n <!-- Chained Mode: Previous Link to Selection -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source Link (previous link) -->\r\n <mt-select-field\r\n [label]=\"t('previousLink')\"\r\n formControlName=\"sourceLinkId\"\r\n [options]=\"getAvailableSourceLinks(i)\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"index\"\r\n [placeholder]=\"t('selectPreviousLink')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n\r\n <!-- Source 2 Selection -->\r\n <mt-select-field\r\n [label]=\"t('source2')\"\r\n formControlName=\"source2SelectionId\"\r\n [options]=\"selectionOptions()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"selectionId\"\r\n [placeholder]=\"t('selectSource')\"\r\n (ngModelChange)=\"onSourceChange(i)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Link Properties -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\r\n <!-- Source 1 Property -->\r\n <mt-select-field\r\n [label]=\"t('source1LinkProperty')\"\r\n formControlName=\"source1PropertyKey\"\r\n [options]=\"getSource1PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n\r\n <!-- Source 2 Property -->\r\n <mt-select-field\r\n [label]=\"t('source2LinkProperty')\"\r\n formControlName=\"source2PropertyKey\"\r\n [options]=\"getSource2PropertiesGrouped(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Join Options -->\r\n <div class=\"flex items-center gap-6\">\r\n <mt-toggle-field\r\n [label]=\"t('isLeftJoin')\"\r\n formControlName=\"isLeftJoin\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('isFilterLinkage')\"\r\n formControlName=\"isFilterLinkage\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (sourceLinksArray.length === 0) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-link-01 text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSourceLinksConfigured\") }}</p>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSourceLink')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSourceLink()\"\r\n />\r\n </div>\r\n }\r\n </div>\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: "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: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
11828
11828
  }
11829
11829
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SourceLinkConfiguration, decorators: [{
11830
11830
  type: Component,
@@ -13665,7 +13665,7 @@ class DataSourceSettings {
13665
13665
  };
13666
13666
  }
13667
13667
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DataSourceSettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
13668
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DataSourceSettings, isStandalone: true, selector: "mt-data-source-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, informativeContext: { classPropertyName: "informativeContext", publicName: "informativeContext", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { serviceConfigChange: "serviceConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Pass-2: Simple/Advanced toggle for progressive disclosure -->\r\n @if (!hideSelectionConfig()) {\r\n <div\r\n class=\"flex items-center justify-between rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-sm font-semibold text-surface-700\">\r\n {{ isAdvanced() ? \"Advanced data source\" : \"Simple data source\" }}\r\n </span>\r\n <span class=\"text-xs text-muted-color\">\r\n {{\r\n isAdvanced()\r\n ? \"All options are visible, including custom API, multi-selection joins, and advanced filters.\"\r\n : \"Only the essential fields are shown. Switch to Advanced for full power.\"\r\n }}\r\n </span>\r\n </div>\r\n <mt-toggle-field\r\n label=\"Advanced\"\r\n [ngModel]=\"isAdvanced()\"\r\n (ngModelChange)=\"onDisclosureToggle($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Data Source Type Tabs (visible only in Advanced \u2014 hidden for layout/snapshot/phaseGate) -->\r\n @if (!hideSelectionConfig() && isAdvanced()) {\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"id\"\r\n [active]=\"activeTab()\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n }\r\n\r\n <!-- Custom API Configuration Tab (Advanced only) -->\r\n @if (!hideSelectionConfig() && isAdvanced()) {\r\n <div [hidden]=\"activeTab() !== 'customApi'\">\r\n <mt-custom-api-configuration\r\n [ngModel]=\"customApi()\"\r\n (ngModelChange)=\"onCustomApiChange($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Selection Configuration Tab (always visible in Simple; switches between Selection/Custom-API only in Advanced) -->\r\n <div\r\n [hidden]=\"isAdvanced() && activeTab() !== 'selection'\"\r\n class=\"flex flex-col gap-6\"\r\n >\r\n <!-- Selection Configuration (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <!-- Step 1 label -->\r\n <div\r\n class=\"flex items-center gap-2 text-sm font-semibold text-surface-700\"\r\n >\r\n <span\r\n class=\"w-6 h-6 inline-flex items-center justify-center rounded-full bg-primary-100 text-primary-600 text-xs font-bold\"\r\n >1</span\r\n >\r\n {{ \"Source / Entity\" }}\r\n </div>\r\n\r\n @if (showInformativeSelectionMode()) {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-toggle-field\r\n [label]=\"'Advanced selection'\"\r\n [ngModel]=\"selectionMode() === 'advanced'\"\r\n (ngModelChange)=\"onAdvancedSelectionToggle($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (!showInformativeSelectionMode() || selectionMode() === \"advanced\") {\r\n <div class=\"flex flex-col gap-6\">\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n (moduleChange)=\"onModuleChange($event)\"\r\n />\r\n\r\n <!-- Source Link Configuration (Advanced only, when multiple selections) -->\r\n @if (showSourceLinks() && isAdvanced()) {\r\n <mt-source-link-configuration\r\n [selectionModules]=\"selectionModules()\"\r\n [ngModel]=\"sourceLinks()\"\r\n (ngModelChange)=\"onSourceLinksChange($event)\"\r\n />\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-6\">\r\n <mt-informative-context-selection\r\n class=\"block\"\r\n [informativeContext]=\"informativeContext()\"\r\n [currentSelection]=\"selections()\"\r\n [preferredTargetSelector]=\"contextTargetSelector()\"\r\n [applyToken]=\"contextTargetApplyToken()\"\r\n (templateApply)=\"onContextTemplateApply($event)\"\r\n />\r\n\r\n @if (selections().length) {\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [structureLocked]=\"true\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Loading Skeleton for Query Configuration -->\r\n @if (loadingProperties()) {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton for field labels and inputs -->\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"120px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"grid grid-cols-2 gap-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"90px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"140px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <!-- Step 2 label (only shown when there is a query editor to render) -->\r\n @if (queryComponentType() !== \"none\" && !hideSelectionConfig()) {\r\n <div\r\n class=\"flex items-center gap-2 text-sm font-semibold text-surface-700\"\r\n >\r\n <span\r\n class=\"w-6 h-6 inline-flex items-center justify-center rounded-full bg-primary-100 text-primary-600 text-xs font-bold\"\r\n >2</span\r\n >\r\n {{ \"Fields & query\" }}\r\n </div>\r\n }\r\n\r\n <!-- Query Configuration based on chart type -->\r\n @switch (queryComponentType()) {\r\n @case (\"general\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"mb-4 flex items-center\">\r\n <mt-toggle-field\r\n [label]=\"t('isNormalized')\"\r\n [ngModel]=\"isNormalized()\"\r\n (ngModelChange)=\"onIsNormalizedChange($event)\"\r\n />\r\n </div>\r\n <mt-general-query\r\n [chartType]=\"getChartTypeId()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"table\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <!-- Group By Multiple (for non-report table views) -->\r\n @if (showGroupByMultiple()) {\r\n <div class=\"mb-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByMultiple')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectGroupByProperties')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"groupByMultiple()\"\r\n (ngModelChange)=\"onGroupByMultipleChange($event)\"\r\n />\r\n </div>\r\n }\r\n <mt-table-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTableQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timeline\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-timeline-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTimelineQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timelineMultiLevel\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-6\">\r\n <div class=\"flex items-center justify-between\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"timelineMultiLevelDescription\") }}\r\n </p>\r\n <mt-button\r\n size=\"small\"\r\n severity=\"secondary\"\r\n icon=\"general.plus\"\r\n [label]=\"t('addLevel')\"\r\n (onClick)=\"addTimelineLevel()\"\r\n />\r\n </div>\r\n\r\n @for (level of timelineLevels(); track $index) {\r\n <div\r\n class=\"border border-surface-300 rounded-md p-4 flex flex-col gap-3\"\r\n >\r\n <div class=\"flex items-center justify-between\">\r\n <span class=\"font-medium\">\r\n {{ t(\"level\") }} {{ level.levelNumber || $index + 1 }}\r\n </span>\r\n <mt-button\r\n size=\"small\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n icon=\"general.trash-02\"\r\n (onClick)=\"removeTimelineLevel($index)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <mt-select-field\r\n [label]=\"t('pivotProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.pivotProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'pivotProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.lookupProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'lookupProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('timeFrame')\"\r\n [options]=\"timeFrameOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"level.timeFrame\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField($index, 'timeFrame', $event)\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('startTimeProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.startPoint_timeProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'startPoint_timeProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('endTimeProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.endPoint_timeProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'endPoint_timeProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('parentProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.parentProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'parentProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <mt-multi-select-field\r\n [label]=\"t('extraProperties')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.extras || []\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField($index, 'extras', $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n\r\n @if (timelineLevels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noTimelineLevelsHint\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"map\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-map-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onMapQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"splitter\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-splitter-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSplitterQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"properties\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-properties-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onPropertiesQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"snapshot\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-snapshot-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSnapshotQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"phaseGate\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-3\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"phaseGateLevelIdHint\") }}\r\n </p>\r\n <mt-text-field\r\n [label]=\"t('levelId')\"\r\n [placeholder]=\"'{{levelId}}'\"\r\n [ngModel]=\"phaseGateLevelId()\"\r\n (ngModelChange)=\"onPhaseGateLevelIdChange($event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"repeater\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('selectDashboard')\"\r\n [options]=\"availableDashboards()\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectDashboardPlaceholder')\"\r\n [ngModel]=\"repeaterDashboardId()\"\r\n (ngModelChange)=\"onRepeaterDashboardChange($event)\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('repeaterSelectedProperties')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('repeaterSelectedPropertiesPlaceholder')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"repeaterSelectedProperties()\"\r\n (ngModelChange)=\"onRepeaterSelectedPropertiesChange($event)\"\r\n />\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"repeaterDescription\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"none\") {\r\n <!-- No query configuration needed for layout components -->\r\n }\r\n }\r\n }\r\n </div>\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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], 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: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { 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: SelectionConfiguration, selector: "mt-selection-configuration", inputs: ["structureLocked", "modulesProperties", "propertiesFlat"], outputs: ["moduleChange"] }, { kind: "component", type: SourceLinkConfiguration, selector: "mt-source-link-configuration", inputs: ["selectionModules"] }, { kind: "component", type: CustomApiConfiguration, selector: "mt-custom-api-configuration" }, { kind: "component", type: GeneralQuery, selector: "mt-general-query", inputs: ["chartType", "propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TableQuery, selector: "mt-table-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TimelineQuery, selector: "mt-timeline-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: PropertiesQuery, selector: "mt-properties-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SnapshotQuery, selector: "mt-snapshot-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: MapQuery, selector: "mt-map-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SplitterQuery, selector: "mt-splitter-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: InformativeContextSelection, selector: "mt-informative-context-selection", inputs: ["informativeContext", "currentSelection", "preferredTargetSelector", "applyToken"], outputs: ["templateApply"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13668
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DataSourceSettings, isStandalone: true, selector: "mt-data-source-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, informativeContext: { classPropertyName: "informativeContext", publicName: "informativeContext", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { serviceConfigChange: "serviceConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Pass-2: Simple/Advanced toggle for progressive disclosure -->\r\n @if (!hideSelectionConfig()) {\r\n <div\r\n class=\"flex items-center justify-between rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <div class=\"flex flex-col\">\r\n <span class=\"text-sm font-semibold text-surface-700\">\r\n {{ isAdvanced() ? \"Advanced data source\" : \"Simple data source\" }}\r\n </span>\r\n <span class=\"text-xs text-muted-color\">\r\n {{\r\n isAdvanced()\r\n ? \"All options are visible, including custom API, multi-selection joins, and advanced filters.\"\r\n : \"Only the essential fields are shown. Switch to Advanced for full power.\"\r\n }}\r\n </span>\r\n </div>\r\n <mt-toggle-field\r\n label=\"Advanced\"\r\n [ngModel]=\"isAdvanced()\"\r\n (ngModelChange)=\"onDisclosureToggle($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Data Source Type Tabs (visible only in Advanced \u2014 hidden for layout/snapshot/phaseGate) -->\r\n @if (!hideSelectionConfig() && isAdvanced()) {\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"id\"\r\n [active]=\"activeTab()\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n }\r\n\r\n <!-- Custom API Configuration Tab (Advanced only) -->\r\n @if (!hideSelectionConfig() && isAdvanced()) {\r\n <div [hidden]=\"activeTab() !== 'customApi'\">\r\n <mt-custom-api-configuration\r\n [ngModel]=\"customApi()\"\r\n (ngModelChange)=\"onCustomApiChange($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Selection Configuration Tab (always visible in Simple; switches between Selection/Custom-API only in Advanced) -->\r\n <div\r\n [hidden]=\"isAdvanced() && activeTab() !== 'selection'\"\r\n class=\"flex flex-col gap-6\"\r\n >\r\n <!-- Selection Configuration (hidden for layout, snapshot, phaseGate types) -->\r\n @if (!hideSelectionConfig()) {\r\n <!-- Step 1 label -->\r\n <div\r\n class=\"flex items-center gap-2 text-sm font-semibold text-surface-700\"\r\n >\r\n <span\r\n class=\"w-6 h-6 inline-flex items-center justify-center rounded-full bg-primary-100 text-primary-600 text-xs font-bold\"\r\n >1</span\r\n >\r\n {{ \"Source / Entity\" }}\r\n </div>\r\n\r\n @if (showInformativeSelectionMode()) {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-toggle-field\r\n [label]=\"'Advanced selection'\"\r\n [ngModel]=\"selectionMode() === 'advanced'\"\r\n (ngModelChange)=\"onAdvancedSelectionToggle($event)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (!showInformativeSelectionMode() || selectionMode() === \"advanced\") {\r\n <div class=\"flex flex-col gap-6\">\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n (moduleChange)=\"onModuleChange($event)\"\r\n />\r\n\r\n <!-- Source Link Configuration (Advanced only, when multiple selections) -->\r\n @if (showSourceLinks() && isAdvanced()) {\r\n <mt-source-link-configuration\r\n [selectionModules]=\"selectionModules()\"\r\n [ngModel]=\"sourceLinks()\"\r\n (ngModelChange)=\"onSourceLinksChange($event)\"\r\n />\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-6\">\r\n <mt-informative-context-selection\r\n class=\"block\"\r\n [informativeContext]=\"informativeContext()\"\r\n [currentSelection]=\"selections()\"\r\n [preferredTargetSelector]=\"contextTargetSelector()\"\r\n [applyToken]=\"contextTargetApplyToken()\"\r\n (templateApply)=\"onContextTemplateApply($event)\"\r\n />\r\n\r\n @if (selections().length) {\r\n <mt-selection-configuration\r\n [modulesProperties]=\"modulesProperties()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [structureLocked]=\"true\"\r\n [ngModel]=\"selections()\"\r\n (ngModelChange)=\"onSelectionsChange($event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Loading Skeleton for Query Configuration -->\r\n @if (loadingProperties()) {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton for field labels and inputs -->\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"120px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"100px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"grid grid-cols-2 gap-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"90px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"140px\" height=\"16px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <!-- Step 2 label (only shown when there is a query editor to render) -->\r\n @if (queryComponentType() !== \"none\" && !hideSelectionConfig()) {\r\n <div\r\n class=\"flex items-center gap-2 text-sm font-semibold text-surface-700\"\r\n >\r\n <span\r\n class=\"w-6 h-6 inline-flex items-center justify-center rounded-full bg-primary-100 text-primary-600 text-xs font-bold\"\r\n >2</span\r\n >\r\n {{ \"Fields & query\" }}\r\n </div>\r\n }\r\n\r\n <!-- Query Configuration based on chart type -->\r\n @switch (queryComponentType()) {\r\n @case (\"general\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"mb-4 flex items-center\">\r\n <mt-toggle-field\r\n [label]=\"t('isNormalized')\"\r\n [ngModel]=\"isNormalized()\"\r\n (ngModelChange)=\"onIsNormalizedChange($event)\"\r\n />\r\n </div>\r\n <mt-general-query\r\n [chartType]=\"getChartTypeId()\"\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"table\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <!-- Group By Multiple (for non-report table views) -->\r\n @if (showGroupByMultiple()) {\r\n <div class=\"mb-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('groupByMultiple')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectGroupByProperties')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"groupByMultiple()\"\r\n (ngModelChange)=\"onGroupByMultipleChange($event)\"\r\n />\r\n </div>\r\n }\r\n <mt-table-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTableQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timeline\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-timeline-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onTimelineQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"timelineMultiLevel\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-6\">\r\n <div class=\"flex items-center justify-between\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"timelineMultiLevelDescription\") }}\r\n </p>\r\n <mt-button\r\n size=\"small\"\r\n severity=\"secondary\"\r\n icon=\"general.plus\"\r\n [label]=\"t('addLevel')\"\r\n (onClick)=\"addTimelineLevel()\"\r\n />\r\n </div>\r\n\r\n @for (level of timelineLevels(); track $index) {\r\n <div\r\n class=\"border border-surface-300 rounded-md p-4 flex flex-col gap-3\"\r\n >\r\n <div class=\"flex items-center justify-between\">\r\n <span class=\"font-medium\">\r\n {{ t(\"level\") }} {{ level.levelNumber || $index + 1 }}\r\n </span>\r\n <mt-button\r\n size=\"small\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n icon=\"general.trash-02\"\r\n (onClick)=\"removeTimelineLevel($index)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <mt-select-field\r\n [label]=\"t('pivotProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.pivotProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'pivotProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.lookupProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'lookupProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('timeFrame')\"\r\n [options]=\"timeFrameOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [ngModel]=\"level.timeFrame\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField($index, 'timeFrame', $event)\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('startTimeProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.startPoint_timeProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'startPoint_timeProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('endTimeProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.endPoint_timeProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'endPoint_timeProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('parentProperty')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.parentProperty\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField(\r\n $index,\r\n 'parentProperty',\r\n $event\r\n )\r\n \"\r\n />\r\n </div>\r\n\r\n <mt-multi-select-field\r\n [label]=\"t('extraProperties')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [ngModel]=\"level.extras || []\"\r\n (ngModelChange)=\"\r\n updateTimelineLevelField($index, 'extras', $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n\r\n @if (timelineLevels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noTimelineLevelsHint\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"map\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-map-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onMapQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"splitter\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-splitter-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSplitterQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"properties\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-properties-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onPropertiesQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"snapshot\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <mt-snapshot-query\r\n [propertiesFlat]=\"propertiesFlat()\"\r\n [propertiesGrouped]=\"propertiesGrouped()\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onSnapshotQueryChange($event)\"\r\n />\r\n </mt-card>\r\n }\r\n @case (\"phaseGate\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-3\">\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"phaseGateLevelIdHint\") }}\r\n </p>\r\n <mt-text-field\r\n [label]=\"t('levelId')\"\r\n [placeholder]=\"'{{levelId}}'\"\r\n [ngModel]=\"phaseGateLevelId()\"\r\n (ngModelChange)=\"onPhaseGateLevelIdChange($event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"repeater\") {\r\n <mt-card [title]=\"t('queryConfiguration')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [label]=\"t('selectDashboard')\"\r\n [options]=\"availableDashboards()\"\r\n optionLabel=\"name\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectDashboardPlaceholder')\"\r\n [ngModel]=\"repeaterDashboardId()\"\r\n (ngModelChange)=\"onRepeaterDashboardChange($event)\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('repeaterSelectedProperties')\"\r\n [options]=\"\r\n propertiesGrouped().length > 1\r\n ? propertiesGrouped()\r\n : propertiesFlat()\r\n \"\r\n [group]=\"propertiesGrouped().length > 1\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('repeaterSelectedPropertiesPlaceholder')\"\r\n [filter]=\"true\"\r\n [ngModel]=\"repeaterSelectedProperties()\"\r\n (ngModelChange)=\"onRepeaterSelectedPropertiesChange($event)\"\r\n />\r\n <p class=\"text-sm text-muted-color\">\r\n {{ t(\"repeaterDescription\") }}\r\n </p>\r\n </div>\r\n </mt-card>\r\n }\r\n @case (\"none\") {\r\n <!-- No query configuration needed for layout components -->\r\n }\r\n }\r\n }\r\n </div>\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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { 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: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], 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: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { 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: SelectionConfiguration, selector: "mt-selection-configuration", inputs: ["structureLocked", "modulesProperties", "propertiesFlat"], outputs: ["moduleChange"] }, { kind: "component", type: SourceLinkConfiguration, selector: "mt-source-link-configuration", inputs: ["selectionModules"] }, { kind: "component", type: CustomApiConfiguration, selector: "mt-custom-api-configuration" }, { kind: "component", type: GeneralQuery, selector: "mt-general-query", inputs: ["chartType", "propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TableQuery, selector: "mt-table-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: TimelineQuery, selector: "mt-timeline-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: PropertiesQuery, selector: "mt-properties-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SnapshotQuery, selector: "mt-snapshot-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: MapQuery, selector: "mt-map-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: SplitterQuery, selector: "mt-splitter-query", inputs: ["propertiesFlat", "propertiesGrouped"] }, { kind: "component", type: InformativeContextSelection, selector: "mt-informative-context-selection", inputs: ["informativeContext", "currentSelection", "preferredTargetSelector", "applyToken"], outputs: ["templateApply"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13669
13669
  }
13670
13670
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DataSourceSettings, decorators: [{
13671
13671
  type: Component,
@@ -26178,7 +26178,7 @@ class PropertiesCardComponent {
26178
26178
  return '';
26179
26179
  }
26180
26180
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
26181
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertiesCardComponent, isStandalone: true, selector: "mt-properties-card, mt-entities-preview-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n @if (showTabs()) {\n <div class=\"mb-3\">\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\n </div>\n }\n\n <div\n class=\"overflow-y-auto overflow-x-hidden\"\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\n >\n @if (currentTabCards().length === 0) {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n } @else {\n <div class=\"flex flex-wrap\">\n @for (cardView of currentTabCards(); track cardView.trackId) {\n <div\n class=\"mb-2 p-2\"\n [class.card-col]=\"!galleryMode()\"\n [class.gallery-card-col]=\"galleryMode()\"\n [class.w-full]=\"!galleryMode()\"\n [class.md:w-1/2]=\"!galleryMode()\"\n [class.lg:w-1/3]=\"!galleryMode()\"\n >\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white p-3 shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n @if (cardView.entities.length > 0) {\n <mt-entities-preview [entities]=\"cardView.entities\" />\n } @else {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}.card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
26181
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertiesCardComponent, isStandalone: true, selector: "mt-properties-card, mt-entities-preview-card", inputs: { dashboardId: { classPropertyName: "dashboardId", publicName: "dashboardId", isSignal: true, isRequired: true, transformFunction: null }, inGroup: { classPropertyName: "inGroup", publicName: "inGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onAction: "onAction" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n @if (showTabs()) {\n <div class=\"mb-3\">\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\n </div>\n }\n\n <div\n class=\"overflow-y-auto overflow-x-hidden\"\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\n >\n @if (currentTabCards().length === 0) {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n } @else {\n <div class=\"flex flex-wrap\">\n @for (cardView of currentTabCards(); track cardView.trackId) {\n <div\n class=\"mb-2 p-2\"\n [class.card-col]=\"!galleryMode()\"\n [class.gallery-card-col]=\"galleryMode()\"\n [class.w-full]=\"!galleryMode()\"\n [class.md:w-1/2]=\"!galleryMode()\"\n [class.lg:w-1/3]=\"!galleryMode()\"\n >\n <div\n class=\"h-full cursor-pointer rounded-lg bg-white p-3 shadow-sm transition-all hover:shadow-md\"\n (click)=\"onCardClick(cardView.card)\"\n >\n @if (cardView.entities.length > 0) {\n <mt-entities-preview [entities]=\"cardView.entities\" />\n } @else {\n <div class=\"py-6 text-center text-sm text-gray-400\">\n {{ t(\"noData\") }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n</ng-container>\n", styles: [":host{display:block;height:100%}.card-col{flex:0 0 100%}@media(min-width:768px){.card-col{flex:0 0 50%}}@media(min-width:1024px){.card-col{flex:0 0 33.333%}}.gallery-card-col{flex:0 0 100%}@media(min-width:640px){.gallery-card-col{flex:0 0 50%}}@media(min-width:1024px){.gallery-card-col{flex:0 0 25%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
26182
26182
  }
26183
26183
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesCardComponent, decorators: [{
26184
26184
  type: Component,
@@ -27204,7 +27204,7 @@ class ManageItem {
27204
27204
  this._manageItemService.updateClientConfig(partialConfig);
27205
27205
  }
27206
27206
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
27207
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ManageItem, isStandalone: true, selector: "mt-manage-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ManageItemService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n (chartTypeChange)=\"onChartTypeChange($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n [informativeContext]=\"informativeContext()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"cancel()\" />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: GeneralSettings, selector: "mt-general-settings", inputs: ["config", "isDialog", "hasPreselectedType"], outputs: ["configChange", "chartTypeChange"] }, { kind: "component", type: DataSourceSettings, selector: "mt-data-source-settings", inputs: ["config", "chartType", "informativeContext"], outputs: ["serviceConfigChange"] }, { kind: "component", type: ActionsSettings, selector: "mt-actions-settings", inputs: ["config"], outputs: ["clientConfigChange"] }, { kind: "component", type: ChartViewer, selector: "mt-chart-viewer", inputs: ["config", "chartTypeId"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
27207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ManageItem, isStandalone: true, selector: "mt-manage-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ManageItemService], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\r\n <!-- Main Layout: 60% Config | 40% Preview -->\r\n <div class=\"flex flex-1\">\r\n <!-- Left Side: Configuration (60%) -->\r\n <div class=\"w-[60%] flex flex-col border-r border-surface-200\">\r\n <!-- Content -->\r\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\r\n <!-- Chart Type Badge -->\r\n @if (selectedChartType()) {\r\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\r\n <span\r\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\r\n >\r\n <mt-icon\r\n [icon]=\"selectedChartType()?.icon\"\r\n class=\"text-xl\"\r\n ></mt-icon>\r\n </span>\r\n <div class=\"flex-1\">\r\n <h3 class=\"text-sm font-semibold text-surface-700\">\r\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\r\n </h3>\r\n <p class=\"text-xs text-muted-color\">\r\n {{ selectedChartType()?.name }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Tabs -->\r\n <mt-tabs\r\n [options]=\"tabOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n />\r\n\r\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\r\n <div [hidden]=\"activeTab() !== 'general'\">\r\n <mt-general-settings\r\n [config]=\"config()\"\r\n [isDialog]=\"isDialog()\"\r\n [hasPreselectedType]=\"hasPreselectedType()\"\r\n (configChange)=\"onConfigUpdate($event)\"\r\n (chartTypeChange)=\"onChartTypeChange($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'dataSource'\">\r\n <mt-data-source-settings\r\n [config]=\"config()\"\r\n [chartType]=\"selectedChartType()\"\r\n [informativeContext]=\"informativeContext()\"\r\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\r\n />\r\n </div>\r\n\r\n <div [hidden]=\"activeTab() !== 'actions'\">\r\n <mt-actions-settings\r\n [config]=\"config()\"\r\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Chart Preview (40%) -->\r\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\r\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <!-- Validation Status -->\r\n <div class=\"flex items-center gap-2 text-sm flex-1\">\r\n @if (isValid()) {\r\n <span class=\"flex items-center gap-1 text-green-600\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"ready\") }}\r\n </span>\r\n } @else {\r\n <span class=\"flex items-center gap-1 text-amber-600\">\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"incomplete\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"cancel()\" />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"!isValid()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: GeneralSettings, selector: "mt-general-settings", inputs: ["config", "isDialog", "hasPreselectedType"], outputs: ["configChange", "chartTypeChange"] }, { kind: "component", type: DataSourceSettings, selector: "mt-data-source-settings", inputs: ["config", "chartType", "informativeContext"], outputs: ["serviceConfigChange"] }, { kind: "component", type: ActionsSettings, selector: "mt-actions-settings", inputs: ["config"], outputs: ["clientConfigChange"] }, { kind: "component", type: ChartViewer, selector: "mt-chart-viewer", inputs: ["config", "chartTypeId"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
27208
27208
  }
27209
27209
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageItem, decorators: [{
27210
27210
  type: Component,
@@ -29255,7 +29255,7 @@ class ItemConfigPopoverComponent {
29255
29255
  return JSON.parse(JSON.stringify(item));
29256
29256
  }
29257
29257
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ItemConfigPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
29258
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ItemConfigPopoverComponent, isStandalone: true, selector: "mt-item-config-popover", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder.pass4'\">\r\n @if (item(); as currentItem) {\r\n <div class=\"db-config-popover\">\r\n <header class=\"db-config-popover__header\">\r\n <div class=\"db-config-popover__title-row\">\r\n <mt-icon\r\n [icon]=\"capability()?.icon ?? 'general.settings-02'\"\r\n class=\"db-config-popover__icon\"\r\n />\r\n <div class=\"db-config-popover__title\">\r\n <input\r\n type=\"text\"\r\n class=\"db-config-popover__title-input\"\r\n [ngModel]=\"ui()?.title?.title ?? ''\"\r\n (ngModelChange)=\"onTitleChange($event)\"\r\n [placeholder]=\"t('header.titlePlaceholder') || 'Untitled'\"\r\n />\r\n <span class=\"db-config-popover__chart-type\">\r\n {{ capability()?.name }}\r\n </span>\r\n </div>\r\n </div>\r\n <div class=\"db-config-popover__close\">\r\n <mt-button\r\n icon=\"general.x-close\"\r\n [tooltip]=\"t('header.close') || 'Close'\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n (onClick)=\"cancel()\"\r\n />\r\n </div>\r\n </header>\r\n\r\n <mt-tabs\r\n [options]=\"tabs()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n class=\"db-config-popover__tabs\"\r\n />\r\n\r\n <main class=\"db-config-popover__main\">\r\n <!-- DATA TAB -->\r\n <section [hidden]=\"activeTab() !== 'data'\" class=\"db-config-section\">\r\n <mt-datasource-panel\r\n [item]=\"currentItem\"\r\n (serviceConfigChange)=\"onServiceConfigPatch($event)\"\r\n (openAdvanced)=\"openAdvancedEditor('dataSource')\"\r\n />\r\n\r\n @if (issuesByDomain().datasource.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().datasource; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n @if (issuesByDomain().fields.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().fields; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </section>\r\n\r\n <!-- FILTERS TAB -->\r\n <section [hidden]=\"activeTab() !== 'filters'\" class=\"db-config-section\">\r\n <mt-filter-builder\r\n [chips]=\"chips()\"\r\n [persisted]=\"currentItem.config\"\r\n (chipsChange)=\"onChipsChange($event)\"\r\n />\r\n @if (issuesByDomain().filters.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().filters; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </section>\r\n\r\n <!-- STYLE TAB -->\r\n <section [hidden]=\"activeTab() !== 'style'\" class=\"db-config-section\">\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"style.presets\") || \"Presets\" }}\r\n </h4>\r\n <div class=\"db-style-presets\">\r\n @for (preset of presets(); track preset.key) {\r\n <button\r\n type=\"button\"\r\n class=\"db-style-preset\"\r\n [class.is-selected]=\"selectedPresetKey() === preset.key\"\r\n (click)=\"onApplyPreset(preset)\"\r\n >\r\n <span class=\"db-style-preset__label\">{{ preset.label }}</span>\r\n <span class=\"db-style-preset__desc\">{{\r\n preset.description\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"db-config-section__actions db-config-section__actions--scope\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"db-scope-toggle\"\r\n (click)=\"toggleControlScope()\"\r\n >\r\n <i\r\n [class]=\"\r\n 'mti mti-' +\r\n (controlScope() === 'advanced'\r\n ? 'general.eye'\r\n : 'general.eye-off')\r\n \"\r\n ></i>\r\n <span>\r\n {{\r\n controlScope() === \"advanced\"\r\n ? t(\"controls.simpleMode\") || \"Show simple controls\"\r\n : t(\"controls.advancedMode\") || \"Show all controls\"\r\n }}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <mt-schema-control-renderer\r\n [schema]=\"schema()\"\r\n [persisted]=\"persistedConfig()\"\r\n [capability]=\"capability()\"\r\n [scope]=\"controlScope()\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"\r\n t('style.openLegacyDrawer') || 'Power user: open legacy drawer'\r\n \"\r\n icon=\"general.settings-02\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [outlined]=\"true\"\r\n (onClick)=\"openChartSettingsDrawer()\"\r\n />\r\n </div>\r\n </section>\r\n\r\n <!-- BEHAVIOR TAB -->\r\n <section\r\n [hidden]=\"activeTab() !== 'behavior'\"\r\n class=\"db-config-section\"\r\n >\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"behavior.title\") || \"Card behavior\" }}\r\n </h4>\r\n <label class=\"db-style-row\">\r\n <span>\r\n {{ t(\"behavior.showFiltersBar\") || \"Show per-card filter bar\" }}\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"ui()?.behavior?.filtersBarVisible || false\"\r\n (change)=\"onShowFiltersBarChange($any($event.target).checked)\"\r\n />\r\n </label>\r\n <p class=\"db-config-summary__hint\">\r\n {{\r\n t(\"behavior.actionsCount\") ||\r\n ui()?.behavior?.cardActions + \" click action(s) configured\"\r\n }}\r\n ({{ ui()?.behavior?.cardActions || 0 }})\r\n </p>\r\n\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"t('behavior.openAdvanced') || 'Manage card actions'\"\r\n icon=\"general.cursor-click-02\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [outlined]=\"true\"\r\n (onClick)=\"openAdvancedEditor('actions')\"\r\n />\r\n </div>\r\n </section>\r\n\r\n <!-- ADVANCED TAB -->\r\n <section\r\n [hidden]=\"activeTab() !== 'advanced'\"\r\n class=\"db-config-section\"\r\n >\r\n <p class=\"db-config-summary__hint\">\r\n {{\r\n t(\"advanced.hint\") ||\r\n \"Edit clientConfig as JSON for fields the controls do not expose. Validated and merged. Invalid JSON is never persisted.\"\r\n }}\r\n </p>\r\n\r\n <mt-schema-control-renderer\r\n [schema]=\"schema()\"\r\n [persisted]=\"persistedConfig()\"\r\n [capability]=\"capability()\"\r\n scope=\"advanced\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"advanced.json\") || \"Raw clientConfig JSON\" }}\r\n </h4>\r\n <textarea\r\n class=\"db-config-advanced-editor\"\r\n rows=\"14\"\r\n spellcheck=\"false\"\r\n (focus)=\"initAdvancedJsonIfNeeded()\"\r\n [value]=\"advancedJsonDraft()\"\r\n (input)=\"onAdvancedJsonChange($any($event.target).value)\"\r\n ></textarea>\r\n @if (advancedJsonError()) {\r\n <p class=\"db-config-advanced-editor__error\">\r\n {{ advancedJsonError() }}\r\n </p>\r\n }\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"t('advanced.apply') || 'Apply JSON'\"\r\n icon=\"general.check\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n (onClick)=\"applyAdvancedJson()\"\r\n />\r\n </div>\r\n </section>\r\n </main>\r\n\r\n <footer class=\"db-config-popover__footer\">\r\n @if (hasErrors()) {\r\n <span\r\n class=\"db-config-popover__status db-config-popover__status--error\"\r\n >\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"footer.errors\") || \"Resolve the issues above before saving\" }}\r\n </span>\r\n } @else {\r\n <span class=\"db-config-popover__status db-config-popover__status--ok\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"footer.ready\") || \"Ready\" }}\r\n </span>\r\n }\r\n <mt-button\r\n [label]=\"t('footer.cancel') || 'Cancel'\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('footer.apply') || 'Apply'\"\r\n icon=\"general.check\"\r\n severity=\"primary\"\r\n [disabled]=\"hasErrors()\"\r\n (onClick)=\"apply()\"\r\n />\r\n </footer>\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".db-config-popover{display:flex;flex-direction:column;height:100%;width:100%;background:var(--p-surface-0, #fff)}.db-config-popover__header{display:flex;align-items:flex-start;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);gap:.75rem}.db-config-popover__title-row{display:flex;align-items:center;gap:.5rem;min-width:0;flex:1}.db-config-popover__icon{color:var(--p-primary-600, #2563eb);font-size:1.4rem}.db-config-popover__title{display:flex;flex-direction:column;gap:.15rem;min-width:0;flex:1}.db-config-popover__title-input{background:transparent;border:0;border-bottom:1px dashed transparent;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);padding:.05rem 0;width:100%;outline:none}.db-config-popover__title-input:hover{border-bottom-color:var(--p-surface-300, #d1d5db)}.db-config-popover__title-input:focus{border-bottom-color:var(--p-primary-500, #3b82f6)}.db-config-popover__chart-type{font-size:.7rem;color:var(--p-text-muted-color, #6b7280);text-transform:uppercase;letter-spacing:.05em}.db-config-popover__close{flex-shrink:0}.db-config-popover__tabs{border-bottom:1px solid var(--p-surface-200, #e5e7eb);padding:0 1rem}.db-config-popover__main{flex:1 1 0;min-height:0;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:1rem}.db-config-popover__footer{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-top:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);position:sticky;bottom:0}.db-config-popover__status{flex:1;display:inline-flex;align-items:center;gap:.4rem;font-size:.8rem}.db-config-popover__status--ok{color:var(--p-green-600, #16a34a)}.db-config-popover__status--error{color:var(--p-amber-600, #d97706)}.db-config-section{display:flex;flex-direction:column;gap:.75rem}.db-config-section__title{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--p-text-muted-color, #6b7280);margin:0}.db-config-section__actions{display:flex;justify-content:flex-end;gap:.5rem;padding-top:.5rem;border-top:1px dashed var(--p-surface-200, #e5e7eb)}.db-config-summary{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.4rem}.db-config-summary__row{display:grid;grid-template-columns:7rem 1fr;align-items:start;gap:.75rem;font-size:.8rem}.db-config-summary__key{color:var(--p-text-muted-color, #6b7280);font-weight:500}.db-config-summary__value{color:var(--p-text-color, #1f2937);word-break:break-word;display:inline-flex;flex-wrap:wrap;gap:.25rem}.db-config-summary__value--ok{color:var(--p-green-600, #16a34a);font-weight:600}.db-config-summary__value--missing{color:var(--p-amber-600, #d97706);font-weight:600}.db-config-summary__formula{background:var(--p-surface-50, #f9fafb);padding:.25rem .4rem;border-radius:.25rem;font-size:.75rem;word-break:break-all}.db-config-summary__hint{font-size:.78rem;color:var(--p-text-muted-color, #6b7280);margin:0}.db-config-chip{background:var(--p-surface-100, #f3f4f6);border:1px solid var(--p-surface-200, #e5e7eb);padding:.1rem .5rem;border-radius:999px;font-size:.75rem;color:var(--p-text-color, #1f2937)}.db-config-issues{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.25rem}.db-config-issue{display:flex;align-items:center;gap:.4rem;font-size:.78rem;padding:.4rem .55rem;border-radius:.4rem}.db-config-issue i{font-size:.85rem}.db-config-issue[data-severity=error]{color:var(--p-red-700, #b91c1c);background:var(--p-red-50, #fef2f2);border:1px solid var(--p-red-100, #fee2e2)}.db-config-issue[data-severity=warning]{color:var(--p-amber-700, #b45309);background:var(--p-amber-50, #fffbeb);border:1px solid var(--p-amber-100, #fef3c7)}.db-config-issue[data-severity=info]{color:var(--p-blue-700, #1d4ed8);background:var(--p-blue-50, #eff6ff);border:1px solid var(--p-blue-100, #dbeafe)}.db-style-presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:.5rem}.db-style-preset{display:flex;flex-direction:column;gap:.2rem;padding:.6rem .7rem;background:var(--p-surface-0, #fff);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.5rem;text-align:left;cursor:pointer;transition:all .12s ease}.db-style-preset:hover{border-color:var(--p-primary-300, #93c5fd);background:var(--p-primary-50, #eff6ff)}.db-style-preset.is-selected{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff);box-shadow:0 0 0 2px var(--p-primary-100, #dbeafe)}.db-style-preset__label{font-size:.85rem;font-weight:600;color:var(--p-text-color, #1f2937)}.db-style-preset__desc{font-size:.72rem;color:var(--p-text-muted-color, #6b7280)}.db-style-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem .75rem}.db-style-row{display:grid;grid-template-columns:1fr auto;align-items:center;gap:.5rem;font-size:.8rem;color:var(--p-text-color, #1f2937)}.db-style-row input[type=color]{width:2.5rem;height:1.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;cursor:pointer;background:transparent;padding:0}.db-style-row input[type=number]{width:4.5rem;padding:.25rem .4rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;font-size:.78rem}.db-style-row input[type=checkbox]{width:1rem;height:1rem}.db-style-select{padding:.25rem .4rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;font-size:.78rem;background:var(--p-surface-0, #fff)}.db-config-section__actions--scope{border-top:0;padding-top:0;justify-content:flex-end}.db-scope-toggle{display:inline-flex;align-items:center;gap:.4rem;padding:.3rem .55rem;font-size:.75rem;border-radius:999px;border:1px solid var(--p-surface-300, #d1d5db);background:var(--p-surface-0, #fff);color:var(--p-text-color, #1f2937);cursor:pointer}.db-scope-toggle:hover{background:var(--p-surface-100, #f3f4f6)}.db-config-advanced-editor{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.75rem;padding:.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.4rem;background:var(--p-surface-50, #f9fafb);resize:vertical}.db-config-advanced-editor__error{color:var(--p-red-600, #dc2626);font-size:.78rem;margin:0}@media(max-width:768px){.db-config-popover__header{padding:.6rem .75rem}.db-config-popover__main{padding:.75rem}.db-style-grid,.db-style-presets,.db-config-summary__row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: FilterBuilderComponent, selector: "mt-filter-builder", inputs: ["chips", "persisted"], outputs: ["chipsChange"] }, { kind: "component", type: DatasourcePanelComponent, selector: "mt-datasource-panel", inputs: ["item"], outputs: ["serviceConfigChange", "openAdvanced"] }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
29258
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ItemConfigPopoverComponent, isStandalone: true, selector: "mt-item-config-popover", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder.pass4'\">\r\n @if (item(); as currentItem) {\r\n <div class=\"db-config-popover\">\r\n <header class=\"db-config-popover__header\">\r\n <div class=\"db-config-popover__title-row\">\r\n <mt-icon\r\n [icon]=\"capability()?.icon ?? 'general.settings-02'\"\r\n class=\"db-config-popover__icon\"\r\n />\r\n <div class=\"db-config-popover__title\">\r\n <input\r\n type=\"text\"\r\n class=\"db-config-popover__title-input\"\r\n [ngModel]=\"ui()?.title?.title ?? ''\"\r\n (ngModelChange)=\"onTitleChange($event)\"\r\n [placeholder]=\"t('header.titlePlaceholder') || 'Untitled'\"\r\n />\r\n <span class=\"db-config-popover__chart-type\">\r\n {{ capability()?.name }}\r\n </span>\r\n </div>\r\n </div>\r\n <div class=\"db-config-popover__close\">\r\n <mt-button\r\n icon=\"general.x-close\"\r\n [tooltip]=\"t('header.close') || 'Close'\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n (onClick)=\"cancel()\"\r\n />\r\n </div>\r\n </header>\r\n\r\n <mt-tabs\r\n [options]=\"tabs()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [(active)]=\"activeTab\"\r\n class=\"db-config-popover__tabs\"\r\n />\r\n\r\n <main class=\"db-config-popover__main\">\r\n <!-- DATA TAB -->\r\n <section [hidden]=\"activeTab() !== 'data'\" class=\"db-config-section\">\r\n <mt-datasource-panel\r\n [item]=\"currentItem\"\r\n (serviceConfigChange)=\"onServiceConfigPatch($event)\"\r\n (openAdvanced)=\"openAdvancedEditor('dataSource')\"\r\n />\r\n\r\n @if (issuesByDomain().datasource.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().datasource; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n @if (issuesByDomain().fields.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().fields; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </section>\r\n\r\n <!-- FILTERS TAB -->\r\n <section [hidden]=\"activeTab() !== 'filters'\" class=\"db-config-section\">\r\n <mt-filter-builder\r\n [chips]=\"chips()\"\r\n [persisted]=\"currentItem.config\"\r\n (chipsChange)=\"onChipsChange($event)\"\r\n />\r\n @if (issuesByDomain().filters.length) {\r\n <ul class=\"db-config-issues\">\r\n @for (issue of issuesByDomain().filters; track issue.code) {\r\n <li\r\n class=\"db-config-issue\"\r\n [attr.data-severity]=\"issue.severity\"\r\n >\r\n <i class=\"mti mti-general.alert-circle\"></i>\r\n <span>{{ issue.message }}</span>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </section>\r\n\r\n <!-- STYLE TAB -->\r\n <section [hidden]=\"activeTab() !== 'style'\" class=\"db-config-section\">\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"style.presets\") || \"Presets\" }}\r\n </h4>\r\n <div class=\"db-style-presets\">\r\n @for (preset of presets(); track preset.key) {\r\n <button\r\n type=\"button\"\r\n class=\"db-style-preset\"\r\n [class.is-selected]=\"selectedPresetKey() === preset.key\"\r\n (click)=\"onApplyPreset(preset)\"\r\n >\r\n <span class=\"db-style-preset__label\">{{ preset.label }}</span>\r\n <span class=\"db-style-preset__desc\">{{\r\n preset.description\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"db-config-section__actions db-config-section__actions--scope\"\r\n >\r\n <button\r\n type=\"button\"\r\n class=\"db-scope-toggle\"\r\n (click)=\"toggleControlScope()\"\r\n >\r\n <i\r\n [class]=\"\r\n 'mti mti-' +\r\n (controlScope() === 'advanced'\r\n ? 'general.eye'\r\n : 'general.eye-off')\r\n \"\r\n ></i>\r\n <span>\r\n {{\r\n controlScope() === \"advanced\"\r\n ? t(\"controls.simpleMode\") || \"Show simple controls\"\r\n : t(\"controls.advancedMode\") || \"Show all controls\"\r\n }}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <mt-schema-control-renderer\r\n [schema]=\"schema()\"\r\n [persisted]=\"persistedConfig()\"\r\n [capability]=\"capability()\"\r\n [scope]=\"controlScope()\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"\r\n t('style.openLegacyDrawer') || 'Power user: open legacy drawer'\r\n \"\r\n icon=\"general.settings-02\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [outlined]=\"true\"\r\n (onClick)=\"openChartSettingsDrawer()\"\r\n />\r\n </div>\r\n </section>\r\n\r\n <!-- BEHAVIOR TAB -->\r\n <section\r\n [hidden]=\"activeTab() !== 'behavior'\"\r\n class=\"db-config-section\"\r\n >\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"behavior.title\") || \"Card behavior\" }}\r\n </h4>\r\n <label class=\"db-style-row\">\r\n <span>\r\n {{ t(\"behavior.showFiltersBar\") || \"Show per-card filter bar\" }}\r\n </span>\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"ui()?.behavior?.filtersBarVisible || false\"\r\n (change)=\"onShowFiltersBarChange($any($event.target).checked)\"\r\n />\r\n </label>\r\n <p class=\"db-config-summary__hint\">\r\n {{\r\n t(\"behavior.actionsCount\") ||\r\n ui()?.behavior?.cardActions + \" click action(s) configured\"\r\n }}\r\n ({{ ui()?.behavior?.cardActions || 0 }})\r\n </p>\r\n\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"t('behavior.openAdvanced') || 'Manage card actions'\"\r\n icon=\"general.cursor-click-02\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [outlined]=\"true\"\r\n (onClick)=\"openAdvancedEditor('actions')\"\r\n />\r\n </div>\r\n </section>\r\n\r\n <!-- ADVANCED TAB -->\r\n <section\r\n [hidden]=\"activeTab() !== 'advanced'\"\r\n class=\"db-config-section\"\r\n >\r\n <p class=\"db-config-summary__hint\">\r\n {{\r\n t(\"advanced.hint\") ||\r\n \"Edit clientConfig as JSON for fields the controls do not expose. Validated and merged. Invalid JSON is never persisted.\"\r\n }}\r\n </p>\r\n\r\n <mt-schema-control-renderer\r\n [schema]=\"schema()\"\r\n [persisted]=\"persistedConfig()\"\r\n [capability]=\"capability()\"\r\n scope=\"advanced\"\r\n (patch)=\"onSchemaPatch($event)\"\r\n />\r\n\r\n <h4 class=\"db-config-section__title\">\r\n {{ t(\"advanced.json\") || \"Raw clientConfig JSON\" }}\r\n </h4>\r\n <textarea\r\n class=\"db-config-advanced-editor\"\r\n rows=\"14\"\r\n spellcheck=\"false\"\r\n (focus)=\"initAdvancedJsonIfNeeded()\"\r\n [value]=\"advancedJsonDraft()\"\r\n (input)=\"onAdvancedJsonChange($any($event.target).value)\"\r\n ></textarea>\r\n @if (advancedJsonError()) {\r\n <p class=\"db-config-advanced-editor__error\">\r\n {{ advancedJsonError() }}\r\n </p>\r\n }\r\n <div class=\"db-config-section__actions\">\r\n <mt-button\r\n [label]=\"t('advanced.apply') || 'Apply JSON'\"\r\n icon=\"general.check\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n (onClick)=\"applyAdvancedJson()\"\r\n />\r\n </div>\r\n </section>\r\n </main>\r\n\r\n <footer class=\"db-config-popover__footer\">\r\n @if (hasErrors()) {\r\n <span\r\n class=\"db-config-popover__status db-config-popover__status--error\"\r\n >\r\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\r\n {{ t(\"footer.errors\") || \"Resolve the issues above before saving\" }}\r\n </span>\r\n } @else {\r\n <span class=\"db-config-popover__status db-config-popover__status--ok\">\r\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\r\n {{ t(\"footer.ready\") || \"Ready\" }}\r\n </span>\r\n }\r\n <mt-button\r\n [label]=\"t('footer.cancel') || 'Cancel'\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('footer.apply') || 'Apply'\"\r\n icon=\"general.check\"\r\n severity=\"primary\"\r\n [disabled]=\"hasErrors()\"\r\n (onClick)=\"apply()\"\r\n />\r\n </footer>\r\n </div>\r\n }\r\n</ng-container>\r\n", styles: [".db-config-popover{display:flex;flex-direction:column;height:100%;width:100%;background:var(--p-surface-0, #fff)}.db-config-popover__header{display:flex;align-items:flex-start;justify-content:space-between;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);gap:.75rem}.db-config-popover__title-row{display:flex;align-items:center;gap:.5rem;min-width:0;flex:1}.db-config-popover__icon{color:var(--p-primary-600, #2563eb);font-size:1.4rem}.db-config-popover__title{display:flex;flex-direction:column;gap:.15rem;min-width:0;flex:1}.db-config-popover__title-input{background:transparent;border:0;border-bottom:1px dashed transparent;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);padding:.05rem 0;width:100%;outline:none}.db-config-popover__title-input:hover{border-bottom-color:var(--p-surface-300, #d1d5db)}.db-config-popover__title-input:focus{border-bottom-color:var(--p-primary-500, #3b82f6)}.db-config-popover__chart-type{font-size:.7rem;color:var(--p-text-muted-color, #6b7280);text-transform:uppercase;letter-spacing:.05em}.db-config-popover__close{flex-shrink:0}.db-config-popover__tabs{border-bottom:1px solid var(--p-surface-200, #e5e7eb);padding:0 1rem}.db-config-popover__main{flex:1 1 0;min-height:0;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:1rem}.db-config-popover__footer{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-top:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);position:sticky;bottom:0}.db-config-popover__status{flex:1;display:inline-flex;align-items:center;gap:.4rem;font-size:.8rem}.db-config-popover__status--ok{color:var(--p-green-600, #16a34a)}.db-config-popover__status--error{color:var(--p-amber-600, #d97706)}.db-config-section{display:flex;flex-direction:column;gap:.75rem}.db-config-section__title{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--p-text-muted-color, #6b7280);margin:0}.db-config-section__actions{display:flex;justify-content:flex-end;gap:.5rem;padding-top:.5rem;border-top:1px dashed var(--p-surface-200, #e5e7eb)}.db-config-summary{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.4rem}.db-config-summary__row{display:grid;grid-template-columns:7rem 1fr;align-items:start;gap:.75rem;font-size:.8rem}.db-config-summary__key{color:var(--p-text-muted-color, #6b7280);font-weight:500}.db-config-summary__value{color:var(--p-text-color, #1f2937);word-break:break-word;display:inline-flex;flex-wrap:wrap;gap:.25rem}.db-config-summary__value--ok{color:var(--p-green-600, #16a34a);font-weight:600}.db-config-summary__value--missing{color:var(--p-amber-600, #d97706);font-weight:600}.db-config-summary__formula{background:var(--p-surface-50, #f9fafb);padding:.25rem .4rem;border-radius:.25rem;font-size:.75rem;word-break:break-all}.db-config-summary__hint{font-size:.78rem;color:var(--p-text-muted-color, #6b7280);margin:0}.db-config-chip{background:var(--p-surface-100, #f3f4f6);border:1px solid var(--p-surface-200, #e5e7eb);padding:.1rem .5rem;border-radius:999px;font-size:.75rem;color:var(--p-text-color, #1f2937)}.db-config-issues{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.25rem}.db-config-issue{display:flex;align-items:center;gap:.4rem;font-size:.78rem;padding:.4rem .55rem;border-radius:.4rem}.db-config-issue i{font-size:.85rem}.db-config-issue[data-severity=error]{color:var(--p-red-700, #b91c1c);background:var(--p-red-50, #fef2f2);border:1px solid var(--p-red-100, #fee2e2)}.db-config-issue[data-severity=warning]{color:var(--p-amber-700, #b45309);background:var(--p-amber-50, #fffbeb);border:1px solid var(--p-amber-100, #fef3c7)}.db-config-issue[data-severity=info]{color:var(--p-blue-700, #1d4ed8);background:var(--p-blue-50, #eff6ff);border:1px solid var(--p-blue-100, #dbeafe)}.db-style-presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:.5rem}.db-style-preset{display:flex;flex-direction:column;gap:.2rem;padding:.6rem .7rem;background:var(--p-surface-0, #fff);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.5rem;text-align:left;cursor:pointer;transition:all .12s ease}.db-style-preset:hover{border-color:var(--p-primary-300, #93c5fd);background:var(--p-primary-50, #eff6ff)}.db-style-preset.is-selected{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff);box-shadow:0 0 0 2px var(--p-primary-100, #dbeafe)}.db-style-preset__label{font-size:.85rem;font-weight:600;color:var(--p-text-color, #1f2937)}.db-style-preset__desc{font-size:.72rem;color:var(--p-text-muted-color, #6b7280)}.db-style-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.5rem .75rem}.db-style-row{display:grid;grid-template-columns:1fr auto;align-items:center;gap:.5rem;font-size:.8rem;color:var(--p-text-color, #1f2937)}.db-style-row input[type=color]{width:2.5rem;height:1.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;cursor:pointer;background:transparent;padding:0}.db-style-row input[type=number]{width:4.5rem;padding:.25rem .4rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;font-size:.78rem}.db-style-row input[type=checkbox]{width:1rem;height:1rem}.db-style-select{padding:.25rem .4rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.25rem;font-size:.78rem;background:var(--p-surface-0, #fff)}.db-config-section__actions--scope{border-top:0;padding-top:0;justify-content:flex-end}.db-scope-toggle{display:inline-flex;align-items:center;gap:.4rem;padding:.3rem .55rem;font-size:.75rem;border-radius:999px;border:1px solid var(--p-surface-300, #d1d5db);background:var(--p-surface-0, #fff);color:var(--p-text-color, #1f2937);cursor:pointer}.db-scope-toggle:hover{background:var(--p-surface-100, #f3f4f6)}.db-config-advanced-editor{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.75rem;padding:.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.4rem;background:var(--p-surface-50, #f9fafb);resize:vertical}.db-config-advanced-editor__error{color:var(--p-red-600, #dc2626);font-size:.78rem;margin:0}@media(max-width:768px){.db-config-popover__header{padding:.6rem .75rem}.db-config-popover__main{padding:.75rem}.db-style-grid,.db-style-presets,.db-config-summary__row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: FilterBuilderComponent, selector: "mt-filter-builder", inputs: ["chips", "persisted"], outputs: ["chipsChange"] }, { kind: "component", type: DatasourcePanelComponent, selector: "mt-datasource-panel", inputs: ["item"], outputs: ["serviceConfigChange", "openAdvanced"] }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
29259
29259
  }
29260
29260
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ItemConfigPopoverComponent, decorators: [{
29261
29261
  type: Component,
@@ -29869,7 +29869,7 @@ class GuidedConfigDialogComponent {
29869
29869
  </div>
29870
29870
  }
29871
29871
  </ng-container>
29872
- `, isInline: true, styles: [":host{display:block}.db-guided{display:flex;flex-direction:column;gap:.75rem;background:var(--p-surface-0, #fff);border-radius:.75rem;max-height:80vh}.db-guided__header{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:1rem 1.25rem .5rem}.db-guided__heading{display:flex;align-items:center;gap:.75rem}.db-guided__heading-icon{font-size:1.5rem;color:var(--p-primary-500, #2563eb)}.db-guided__title{margin:0;font-size:1rem;font-weight:700}.db-guided__subtitle{margin:0;font-size:.75rem;color:var(--p-text-muted-color, #6b7280)}.db-guided__progress{height:3px;background:var(--p-surface-100, #f3f4f6);border-radius:3px;margin:0 1.25rem;overflow:hidden}.db-guided__progress-bar{height:100%;background:var(--p-primary-500, #2563eb);transition:width .22s ease}.db-guided__stepper{padding:0 1.25rem}.db-guided__main{flex:1;overflow-y:auto;padding:1rem 1.25rem;min-height:240px}.db-guided__section{display:flex;flex-direction:column;gap:.75rem}.db-guided__section-title{margin:0;font-size:.95rem;font-weight:700}.db-guided__section-hint{margin:0;font-size:.8rem;line-height:1.45;color:var(--p-text-muted-color, #6b7280)}.db-guided__summary{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.4rem}.db-guided__summary-title{margin:.5rem 0 0;font-size:.85rem;font-weight:600}.db-guided__summary-chip--ok .p-chip{background:var(--p-green-50, #f0fdf4);border-color:var(--p-green-200, #bbf7d0);color:var(--p-green-700, #15803d)}.db-guided__summary-chip--missing .p-chip{background:var(--p-amber-50, #fffbeb);border-color:var(--p-amber-200, #fde68a);color:var(--p-amber-700, #b45309)}.db-guided__title-field{display:block;margin-top:.75rem}.db-guided__issues{list-style:none;padding:0;margin:.75rem 0 0;display:flex;flex-direction:column;gap:.4rem}.db-guided__issue{display:flex;align-items:center;gap:.4rem;padding:.5rem .75rem;font-size:.8rem;background:var(--p-amber-50, #fffbeb);border:1px solid var(--p-amber-200, #fde68a);border-radius:.5rem;color:var(--p-amber-700, #b45309)}.db-guided__issue[data-severity=error]{background:var(--p-red-50, #fef2f2);border-color:var(--p-red-200, #fecaca);color:var(--p-red-700, #b91c1c)}.db-guided__advanced-json{margin-top:1rem;background:var(--p-surface-50, #f9fafb);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.5rem;padding:.75rem}.db-guided__advanced-json summary{cursor:pointer;font-weight:600;font-size:.85rem}.db-guided__advanced-json-editor{width:100%;margin-top:.5rem;font-family:ui-monospace,SFMono-Regular,monospace;font-size:.75rem;padding:.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.4rem;background:var(--p-surface-0, #fff)}.db-guided__advanced-json-error{color:var(--p-red-600, #dc2626);font-size:.75rem;margin:.4rem 0 0}.db-guided__advanced-json-actions{display:flex;justify-content:flex-end;margin-top:.5rem}.db-guided__footer{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.75rem 1.25rem 1rem;border-top:1px solid var(--p-surface-200, #e5e7eb)}.db-guided__footer-actions{display:flex;align-items:center;gap:.5rem}.db-guided__state-chip--info .p-chip{background:var(--p-blue-50, #eff6ff);border-color:var(--p-blue-200, #bfdbfe);color:var(--p-blue-700, #1d4ed8)}.db-guided__state-chip--warn .p-chip{background:var(--p-amber-50, #fffbeb);border-color:var(--p-amber-200, #fde68a);color:var(--p-amber-700, #b45309)}.db-guided__state-chip--error .p-chip{background:var(--p-red-50, #fef2f2);border-color:var(--p-red-200, #fecaca);color:var(--p-red-700, #b91c1c)}.db-guided__state-chip--success .p-chip{background:var(--p-green-50, #f0fdf4);border-color:var(--p-green-200, #bbf7d0);color:var(--p-green-700, #15803d)}\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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Chip, selector: "mt-chip", inputs: ["label", "icon", "image", "removable", "removeIcon", "styleClass"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: FilterBuilderComponent, selector: "mt-filter-builder", inputs: ["chips", "persisted"], outputs: ["chipsChange"] }, { kind: "component", type: DatasourcePanelComponent, selector: "mt-datasource-panel", inputs: ["item"], outputs: ["serviceConfigChange", "openAdvanced"] }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
29872
+ `, isInline: true, styles: [":host{display:block}.db-guided{display:flex;flex-direction:column;gap:.75rem;background:var(--p-surface-0, #fff);border-radius:.75rem;max-height:80vh}.db-guided__header{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:1rem 1.25rem .5rem}.db-guided__heading{display:flex;align-items:center;gap:.75rem}.db-guided__heading-icon{font-size:1.5rem;color:var(--p-primary-500, #2563eb)}.db-guided__title{margin:0;font-size:1rem;font-weight:700}.db-guided__subtitle{margin:0;font-size:.75rem;color:var(--p-text-muted-color, #6b7280)}.db-guided__progress{height:3px;background:var(--p-surface-100, #f3f4f6);border-radius:3px;margin:0 1.25rem;overflow:hidden}.db-guided__progress-bar{height:100%;background:var(--p-primary-500, #2563eb);transition:width .22s ease}.db-guided__stepper{padding:0 1.25rem}.db-guided__main{flex:1;overflow-y:auto;padding:1rem 1.25rem;min-height:240px}.db-guided__section{display:flex;flex-direction:column;gap:.75rem}.db-guided__section-title{margin:0;font-size:.95rem;font-weight:700}.db-guided__section-hint{margin:0;font-size:.8rem;line-height:1.45;color:var(--p-text-muted-color, #6b7280)}.db-guided__summary{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.4rem}.db-guided__summary-title{margin:.5rem 0 0;font-size:.85rem;font-weight:600}.db-guided__summary-chip--ok .p-chip{background:var(--p-green-50, #f0fdf4);border-color:var(--p-green-200, #bbf7d0);color:var(--p-green-700, #15803d)}.db-guided__summary-chip--missing .p-chip{background:var(--p-amber-50, #fffbeb);border-color:var(--p-amber-200, #fde68a);color:var(--p-amber-700, #b45309)}.db-guided__title-field{display:block;margin-top:.75rem}.db-guided__issues{list-style:none;padding:0;margin:.75rem 0 0;display:flex;flex-direction:column;gap:.4rem}.db-guided__issue{display:flex;align-items:center;gap:.4rem;padding:.5rem .75rem;font-size:.8rem;background:var(--p-amber-50, #fffbeb);border:1px solid var(--p-amber-200, #fde68a);border-radius:.5rem;color:var(--p-amber-700, #b45309)}.db-guided__issue[data-severity=error]{background:var(--p-red-50, #fef2f2);border-color:var(--p-red-200, #fecaca);color:var(--p-red-700, #b91c1c)}.db-guided__advanced-json{margin-top:1rem;background:var(--p-surface-50, #f9fafb);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.5rem;padding:.75rem}.db-guided__advanced-json summary{cursor:pointer;font-weight:600;font-size:.85rem}.db-guided__advanced-json-editor{width:100%;margin-top:.5rem;font-family:ui-monospace,SFMono-Regular,monospace;font-size:.75rem;padding:.6rem;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.4rem;background:var(--p-surface-0, #fff)}.db-guided__advanced-json-error{color:var(--p-red-600, #dc2626);font-size:.75rem;margin:.4rem 0 0}.db-guided__advanced-json-actions{display:flex;justify-content:flex-end;margin-top:.5rem}.db-guided__footer{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.75rem 1.25rem 1rem;border-top:1px solid var(--p-surface-200, #e5e7eb)}.db-guided__footer-actions{display:flex;align-items:center;gap:.5rem}.db-guided__state-chip--info .p-chip{background:var(--p-blue-50, #eff6ff);border-color:var(--p-blue-200, #bfdbfe);color:var(--p-blue-700, #1d4ed8)}.db-guided__state-chip--warn .p-chip{background:var(--p-amber-50, #fffbeb);border-color:var(--p-amber-200, #fde68a);color:var(--p-amber-700, #b45309)}.db-guided__state-chip--error .p-chip{background:var(--p-red-50, #fef2f2);border-color:var(--p-red-200, #fecaca);color:var(--p-red-700, #b91c1c)}.db-guided__state-chip--success .p-chip{background:var(--p-green-50, #f0fdf4);border-color:var(--p-green-200, #bbf7d0);color:var(--p-green-700, #15803d)}\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: 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: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Chip, selector: "mt-chip", inputs: ["label", "icon", "image", "removable", "removeIcon", "styleClass"], outputs: ["onRemove", "onImageError"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: FilterBuilderComponent, selector: "mt-filter-builder", inputs: ["chips", "persisted"], outputs: ["chipsChange"] }, { kind: "component", type: DatasourcePanelComponent, selector: "mt-datasource-panel", inputs: ["item"], outputs: ["serviceConfigChange", "openAdvanced"] }, { kind: "component", type: SchemaControlRendererComponent, selector: "mt-schema-control-renderer", inputs: ["schema", "persisted", "capability", "scope"], outputs: ["patch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
29873
29873
  }
29874
29874
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GuidedConfigDialogComponent, decorators: [{
29875
29875
  type: Component,
@@ -30710,7 +30710,7 @@ class WidgetPaletteComponent {
30710
30710
  this.ref?.close(null);
30711
30711
  }
30712
30712
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WidgetPaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
30713
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WidgetPaletteComponent, isStandalone: true, selector: "mt-widget-palette", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n size=\"small\"\r\n fluid\r\n />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30713
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WidgetPaletteComponent, isStandalone: true, selector: "mt-widget-palette", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Content -->\r\n <div class=\"flex flex-col gap-4 p-4\" [class]=\"modal.contentClass\">\r\n <!-- Search -->\r\n <mt-text-field\r\n [placeholder]=\"t('widgetPalette.searchPlaceholder')\"\r\n [icon]=\"'general.search-lg'\"\r\n [(value)]=\"searchTerm\"\r\n />\r\n\r\n <!-- Category Tabs -->\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n size=\"small\"\r\n fluid\r\n />\r\n\r\n <!-- Widgets Grid -->\r\n <div class=\"flex-1 overflow-y-auto\">\r\n <div class=\"grid grid-cols-3 gap-3\">\r\n @for (widget of widgets(); track widget.id) {\r\n <div\r\n class=\"flex flex-col items-center justify-center gap-2 p-4 rounded-lg cursor-pointer border border-surface-200 bg-white select-none transition-all hover:border-primary-400 hover:shadow-md hover:bg-primary-50\"\r\n draggable=\"true\"\r\n (dragstart)=\"onDragStart($event, widget)\"\r\n (click)=\"onWidgetClick(widget)\"\r\n [title]=\"widget.name\"\r\n >\r\n <div\r\n class=\"w-10 h-10 flex items-center justify-center text-primary-500\"\r\n >\r\n <mt-icon [icon]=\"widget.icon\" class=\"text-2xl\" />\r\n </div>\r\n <span\r\n class=\"text-xs font-medium text-color text-center leading-tight\"\r\n >{{ widget.name }}</span\r\n >\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (widgets().length === 0) {\r\n <div class=\"p-8 text-center text-muted-color\">\r\n <mt-icon icon=\"general.search-lg\" class=\"text-3xl mb-2\" />\r\n <p>{{ t(\"widgetPalette.noResults\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Hint -->\r\n <div\r\n class=\"text-xs text-muted-color text-center py-2 border-t border-surface-200\"\r\n >\r\n {{ t(\"widgetPalette.dragHint\") }}\r\n </div>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div [class]=\"modal.footerClass\">\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { 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: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30714
30714
  }
30715
30715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WidgetPaletteComponent, decorators: [{
30716
30716
  type: Component,