@masterteam/dashboard-builder 0.0.41 → 0.0.43
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, signal, Injectable, computed, Pipe, input, ViewEncapsulation, ChangeDetectionStrategy, Component,
|
|
2
|
+
import { inject, signal, Injectable, computed, Pipe, input, ViewEncapsulation, ChangeDetectionStrategy, Component, effect, forwardRef, ViewChild, output, untracked, DestroyRef, ElementRef, NgZone, PLATFORM_ID, viewChild, ChangeDetectorRef, model, HostListener } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { CommonModule, isPlatformBrowser, DatePipe, DecimalPipe } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/forms';
|
|
@@ -19,11 +19,13 @@ import { REQUEST_CONTEXT } from '@masterteam/components';
|
|
|
19
19
|
import { TextField } from '@masterteam/components/text-field';
|
|
20
20
|
import { CheckboxField } from '@masterteam/components/checkbox-field';
|
|
21
21
|
import { ModalRef } from '@masterteam/components/dialog';
|
|
22
|
+
import { takeUntilDestroyed, rxResource } from '@angular/core/rxjs-interop';
|
|
22
23
|
import { Icon } from '@masterteam/icons';
|
|
23
24
|
import { SelectField } from '@masterteam/components/select-field';
|
|
24
25
|
import { NumberField } from '@masterteam/components/number-field';
|
|
25
|
-
import { TextareaField } from '@masterteam/components/textarea-field';
|
|
26
26
|
import { MultiSelectField } from '@masterteam/components/multi-select-field';
|
|
27
|
+
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
28
|
+
import { TextareaField } from '@masterteam/components/textarea-field';
|
|
27
29
|
import { Card } from '@masterteam/components/card';
|
|
28
30
|
import * as i2$1 from 'primeng/tooltip';
|
|
29
31
|
import { Tooltip, TooltipModule } from 'primeng/tooltip';
|
|
@@ -43,7 +45,6 @@ import { DynamicDialogRef, DynamicDialogConfig } from 'primeng/dynamicdialog';
|
|
|
43
45
|
import { DynamicDrawerConfig } from '@masterteam/components/dynamic-drawer';
|
|
44
46
|
import { ColorPickerField } from '@masterteam/components/color-picker-field';
|
|
45
47
|
import { SliderField } from '@masterteam/components/slider-field';
|
|
46
|
-
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
47
48
|
import { IconField } from '@masterteam/components/icon-field';
|
|
48
49
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
49
50
|
import { RadioCards } from '@masterteam/components/radio-cards';
|
|
@@ -55,7 +56,6 @@ import { Menu } from '@masterteam/components/menu';
|
|
|
55
56
|
import { Chip } from '@masterteam/components/chip';
|
|
56
57
|
import * as i2$3 from 'primeng/button';
|
|
57
58
|
import { ButtonModule } from 'primeng/button';
|
|
58
|
-
import { rxResource } from '@angular/core/rxjs-interop';
|
|
59
59
|
import { Table } from '@masterteam/components/table';
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -903,6 +903,9 @@ function createDefaultFilterField() {
|
|
|
903
903
|
selection: [
|
|
904
904
|
{
|
|
905
905
|
id: 1,
|
|
906
|
+
service: 'pplus',
|
|
907
|
+
selector: null,
|
|
908
|
+
selectorName: null,
|
|
906
909
|
moduleType: undefined,
|
|
907
910
|
moduleId: undefined,
|
|
908
911
|
filters: [],
|
|
@@ -918,218 +921,6 @@ function createDefaultFilterField() {
|
|
|
918
921
|
};
|
|
919
922
|
}
|
|
920
923
|
|
|
921
|
-
/**
|
|
922
|
-
* Dynamic Filters Config Component
|
|
923
|
-
*
|
|
924
|
-
* Manages dynamic filter field configurations for dashboard pages.
|
|
925
|
-
* Supports multiple filter types including dropdowns, lookups, status,
|
|
926
|
-
* phase gates, dates, and more.
|
|
927
|
-
*/
|
|
928
|
-
class DynamicFiltersConfig {
|
|
929
|
-
/** Available lookups from parent context */
|
|
930
|
-
lookups = input([], ...(ngDevMode ? [{ debugName: "lookups" }] : /* istanbul ignore next */ []));
|
|
931
|
-
/** Available level schemas from parent context */
|
|
932
|
-
levelsSchema = input([], ...(ngDevMode ? [{ debugName: "levelsSchema" }] : /* istanbul ignore next */ []));
|
|
933
|
-
/** Available level logs from parent context */
|
|
934
|
-
levelLogs = input([], ...(ngDevMode ? [{ debugName: "levelLogs" }] : /* istanbul ignore next */ []));
|
|
935
|
-
/** Product type to filter available field types */
|
|
936
|
-
productType = input('pplus', ...(ngDevMode ? [{ debugName: "productType" }] : /* istanbul ignore next */ []));
|
|
937
|
-
/** Emit when level logs need to be loaded for a specific schema level */
|
|
938
|
-
loadLevelLogs = output();
|
|
939
|
-
/** Filter fields data */
|
|
940
|
-
filterFields = signal([], ...(ngDevMode ? [{ debugName: "filterFields" }] : /* istanbul ignore next */ []));
|
|
941
|
-
/** Paste configuration state */
|
|
942
|
-
showPasteArea = signal(false, ...(ngDevMode ? [{ debugName: "showPasteArea" }] : /* istanbul ignore next */ []));
|
|
943
|
-
pasteContent = signal('', ...(ngDevMode ? [{ debugName: "pasteContent" }] : /* istanbul ignore next */ []));
|
|
944
|
-
pasteError = signal('', ...(ngDevMode ? [{ debugName: "pasteError" }] : /* istanbul ignore next */ []));
|
|
945
|
-
/** Disabled state */
|
|
946
|
-
disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
947
|
-
/** Available field types filtered by product */
|
|
948
|
-
availableFieldTypes = computed(() => {
|
|
949
|
-
const product = this.productType();
|
|
950
|
-
return FILTER_FIELD_TYPES.filter((type) => type.products.includes(product));
|
|
951
|
-
}, ...(ngDevMode ? [{ debugName: "availableFieldTypes" }] : /* istanbul ignore next */ []));
|
|
952
|
-
// ControlValueAccessor callbacks
|
|
953
|
-
onChange = () => { };
|
|
954
|
-
onTouched = () => { };
|
|
955
|
-
// ============================================
|
|
956
|
-
// ControlValueAccessor Implementation
|
|
957
|
-
// ============================================
|
|
958
|
-
writeValue(value) {
|
|
959
|
-
if (value) {
|
|
960
|
-
this.filterFields.set([...value]);
|
|
961
|
-
}
|
|
962
|
-
else {
|
|
963
|
-
this.filterFields.set([]);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
registerOnChange(fn) {
|
|
967
|
-
this.onChange = fn;
|
|
968
|
-
}
|
|
969
|
-
registerOnTouched(fn) {
|
|
970
|
-
this.onTouched = fn;
|
|
971
|
-
}
|
|
972
|
-
setDisabledState(isDisabled) {
|
|
973
|
-
this.disabled.set(isDisabled);
|
|
974
|
-
}
|
|
975
|
-
// ============================================
|
|
976
|
-
// Filter Field Management
|
|
977
|
-
// ============================================
|
|
978
|
-
/** Add a new filter field */
|
|
979
|
-
addFilterField() {
|
|
980
|
-
const newField = createDefaultFilterField();
|
|
981
|
-
this.filterFields.update((fields) => [...fields, newField]);
|
|
982
|
-
this.notifyChange();
|
|
983
|
-
}
|
|
984
|
-
/** Remove a filter field by index */
|
|
985
|
-
removeFilterField(index) {
|
|
986
|
-
this.filterFields.update((fields) => {
|
|
987
|
-
const newFields = [...fields];
|
|
988
|
-
newFields.splice(index, 1);
|
|
989
|
-
return newFields;
|
|
990
|
-
});
|
|
991
|
-
this.notifyChange();
|
|
992
|
-
}
|
|
993
|
-
/** Update a filter field property */
|
|
994
|
-
updateField(index, key, value) {
|
|
995
|
-
this.filterFields.update((fields) => {
|
|
996
|
-
const newFields = [...fields];
|
|
997
|
-
newFields[index] = { ...newFields[index], [key]: value };
|
|
998
|
-
return newFields;
|
|
999
|
-
});
|
|
1000
|
-
this.notifyChange();
|
|
1001
|
-
}
|
|
1002
|
-
/** Update filter field name */
|
|
1003
|
-
updateFieldName(index, lang, value) {
|
|
1004
|
-
this.filterFields.update((fields) => {
|
|
1005
|
-
const newFields = [...fields];
|
|
1006
|
-
const field = newFields[index];
|
|
1007
|
-
field.name = { ...field.name, [lang]: value };
|
|
1008
|
-
return newFields;
|
|
1009
|
-
});
|
|
1010
|
-
this.notifyChange();
|
|
1011
|
-
}
|
|
1012
|
-
/** Update filter field configuration */
|
|
1013
|
-
updateFieldConfig(index, key, value) {
|
|
1014
|
-
this.filterFields.update((fields) => {
|
|
1015
|
-
const newFields = [...fields];
|
|
1016
|
-
const field = newFields[index];
|
|
1017
|
-
field.configuration = { ...field.configuration, [key]: value };
|
|
1018
|
-
return newFields;
|
|
1019
|
-
});
|
|
1020
|
-
this.notifyChange();
|
|
1021
|
-
}
|
|
1022
|
-
/** Handle field type change */
|
|
1023
|
-
onFieldTypeChange(index, type) {
|
|
1024
|
-
this.filterFields.update((fields) => {
|
|
1025
|
-
const newFields = [...fields];
|
|
1026
|
-
newFields[index] = { ...newFields[index], type };
|
|
1027
|
-
// Reset configuration based on type
|
|
1028
|
-
if (type === 'section' || type === 'separator') {
|
|
1029
|
-
newFields[index].configuration = {};
|
|
1030
|
-
}
|
|
1031
|
-
return newFields;
|
|
1032
|
-
});
|
|
1033
|
-
this.notifyChange();
|
|
1034
|
-
}
|
|
1035
|
-
/** Handle schema level change for status/phaseGate */
|
|
1036
|
-
onSchemaLevelChange(index, schemaLevelId) {
|
|
1037
|
-
this.updateFieldConfig(index, 'schemaLevelId', schemaLevelId);
|
|
1038
|
-
// Clear log ID and emit event to load level logs
|
|
1039
|
-
this.updateFieldConfig(index, 'logId', null);
|
|
1040
|
-
if (schemaLevelId) {
|
|
1041
|
-
this.loadLevelLogs.emit(schemaLevelId);
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
// ============================================
|
|
1045
|
-
// Copy/Paste Configuration
|
|
1046
|
-
// ============================================
|
|
1047
|
-
/** Copy current configuration to clipboard */
|
|
1048
|
-
copyConfiguration() {
|
|
1049
|
-
try {
|
|
1050
|
-
const config = JSON.stringify(this.filterFields(), null, 2);
|
|
1051
|
-
navigator.clipboard.writeText(config);
|
|
1052
|
-
}
|
|
1053
|
-
catch (error) {
|
|
1054
|
-
console.error('Error copying configuration:', error);
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
/** Toggle paste area visibility */
|
|
1058
|
-
togglePasteArea() {
|
|
1059
|
-
this.showPasteArea.update((v) => !v);
|
|
1060
|
-
this.pasteContent.set('');
|
|
1061
|
-
this.pasteError.set('');
|
|
1062
|
-
}
|
|
1063
|
-
/** Apply pasted configuration */
|
|
1064
|
-
applyPastedConfiguration() {
|
|
1065
|
-
try {
|
|
1066
|
-
const parsedConfig = JSON.parse(this.pasteContent());
|
|
1067
|
-
if (!Array.isArray(parsedConfig)) {
|
|
1068
|
-
throw new Error('Configuration must be an array');
|
|
1069
|
-
}
|
|
1070
|
-
// Validate each field
|
|
1071
|
-
parsedConfig.forEach((field) => {
|
|
1072
|
-
if (!field.type) {
|
|
1073
|
-
throw new Error('Each field must have a type');
|
|
1074
|
-
}
|
|
1075
|
-
if (field.type !== 'separator' &&
|
|
1076
|
-
(!field.name || !field.name.en || !field.name.ar)) {
|
|
1077
|
-
throw new Error('Each field (except separator) must have name with en and ar properties');
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
this.filterFields.set(parsedConfig);
|
|
1081
|
-
this.notifyChange();
|
|
1082
|
-
this.showPasteArea.set(false);
|
|
1083
|
-
this.pasteContent.set('');
|
|
1084
|
-
this.pasteError.set('');
|
|
1085
|
-
}
|
|
1086
|
-
catch (error) {
|
|
1087
|
-
this.pasteError.set(`Invalid configuration: ${error.message}`);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
// ============================================
|
|
1091
|
-
// Helpers
|
|
1092
|
-
// ============================================
|
|
1093
|
-
/** Track by function for ngFor */
|
|
1094
|
-
trackByIndex(index) {
|
|
1095
|
-
return index;
|
|
1096
|
-
}
|
|
1097
|
-
/** Notify parent of changes */
|
|
1098
|
-
notifyChange() {
|
|
1099
|
-
this.onChange(this.filterFields());
|
|
1100
|
-
this.onTouched();
|
|
1101
|
-
}
|
|
1102
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicFiltersConfig, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1103
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DynamicFiltersConfig, isStandalone: true, selector: "mt-dynamic-filters-config", inputs: { lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, levelsSchema: { classPropertyName: "levelsSchema", publicName: "levelsSchema", isSignal: true, isRequired: false, transformFunction: null }, levelLogs: { classPropertyName: "levelLogs", publicName: "levelLogs", isSignal: true, isRequired: false, transformFunction: null }, productType: { classPropertyName: "productType", publicName: "productType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadLevelLogs: "loadLevelLogs" }, providers: [
|
|
1104
|
-
{
|
|
1105
|
-
provide: NG_VALUE_ACCESSOR,
|
|
1106
|
-
useExisting: forwardRef(() => DynamicFiltersConfig),
|
|
1107
|
-
multi: true,
|
|
1108
|
-
},
|
|
1109
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <!-- Header Actions -->\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-lg font-semibold\">{{ t(\"filterFieldsConfiguration\") }}</h3>\n <div class=\"flex gap-2\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n <mt-button\n icon=\"general.copy-06\"\n [pTooltip]=\"t('copyConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"copyConfiguration()\"\n />\n <mt-button\n icon=\"general.clipboard\"\n [pTooltip]=\"t('pasteConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"togglePasteArea()\"\n />\n </div>\n </div>\n\n <!-- Paste Area -->\n @if (showPasteArea()) {\n <div\n class=\"flex flex-col gap-2 p-3 bg-surface-100 rounded-lg border border-surface-300\"\n >\n <mt-textarea-field\n [label]=\"t('pasteConfigurationHere')\"\n [rows]=\"8\"\n [ngModel]=\"pasteContent()\"\n (ngModelChange)=\"pasteContent.set($event)\"\n [placeholder]=\"t('pasteJsonConfiguration')\"\n />\n @if (pasteError()) {\n <div class=\"text-red-500 text-sm\">{{ pasteError() }}</div>\n }\n <div class=\"flex justify-end gap-2\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('applyConfiguration')\"\n size=\"small\"\n (onClick)=\"applyPastedConfiguration()\"\n />\n </div>\n </div>\n }\n\n <!-- Filter Fields List -->\n <div class=\"flex flex-col gap-4\">\n @for (field of filterFields(); track trackByIndex($index); let i = $index) {\n <div\n class=\"relative p-4 bg-surface-50 border border-surface-200 rounded-lg\"\n >\n <!-- Remove Button -->\n <mt-button\n class=\"!absolute top-2 end-2\"\n icon=\"general.trash-01\"\n severity=\"danger\"\n size=\"small\"\n [rounded]=\"true\"\n [text]=\"true\"\n (onClick)=\"removeFilterField(i)\"\n [disabled]=\"disabled()\"\n />\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 pe-8\">\n <!-- Field Type -->\n <mt-select-field\n [label]=\"t('fieldType')\"\n [options]=\"availableFieldTypes()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"field.type\"\n (ngModelChange)=\"onFieldTypeChange(i, $event)\"\n />\n\n <!-- Key (not for section/separator) -->\n @if (field.type !== \"section\" && field.type !== \"separator\") {\n <mt-text-field\n [label]=\"t('fieldKey')\"\n [placeholder]=\"t('enterFieldKey')\"\n [ngModel]=\"field.key\"\n (ngModelChange)=\"updateField(i, 'key', $event)\"\n />\n }\n\n <!-- Name fields (not for separator) -->\n @if (field.type !== \"separator\") {\n <mt-text-field\n [label]=\"t('nameEnglish')\"\n [placeholder]=\"t('enterEnglishName')\"\n [ngModel]=\"field.name?.en\"\n (ngModelChange)=\"updateFieldName(i, 'en', $event)\"\n />\n <mt-text-field\n [label]=\"t('nameArabic')\"\n [placeholder]=\"t('enterArabicName')\"\n [ngModel]=\"field.name?.ar\"\n (ngModelChange)=\"updateFieldName(i, 'ar', $event)\"\n />\n }\n\n <!-- Configuration: Lookup -->\n @if (field.type === \"lookup\") {\n <mt-select-field\n [label]=\"t('lookupId')\"\n [options]=\"lookups()\"\n optionValue=\"id\"\n optionLabel=\"displayName\"\n [ngModel]=\"field.configuration?.lookupId\"\n (ngModelChange)=\"updateFieldConfig(i, 'lookupId', $event)\"\n />\n }\n\n <!-- Configuration: Status or Phase Gate -->\n @if (field.type === \"status\" || field.type === \"phaseGate\") {\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n }\n\n <!-- Configuration: Status Log ID -->\n @if (field.type === \"status\" && field.configuration?.schemaLevelId) {\n <mt-select-field\n [label]=\"t('logId')\"\n [options]=\"levelLogs()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [ngModel]=\"field.configuration?.logId\"\n (ngModelChange)=\"updateFieldConfig(i, 'logId', $event)\"\n />\n }\n\n <!-- Configuration: Checkbox -->\n @if (field.type === \"checkbox\") {\n <mt-checkbox-field\n [label]=\"t('defaultChecked')\"\n [ngModel]=\"field.configuration?.checked\"\n (ngModelChange)=\"updateFieldConfig(i, 'checked', $event)\"\n />\n }\n\n <!-- Configuration: Year -->\n @if (field.type === \"year\") {\n <mt-number-field\n [label]=\"t('minYear')\"\n [placeholder]=\"t('minYear')\"\n [ngModel]=\"field.configuration?.minYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'minYear', $event)\"\n />\n <mt-number-field\n [label]=\"t('maxYear')\"\n [placeholder]=\"t('maxYear')\"\n [ngModel]=\"field.configuration?.maxYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'maxYear', $event)\"\n />\n }\n\n <!-- Is Required Checkbox -->\n <mt-checkbox-field\n [label]=\"t('isRequired')\"\n [ngModel]=\"field.configuration?.isRequird\"\n (ngModelChange)=\"updateFieldConfig(i, 'isRequird', $event)\"\n />\n\n <!-- Is Multiple Checkbox (not for section, separator, user, date, year) -->\n @if (\n field.type !== \"section\" &&\n field.type !== \"separator\" &&\n field.type !== \"user\" &&\n field.type !== \"date\" &&\n field.type !== \"year\"\n ) {\n <mt-checkbox-field\n [label]=\"t('isMultiple')\"\n [ngModel]=\"field.configuration?.isMultiple\"\n (ngModelChange)=\"updateFieldConfig(i, 'isMultiple', $event)\"\n />\n }\n </div>\n </div>\n } @empty {\n <div class=\"text-center py-8 text-muted-color\">\n <mt-icon icon=\"general.filter-lines\" class=\"text-4xl mb-2\" />\n <p>{{ t(\"noFilterFieldsConfigured\") }}</p>\n <p class=\"text-sm\">{{ t(\"clickAddFieldToStart\") }}</p>\n </div>\n }\n </div>\n</div>\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: Icon, selector: "mt-icon", inputs: ["icon"] }, { 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { 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: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1110
|
-
}
|
|
1111
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicFiltersConfig, decorators: [{
|
|
1112
|
-
type: Component,
|
|
1113
|
-
args: [{ selector: 'mt-dynamic-filters-config', standalone: true, imports: [
|
|
1114
|
-
CommonModule,
|
|
1115
|
-
FormsModule,
|
|
1116
|
-
TranslocoDirective,
|
|
1117
|
-
Button,
|
|
1118
|
-
Icon,
|
|
1119
|
-
SelectField,
|
|
1120
|
-
TextField,
|
|
1121
|
-
NumberField,
|
|
1122
|
-
CheckboxField,
|
|
1123
|
-
TextareaField,
|
|
1124
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
1125
|
-
{
|
|
1126
|
-
provide: NG_VALUE_ACCESSOR,
|
|
1127
|
-
useExisting: forwardRef(() => DynamicFiltersConfig),
|
|
1128
|
-
multi: true,
|
|
1129
|
-
},
|
|
1130
|
-
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <!-- Header Actions -->\n <div class=\"flex items-center justify-between\">\n <h3 class=\"text-lg font-semibold\">{{ t(\"filterFieldsConfiguration\") }}</h3>\n <div class=\"flex gap-2\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n <mt-button\n icon=\"general.copy-06\"\n [pTooltip]=\"t('copyConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"copyConfiguration()\"\n />\n <mt-button\n icon=\"general.clipboard\"\n [pTooltip]=\"t('pasteConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"togglePasteArea()\"\n />\n </div>\n </div>\n\n <!-- Paste Area -->\n @if (showPasteArea()) {\n <div\n class=\"flex flex-col gap-2 p-3 bg-surface-100 rounded-lg border border-surface-300\"\n >\n <mt-textarea-field\n [label]=\"t('pasteConfigurationHere')\"\n [rows]=\"8\"\n [ngModel]=\"pasteContent()\"\n (ngModelChange)=\"pasteContent.set($event)\"\n [placeholder]=\"t('pasteJsonConfiguration')\"\n />\n @if (pasteError()) {\n <div class=\"text-red-500 text-sm\">{{ pasteError() }}</div>\n }\n <div class=\"flex justify-end gap-2\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('applyConfiguration')\"\n size=\"small\"\n (onClick)=\"applyPastedConfiguration()\"\n />\n </div>\n </div>\n }\n\n <!-- Filter Fields List -->\n <div class=\"flex flex-col gap-4\">\n @for (field of filterFields(); track trackByIndex($index); let i = $index) {\n <div\n class=\"relative p-4 bg-surface-50 border border-surface-200 rounded-lg\"\n >\n <!-- Remove Button -->\n <mt-button\n class=\"!absolute top-2 end-2\"\n icon=\"general.trash-01\"\n severity=\"danger\"\n size=\"small\"\n [rounded]=\"true\"\n [text]=\"true\"\n (onClick)=\"removeFilterField(i)\"\n [disabled]=\"disabled()\"\n />\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 pe-8\">\n <!-- Field Type -->\n <mt-select-field\n [label]=\"t('fieldType')\"\n [options]=\"availableFieldTypes()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"field.type\"\n (ngModelChange)=\"onFieldTypeChange(i, $event)\"\n />\n\n <!-- Key (not for section/separator) -->\n @if (field.type !== \"section\" && field.type !== \"separator\") {\n <mt-text-field\n [label]=\"t('fieldKey')\"\n [placeholder]=\"t('enterFieldKey')\"\n [ngModel]=\"field.key\"\n (ngModelChange)=\"updateField(i, 'key', $event)\"\n />\n }\n\n <!-- Name fields (not for separator) -->\n @if (field.type !== \"separator\") {\n <mt-text-field\n [label]=\"t('nameEnglish')\"\n [placeholder]=\"t('enterEnglishName')\"\n [ngModel]=\"field.name?.en\"\n (ngModelChange)=\"updateFieldName(i, 'en', $event)\"\n />\n <mt-text-field\n [label]=\"t('nameArabic')\"\n [placeholder]=\"t('enterArabicName')\"\n [ngModel]=\"field.name?.ar\"\n (ngModelChange)=\"updateFieldName(i, 'ar', $event)\"\n />\n }\n\n <!-- Configuration: Lookup -->\n @if (field.type === \"lookup\") {\n <mt-select-field\n [label]=\"t('lookupId')\"\n [options]=\"lookups()\"\n optionValue=\"id\"\n optionLabel=\"displayName\"\n [ngModel]=\"field.configuration?.lookupId\"\n (ngModelChange)=\"updateFieldConfig(i, 'lookupId', $event)\"\n />\n }\n\n <!-- Configuration: Status or Phase Gate -->\n @if (field.type === \"status\" || field.type === \"phaseGate\") {\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n }\n\n <!-- Configuration: Status Log ID -->\n @if (field.type === \"status\" && field.configuration?.schemaLevelId) {\n <mt-select-field\n [label]=\"t('logId')\"\n [options]=\"levelLogs()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [ngModel]=\"field.configuration?.logId\"\n (ngModelChange)=\"updateFieldConfig(i, 'logId', $event)\"\n />\n }\n\n <!-- Configuration: Checkbox -->\n @if (field.type === \"checkbox\") {\n <mt-checkbox-field\n [label]=\"t('defaultChecked')\"\n [ngModel]=\"field.configuration?.checked\"\n (ngModelChange)=\"updateFieldConfig(i, 'checked', $event)\"\n />\n }\n\n <!-- Configuration: Year -->\n @if (field.type === \"year\") {\n <mt-number-field\n [label]=\"t('minYear')\"\n [placeholder]=\"t('minYear')\"\n [ngModel]=\"field.configuration?.minYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'minYear', $event)\"\n />\n <mt-number-field\n [label]=\"t('maxYear')\"\n [placeholder]=\"t('maxYear')\"\n [ngModel]=\"field.configuration?.maxYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'maxYear', $event)\"\n />\n }\n\n <!-- Is Required Checkbox -->\n <mt-checkbox-field\n [label]=\"t('isRequired')\"\n [ngModel]=\"field.configuration?.isRequird\"\n (ngModelChange)=\"updateFieldConfig(i, 'isRequird', $event)\"\n />\n\n <!-- Is Multiple Checkbox (not for section, separator, user, date, year) -->\n @if (\n field.type !== \"section\" &&\n field.type !== \"separator\" &&\n field.type !== \"user\" &&\n field.type !== \"date\" &&\n field.type !== \"year\"\n ) {\n <mt-checkbox-field\n [label]=\"t('isMultiple')\"\n [ngModel]=\"field.configuration?.isMultiple\"\n (ngModelChange)=\"updateFieldConfig(i, 'isMultiple', $event)\"\n />\n }\n </div>\n </div>\n } @empty {\n <div class=\"text-center py-8 text-muted-color\">\n <mt-icon icon=\"general.filter-lines\" class=\"text-4xl mb-2\" />\n <p>{{ t(\"noFilterFieldsConfigured\") }}</p>\n <p class=\"text-sm\">{{ t(\"clickAddFieldToStart\") }}</p>\n </div>\n }\n </div>\n</div>\n" }]
|
|
1131
|
-
}], propDecorators: { lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], levelsSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelsSchema", required: false }] }], levelLogs: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelLogs", required: false }] }], productType: [{ type: i0.Input, args: [{ isSignal: true, alias: "productType", required: false }] }], loadLevelLogs: [{ type: i0.Output, args: ["loadLevelLogs"] }] } });
|
|
1132
|
-
|
|
1133
924
|
const TITLE_SHARED = ['titleAr', 'titleEn'];
|
|
1134
925
|
const HEADER_BLOCK = ['centerHeader', 'advancedHeaderConfig', 'borderTop'];
|
|
1135
926
|
const CHART_CAPABILITIES = [
|
|
@@ -3752,7 +3543,7 @@ class SelectionConfiguration {
|
|
|
3752
3543
|
useExisting: forwardRef(() => SelectionConfiguration),
|
|
3753
3544
|
multi: true,
|
|
3754
3545
|
},
|
|
3755
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties", "readonly"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3546
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectModule')\"\n [filter]=\"true\"\n [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\"\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\n />\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: FilterValueField, selector: "mt-filter-value-field", inputs: ["label", "placeholder", "extraProperties", "readonly"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3756
3547
|
}
|
|
3757
3548
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SelectionConfiguration, decorators: [{
|
|
3758
3549
|
type: Component,
|
|
@@ -3781,75 +3572,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3781
3572
|
useExisting: forwardRef(() => SelectionConfiguration),
|
|
3782
3573
|
multi: true,
|
|
3783
3574
|
},
|
|
3784
|
-
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectModule')\"\r\n [filter]=\"true\"\r\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\r\n />\r\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n" }]
|
|
3575
|
+
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <mt-card [title]=\"t('selections')\">\r\n <ng-template #cardEnd>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n (onClick)=\"addSelection()\"\r\n [disabled]=\"disabled || loadingTree()\"\r\n [pTooltip]=\"t('addSelection')\"\r\n />\r\n }\r\n </ng-template>\r\n\r\n <!-- Loading Skeleton State - Show for entire component while tree is loading -->\r\n @if (loadingTree()) {\r\n <div class=\"flex flex-col gap-4\">\r\n <!-- Skeleton Selection Card -->\r\n <div class=\"p-4 rounded-lg border border-surface-200\">\r\n <!-- Skeleton Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton shape=\"circle\" width=\"24px\" height=\"24px\" />\r\n <p-skeleton width=\"80px\" height=\"16px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Module Selection -->\r\n <div class=\"grid grid-cols-1 gap-4 mb-4\">\r\n <div class=\"flex flex-col gap-2\">\r\n <p-skeleton width=\"60px\" height=\"14px\" />\r\n <p-skeleton width=\"100%\" height=\"40px\" borderRadius=\"8px\" />\r\n </div>\r\n </div>\r\n <!-- Skeleton Filters Section -->\r\n <div class=\"border border-surface-200 rounded-lg p-4\">\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <p-skeleton width=\"50px\" height=\"14px\" />\r\n <div class=\"flex gap-1\">\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n <p-skeleton shape=\"circle\" width=\"28px\" height=\"28px\" />\r\n </div>\r\n </div>\r\n <div class=\"text-center py-4\">\r\n <p-skeleton width=\"150px\" height=\"14px\" styleClass=\"mx-auto\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4\" [formGroup]=\"selectionsForm\">\r\n <div formArrayName=\"selections\">\r\n @for (\r\n selection of selectionsArray.controls;\r\n track trackBySelectionId($index, selection);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"p-4 rounded-lg border transition-all mb-4 last:mb-0\"\r\n [class.border-red-500]=\"selection.invalid\"\r\n [class.border-surface-200]=\"!selection.invalid\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Selection Header -->\r\n <div class=\"flex items-center justify-between mb-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full text-sm font-semibold\"\r\n [class.bg-primary-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.text-primary-600]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-100]=\"isFixedSelection(selection.value.id)\"\r\n [class.text-amber-600]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n >\r\n @if (isFixedSelection(selection.value.id)) {\r\n <i class=\"mti mti-lock-01 text-xs\"></i>\r\n } @else {\r\n {{ selection.value.id }}\r\n }\r\n </span>\r\n <span class=\"text-sm font-medium text-muted-color\">\r\n @if (isFixedSelection(selection.value.id)) {\r\n {{ t(\"fixedSelection\") }}\r\n } @else {\r\n {{ t(\"selection\") }}\r\n }\r\n </span>\r\n </div>\r\n @if (\r\n selectionsArray.length > 1 &&\r\n !isSelectionStructureLocked(selection.value.id)\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeSelection(i)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Service & Module Selection -->\r\n <div\r\n class=\"grid grid-cols-1 gap-4 mb-4\"\r\n [class.md:grid-cols-2]=\"!hasSingleService()\"\r\n >\r\n <!-- Service (hidden when only one service) -->\r\n @if (!hasSingleService()) {\r\n <mt-select-field\r\n [label]=\"t('service')\"\r\n formControlName=\"service\"\r\n [options]=\"services()\"\r\n optionLabel=\"name\"\r\n optionValue=\"name\"\r\n [placeholder]=\"t('selectService')\"\r\n [loading]=\"loadingTree()\"\r\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\r\n (ngModelChange)=\"onServiceChange(i, $event)\"\r\n />\r\n }\r\n\r\n <!-- Module values (grouped by module type, multi-select within one type) -->\r\n <mt-multi-select-field\r\n [label]=\"t('module')\"\r\n [ngModel]=\"getSelectorValues(i)\"\r\n [ngModelOptions]=\"{ standalone: true }\"\r\n [options]=\"getGroupedModulesForSelection(i)\"\r\n [group]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"selector\"\r\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectModule')\"\n [filter]=\"true\"\n [virtualScroll]=\"true\"\n [virtualScrollItemSize]=\"38\"\n [showClear]=\"!isSelectionStructureLocked(selection.value.id)\"\n [readonly]=\"isSelectionStructureLocked(selection.value.id)\"\n (ngModelChange)=\"onModuleSelectionChange(i, $event)\"\n />\n </div>\r\n @if (\r\n selection.get(\"selector\")?.invalid &&\r\n selection.get(\"selector\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block mb-2\">{{\r\n t(\"moduleRequired\")\r\n }}</small>\r\n }\r\n\r\n <!-- Filters Section -->\r\n <div\r\n class=\"border border-surface-200 rounded-lg p-4\"\r\n [class.border-red-500]=\"getFilters(selection).invalid\"\r\n [class.border-amber-200]=\"isFixedSelection(selection.value.id)\"\r\n [class.bg-amber-50]=\"isFixedSelection(selection.value.id)\"\r\n >\r\n <div class=\"flex items-center justify-between mb-3\">\r\n <span class=\"text-sm font-medium\">{{ t(\"filters\") }}</span>\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"\r\n disabled || getFilters(selection).length === 0\r\n \"\r\n (onClick)=\"copyFilters(i)\"\r\n [pTooltip]=\"t('copyFilters')\"\r\n />\r\n <mt-button\r\n icon=\"file.clipboard\"\r\n severity=\"help\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"togglePaste(i)\"\r\n [pTooltip]=\"t('pasteFilters')\"\r\n />\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addFilter(i)\"\r\n [pTooltip]=\"t('addFilter')\"\r\n />\r\n </div>\r\n } @else {\r\n <span class=\"text-xs text-amber-600 font-medium\">\r\n <i class=\"mti mti-lock-01 mr-1\"></i>\r\n {{ t(\"readOnly\") }}\r\n </span>\r\n }\r\n </div>\r\n\r\n <!-- Paste JSON Area -->\r\n @if (selection.value.showPaste) {\r\n <div\r\n class=\"mb-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteFiltersJson')\"\r\n formControlName=\"filterJson\"\r\n [placeholder]=\"t('pasteFiltersJsonPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (selection.value.pasteError) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n selection.value.pasteError\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-2\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"togglePaste(i)\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPastedFilters(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Filters List -->\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\r\n @for (\r\n filter of getFilters(selection).controls;\r\n track trackByFilterIndex(j);\r\n let j = $index\r\n ) {\r\n <div\r\n class=\"flex flex-col gap-3 p-3 rounded-lg border\"\r\n [class.bg-surface-50]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.border-surface-100]=\"\r\n !isFixedSelection(selection.value.id)\r\n \"\r\n [class.bg-amber-25]=\"isFixedSelection(selection.value.id)\"\r\n [class.border-amber-100]=\"\r\n isFixedSelection(selection.value.id)\r\n \"\r\n [formGroupName]=\"j\"\r\n >\r\n <!-- Row 1: Property, Operation, Logical -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"t('property')\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"getPropertiesForSelection(i)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n (onChange)=\"onFilterPropertyChange(i, j, $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Operation -->\r\n <div class=\"col-span-3\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n formControlName=\"operation\"\r\n [options]=\"operations\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Logical Operator -->\r\n <div class=\"col-span-2\">\r\n <mt-select-field\r\n [label]=\"t('logical')\"\r\n formControlName=\"logical\"\r\n [options]=\"logicals\"\r\n optionLabel=\"name\"\r\n optionValue=\"value\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n\r\n <!-- Remove Filter (hidden for fixed selections) -->\r\n @if (!isFixedSelection(selection.value.id)) {\r\n <div class=\"col-span-2 flex items-end justify-end\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeFilter(i, j)\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"col-span-2\"></div>\r\n }\r\n </div>\r\n\r\n <!-- Row 2: Value, Level -->\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n <!-- Value -->\r\n <div class=\"col-span-10\">\r\n @if (shouldShowPropertyItems(i, j)) {\r\n <mt-select-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [options]=\"getPropertyItemsForFilter(i, j)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n } @else {\r\n <mt-filter-value-field\r\n [label]=\"t('value')\"\r\n formControlName=\"propertyValue\"\r\n [placeholder]=\"t('enterValue')\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n }\r\n </div>\r\n\r\n <!-- Operation Level -->\r\n <div class=\"col-span-2\">\r\n <mt-number-field\r\n [label]=\"t('level')\"\r\n formControlName=\"operationLevel\"\r\n [min]=\"1\"\r\n [max]=\"10\"\r\n [readonly]=\"isFixedSelection(selection.value.id)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (getFilters(selection).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noFiltersConfigured\") }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (selectionsArray.length === 0 && !loadingTree()) {\r\n <div class=\"text-center py-8 text-muted-color\">\r\n <i class=\"mti mti-database text-3xl mb-2 block\"></i>\r\n <p class=\"mb-2\">{{ t(\"noSelectionsConfigured\") }}</p>\r\n @if (!structureLocked()) {\r\n <mt-button\r\n icon=\"general.plus\"\r\n [label]=\"t('addSelection')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"addSelection()\"\r\n />\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n</div>\r\n" }]
|
|
3785
3576
|
}], ctorParameters: () => [], propDecorators: { structureLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "structureLocked", required: false }] }], workspaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "workspaceId", required: false }] }], modulesProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "modulesProperties", required: false }] }], propertiesFlat: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertiesFlat", required: false }] }], moduleChange: [{ type: i0.Output, args: ["moduleChange"] }] } });
|
|
3786
3577
|
|
|
3787
3578
|
/**
|
|
3788
|
-
*
|
|
3579
|
+
* Dynamic Filters Config Component
|
|
3789
3580
|
*
|
|
3790
|
-
* Manages
|
|
3791
|
-
*
|
|
3581
|
+
* Manages dynamic filter field configurations for dashboard pages.
|
|
3582
|
+
* Supports multiple filter types including dropdowns, lookups, status,
|
|
3583
|
+
* phase gates, dates, and more.
|
|
3792
3584
|
*/
|
|
3793
|
-
class
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3585
|
+
class DynamicFiltersConfig {
|
|
3586
|
+
dashboardService = inject(DashboardBuilderService);
|
|
3587
|
+
destroyRef = inject(DestroyRef);
|
|
3588
|
+
emptySelections = [];
|
|
3589
|
+
emptyModulesProperties = [];
|
|
3590
|
+
emptyProperties = [];
|
|
3591
|
+
propertiesFlatCache = new Map();
|
|
3592
|
+
dropdownPropertiesSignatureByIndex = new Map();
|
|
3593
|
+
/** Available lookups from parent context */
|
|
3594
|
+
lookups = input([], ...(ngDevMode ? [{ debugName: "lookups" }] : /* istanbul ignore next */ []));
|
|
3595
|
+
/** Available level schemas from parent context */
|
|
3596
|
+
levelsSchema = input([], ...(ngDevMode ? [{ debugName: "levelsSchema" }] : /* istanbul ignore next */ []));
|
|
3597
|
+
/** Available level logs from parent context */
|
|
3598
|
+
levelLogs = input([], ...(ngDevMode ? [{ debugName: "levelLogs" }] : /* istanbul ignore next */ []));
|
|
3599
|
+
/** Product type to filter available field types */
|
|
3600
|
+
productType = input('pplus', ...(ngDevMode ? [{ debugName: "productType" }] : /* istanbul ignore next */ []));
|
|
3601
|
+
/** Emit when level logs need to be loaded for a specific schema level */
|
|
3602
|
+
loadLevelLogs = output();
|
|
3603
|
+
/** Filter fields data */
|
|
3604
|
+
filterFields = signal([], ...(ngDevMode ? [{ debugName: "filterFields" }] : /* istanbul ignore next */ []));
|
|
3605
|
+
/** Active dropdown selection editor. Heavy nested editors stay lazy. */
|
|
3606
|
+
activeDropdownConfigIndex = signal(null, ...(ngDevMode ? [{ debugName: "activeDropdownConfigIndex" }] : /* istanbul ignore next */ []));
|
|
3607
|
+
/** Properties loaded for dropdown-by-selection fields. */
|
|
3608
|
+
fieldModulesProperties = signal({}, ...(ngDevMode ? [{ debugName: "fieldModulesProperties" }] : /* istanbul ignore next */ []));
|
|
3609
|
+
/** Paste configuration state */
|
|
3803
3610
|
showPasteArea = signal(false, ...(ngDevMode ? [{ debugName: "showPasteArea" }] : /* istanbul ignore next */ []));
|
|
3804
|
-
|
|
3805
|
-
pasteText = signal('', ...(ngDevMode ? [{ debugName: "pasteText" }] : /* istanbul ignore next */ []));
|
|
3806
|
-
/** Paste error */
|
|
3611
|
+
pasteContent = signal('', ...(ngDevMode ? [{ debugName: "pasteContent" }] : /* istanbul ignore next */ []));
|
|
3807
3612
|
pasteError = signal('', ...(ngDevMode ? [{ debugName: "pasteError" }] : /* istanbul ignore next */ []));
|
|
3808
3613
|
/** Disabled state */
|
|
3809
|
-
disabled = false;
|
|
3810
|
-
/** Available
|
|
3811
|
-
|
|
3812
|
-
const
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
return selected
|
|
3817
|
-
.filter((prop) => !used.includes(prop))
|
|
3818
|
-
.map((prop) => {
|
|
3819
|
-
const propInfo = props.find((p) => p.key === prop);
|
|
3820
|
-
return {
|
|
3821
|
-
value: prop,
|
|
3822
|
-
label: propInfo?.name || prop,
|
|
3823
|
-
};
|
|
3824
|
-
});
|
|
3825
|
-
}
|
|
3826
|
-
return props
|
|
3827
|
-
.filter((p) => !used.includes(p.key))
|
|
3828
|
-
.map((p) => ({
|
|
3829
|
-
value: p.key,
|
|
3830
|
-
label: p.name,
|
|
3831
|
-
}));
|
|
3832
|
-
}, ...(ngDevMode ? [{ debugName: "availableProperties" }] : /* istanbul ignore next */ []));
|
|
3833
|
-
/** Translation keys for iteration */
|
|
3834
|
-
translationKeys = computed(() => Object.keys(this.translations()), ...(ngDevMode ? [{ debugName: "translationKeys" }] : /* istanbul ignore next */ []));
|
|
3835
|
-
/** ControlValueAccessor callbacks */
|
|
3614
|
+
disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3615
|
+
/** Available field types filtered by product */
|
|
3616
|
+
availableFieldTypes = computed(() => {
|
|
3617
|
+
const product = this.productType();
|
|
3618
|
+
return FILTER_FIELD_TYPES.filter((type) => type.products.includes(product));
|
|
3619
|
+
}, ...(ngDevMode ? [{ debugName: "availableFieldTypes" }] : /* istanbul ignore next */ []));
|
|
3620
|
+
// ControlValueAccessor callbacks
|
|
3836
3621
|
onChange = () => { };
|
|
3837
3622
|
onTouched = () => { };
|
|
3838
|
-
//
|
|
3623
|
+
// ============================================
|
|
3624
|
+
// ControlValueAccessor Implementation
|
|
3625
|
+
// ============================================
|
|
3839
3626
|
writeValue(value) {
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
obj[item.key] = { ar: item.ar, en: item.en };
|
|
3846
|
-
});
|
|
3847
|
-
this.translations.set(obj);
|
|
3848
|
-
}
|
|
3849
|
-
else {
|
|
3850
|
-
this.translations.set({ ...value });
|
|
3627
|
+
const fields = (value ?? []).map((field) => this.normalizeField(field));
|
|
3628
|
+
this.filterFields.set(fields);
|
|
3629
|
+
fields.forEach((field, index) => {
|
|
3630
|
+
if (field.type === 'status' && field.configuration?.schemaLevelId) {
|
|
3631
|
+
this.loadLevelLogs.emit(field.configuration.schemaLevelId);
|
|
3851
3632
|
}
|
|
3852
|
-
}
|
|
3633
|
+
});
|
|
3853
3634
|
}
|
|
3854
3635
|
registerOnChange(fn) {
|
|
3855
3636
|
this.onChange = fn;
|
|
@@ -3858,99 +3639,497 @@ class PropertyTranslationsComponent {
|
|
|
3858
3639
|
this.onTouched = fn;
|
|
3859
3640
|
}
|
|
3860
3641
|
setDisabledState(isDisabled) {
|
|
3861
|
-
this.disabled
|
|
3642
|
+
this.disabled.set(isDisabled);
|
|
3862
3643
|
}
|
|
3863
|
-
//
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3644
|
+
// ============================================
|
|
3645
|
+
// Filter Field Management
|
|
3646
|
+
// ============================================
|
|
3647
|
+
/** Add a new filter field */
|
|
3648
|
+
addFilterField() {
|
|
3649
|
+
const newField = this.normalizeField(createDefaultFilterField());
|
|
3650
|
+
this.filterFields.update((fields) => [...fields, newField]);
|
|
3651
|
+
this.notifyChange();
|
|
3652
|
+
}
|
|
3653
|
+
/** Remove a filter field by index */
|
|
3654
|
+
removeFilterField(index) {
|
|
3655
|
+
this.filterFields.update((fields) => {
|
|
3656
|
+
const newFields = [...fields];
|
|
3657
|
+
newFields.splice(index, 1);
|
|
3658
|
+
return newFields;
|
|
3659
|
+
});
|
|
3660
|
+
this.removeCachedFieldState(index);
|
|
3661
|
+
this.notifyChange();
|
|
3662
|
+
}
|
|
3663
|
+
/** Update a filter field property */
|
|
3664
|
+
updateField(index, key, value) {
|
|
3665
|
+
this.filterFields.update((fields) => {
|
|
3666
|
+
const newFields = [...fields];
|
|
3667
|
+
newFields[index] = { ...newFields[index], [key]: value };
|
|
3668
|
+
return newFields;
|
|
3669
|
+
});
|
|
3670
|
+
this.notifyChange();
|
|
3671
|
+
}
|
|
3672
|
+
/** Update filter field name */
|
|
3673
|
+
updateFieldName(index, lang, value) {
|
|
3674
|
+
this.filterFields.update((fields) => {
|
|
3675
|
+
const newFields = [...fields];
|
|
3676
|
+
const field = newFields[index];
|
|
3677
|
+
field.name = {
|
|
3678
|
+
...(field.name ?? { en: '', ar: '' }),
|
|
3679
|
+
[lang]: value,
|
|
3680
|
+
};
|
|
3681
|
+
return newFields;
|
|
3682
|
+
});
|
|
3683
|
+
this.notifyChange();
|
|
3684
|
+
}
|
|
3685
|
+
/** Update filter field configuration */
|
|
3686
|
+
updateFieldConfig(index, key, value) {
|
|
3687
|
+
this.filterFields.update((fields) => {
|
|
3688
|
+
const newFields = [...fields];
|
|
3689
|
+
const field = newFields[index];
|
|
3690
|
+
field.configuration = {
|
|
3691
|
+
...this.createConfigurationForType(field.type, field.configuration),
|
|
3692
|
+
[key]: value,
|
|
3693
|
+
};
|
|
3694
|
+
return newFields;
|
|
3695
|
+
});
|
|
3696
|
+
this.notifyChange();
|
|
3697
|
+
}
|
|
3698
|
+
/** Handle field type change */
|
|
3699
|
+
onFieldTypeChange(index, type) {
|
|
3700
|
+
this.filterFields.update((fields) => {
|
|
3701
|
+
const newFields = [...fields];
|
|
3702
|
+
const current = newFields[index];
|
|
3703
|
+
newFields[index] = this.normalizeField({
|
|
3704
|
+
...current,
|
|
3705
|
+
type,
|
|
3706
|
+
key: this.requiresKey(type) ? current.key : undefined,
|
|
3707
|
+
name: type === 'separator' ? undefined : current.name,
|
|
3708
|
+
configuration: this.createConfigurationForType(type, current.configuration),
|
|
3709
|
+
});
|
|
3710
|
+
return newFields;
|
|
3711
|
+
});
|
|
3712
|
+
const field = this.filterFields()[index];
|
|
3713
|
+
if (field?.type === 'dropdownTVService') {
|
|
3714
|
+
this.openDropdownConfig(index, field);
|
|
3715
|
+
}
|
|
3716
|
+
else {
|
|
3717
|
+
if (this.activeDropdownConfigIndex() === index) {
|
|
3718
|
+
this.activeDropdownConfigIndex.set(null);
|
|
3719
|
+
}
|
|
3720
|
+
this.setFieldModulesProperties(index, []);
|
|
3721
|
+
}
|
|
3722
|
+
this.notifyChange();
|
|
3723
|
+
}
|
|
3724
|
+
/** Handle schema level change for status/phaseGate */
|
|
3725
|
+
onSchemaLevelChange(index, schemaLevelId) {
|
|
3726
|
+
this.updateFieldConfig(index, 'schemaLevelId', schemaLevelId);
|
|
3727
|
+
// Clear log ID and emit event to load level logs
|
|
3728
|
+
this.updateFieldConfig(index, 'logId', null);
|
|
3729
|
+
if (schemaLevelId) {
|
|
3730
|
+
this.loadLevelLogs.emit(schemaLevelId);
|
|
3873
3731
|
}
|
|
3874
3732
|
}
|
|
3875
|
-
|
|
3876
|
-
this.
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3733
|
+
updateDropdownSelections(index, selections) {
|
|
3734
|
+
const normalizedSelections = this.normalizeSelections(selections ?? []);
|
|
3735
|
+
const currentField = this.filterFields()[index];
|
|
3736
|
+
if (currentField &&
|
|
3737
|
+
this.getSelectionSignature(this.getDropdownSelections(currentField)) ===
|
|
3738
|
+
this.getSelectionSignature(normalizedSelections)) {
|
|
3739
|
+
return;
|
|
3740
|
+
}
|
|
3741
|
+
this.filterFields.update((fields) => {
|
|
3742
|
+
const newFields = [...fields];
|
|
3743
|
+
const field = this.normalizeField(newFields[index]);
|
|
3744
|
+
const payload = this.ensurePayload(field.configuration?.payload);
|
|
3745
|
+
field.configuration = {
|
|
3746
|
+
...field.configuration,
|
|
3747
|
+
payload: {
|
|
3748
|
+
...payload,
|
|
3749
|
+
selection: normalizedSelections,
|
|
3750
|
+
},
|
|
3751
|
+
};
|
|
3752
|
+
newFields[index] = field;
|
|
3753
|
+
return newFields;
|
|
3880
3754
|
});
|
|
3881
|
-
this.
|
|
3755
|
+
this.loadDropdownProperties(index, normalizedSelections);
|
|
3756
|
+
this.notifyChange();
|
|
3882
3757
|
}
|
|
3883
|
-
|
|
3884
|
-
this.
|
|
3885
|
-
|
|
3886
|
-
[prop]: { ...t[prop], [lang]: value },
|
|
3887
|
-
}));
|
|
3888
|
-
this.onModelChange();
|
|
3758
|
+
onDropdownModuleChange(index, _event) {
|
|
3759
|
+
const field = this.filterFields()[index];
|
|
3760
|
+
this.loadDropdownProperties(index, this.getDropdownSelections(field));
|
|
3889
3761
|
}
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3762
|
+
openDropdownConfig(index, field) {
|
|
3763
|
+
this.activeDropdownConfigIndex.set(index);
|
|
3764
|
+
this.loadDropdownProperties(index, this.getDropdownSelections(field));
|
|
3765
|
+
}
|
|
3766
|
+
closeDropdownConfig(index) {
|
|
3767
|
+
if (this.activeDropdownConfigIndex() === index) {
|
|
3768
|
+
this.activeDropdownConfigIndex.set(null);
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
isDropdownConfigOpen(index) {
|
|
3772
|
+
return this.activeDropdownConfigIndex() === index;
|
|
3773
|
+
}
|
|
3774
|
+
updateSelectedProperties(index, properties) {
|
|
3775
|
+
this.filterFields.update((fields) => {
|
|
3776
|
+
const newFields = [...fields];
|
|
3777
|
+
const field = this.normalizeField(newFields[index]);
|
|
3778
|
+
const payload = this.ensurePayload(field.configuration?.payload);
|
|
3779
|
+
field.configuration = {
|
|
3780
|
+
...field.configuration,
|
|
3781
|
+
payload: {
|
|
3782
|
+
...payload,
|
|
3783
|
+
query: {
|
|
3784
|
+
...payload.query,
|
|
3785
|
+
selectedProperties: properties ?? [],
|
|
3786
|
+
},
|
|
3787
|
+
},
|
|
3788
|
+
};
|
|
3789
|
+
newFields[index] = field;
|
|
3790
|
+
return newFields;
|
|
3895
3791
|
});
|
|
3792
|
+
this.notifyChange();
|
|
3793
|
+
}
|
|
3794
|
+
// ============================================
|
|
3795
|
+
// Copy/Paste Configuration
|
|
3796
|
+
// ============================================
|
|
3797
|
+
/** Copy current configuration to clipboard */
|
|
3798
|
+
copyConfiguration() {
|
|
3799
|
+
try {
|
|
3800
|
+
const config = JSON.stringify(this.filterFields(), null, 2);
|
|
3801
|
+
navigator.clipboard.writeText(config);
|
|
3802
|
+
}
|
|
3803
|
+
catch (error) {
|
|
3804
|
+
console.error('Error copying configuration:', error);
|
|
3805
|
+
}
|
|
3896
3806
|
}
|
|
3807
|
+
/** Toggle paste area visibility */
|
|
3897
3808
|
togglePasteArea() {
|
|
3898
3809
|
this.showPasteArea.update((v) => !v);
|
|
3899
|
-
this.
|
|
3810
|
+
this.pasteContent.set('');
|
|
3900
3811
|
this.pasteError.set('');
|
|
3901
3812
|
}
|
|
3902
|
-
|
|
3813
|
+
/** Apply pasted configuration */
|
|
3814
|
+
applyPastedConfiguration() {
|
|
3903
3815
|
try {
|
|
3904
|
-
const
|
|
3905
|
-
if (
|
|
3906
|
-
|
|
3907
|
-
this.showPasteArea.set(false);
|
|
3908
|
-
this.pasteText.set('');
|
|
3909
|
-
this.pasteError.set('');
|
|
3910
|
-
this.onModelChange();
|
|
3911
|
-
}
|
|
3912
|
-
else {
|
|
3913
|
-
this.pasteError.set('Invalid format');
|
|
3816
|
+
const parsedConfig = JSON.parse(this.pasteContent());
|
|
3817
|
+
if (!Array.isArray(parsedConfig)) {
|
|
3818
|
+
throw new Error('Configuration must be an array');
|
|
3914
3819
|
}
|
|
3820
|
+
// Validate each field
|
|
3821
|
+
parsedConfig.forEach((field) => {
|
|
3822
|
+
if (!field.type) {
|
|
3823
|
+
throw new Error('Each field must have a type');
|
|
3824
|
+
}
|
|
3825
|
+
if (field.type !== 'separator' &&
|
|
3826
|
+
(!field.name || !field.name.en || !field.name.ar)) {
|
|
3827
|
+
throw new Error('Each field (except separator) must have name with en and ar properties');
|
|
3828
|
+
}
|
|
3829
|
+
});
|
|
3830
|
+
const normalizedConfig = parsedConfig.map((field) => this.normalizeField(field));
|
|
3831
|
+
this.filterFields.set(normalizedConfig);
|
|
3832
|
+
this.resetDropdownCaches();
|
|
3833
|
+
this.notifyChange();
|
|
3834
|
+
this.showPasteArea.set(false);
|
|
3835
|
+
this.pasteContent.set('');
|
|
3836
|
+
this.pasteError.set('');
|
|
3915
3837
|
}
|
|
3916
|
-
catch (
|
|
3917
|
-
this.pasteError.set(
|
|
3838
|
+
catch (error) {
|
|
3839
|
+
this.pasteError.set(`Invalid configuration: ${error.message}`);
|
|
3918
3840
|
}
|
|
3919
3841
|
}
|
|
3920
|
-
//
|
|
3921
|
-
|
|
3922
|
-
|
|
3842
|
+
// ============================================
|
|
3843
|
+
// Helpers
|
|
3844
|
+
// ============================================
|
|
3845
|
+
/** Track by function for ngFor */
|
|
3846
|
+
trackByIndex(index) {
|
|
3847
|
+
return index;
|
|
3848
|
+
}
|
|
3849
|
+
getFieldTitle(field, index) {
|
|
3850
|
+
const name = field.name?.en || field.name?.ar;
|
|
3851
|
+
return name || field.key || this.getFieldTypeLabel(field.type) || `#${index + 1}`;
|
|
3852
|
+
}
|
|
3853
|
+
getFieldTypeLabel(type) {
|
|
3854
|
+
return (this.availableFieldTypes().find((item) => item.value === type)?.label ??
|
|
3855
|
+
type);
|
|
3856
|
+
}
|
|
3857
|
+
requiresKey(type) {
|
|
3858
|
+
return type !== 'section' && type !== 'separator';
|
|
3859
|
+
}
|
|
3860
|
+
requiresName(type) {
|
|
3861
|
+
return type !== 'separator';
|
|
3862
|
+
}
|
|
3863
|
+
supportsRequired(field) {
|
|
3864
|
+
return field.type !== 'section' && field.type !== 'separator';
|
|
3865
|
+
}
|
|
3866
|
+
supportsMultiple(field) {
|
|
3867
|
+
return ![
|
|
3868
|
+
'section',
|
|
3869
|
+
'separator',
|
|
3870
|
+
'checkbox',
|
|
3871
|
+
'user',
|
|
3872
|
+
'date',
|
|
3873
|
+
'year',
|
|
3874
|
+
].includes(field.type);
|
|
3875
|
+
}
|
|
3876
|
+
hasTypeConfiguration(field) {
|
|
3877
|
+
return [
|
|
3878
|
+
'dropdownTVService',
|
|
3879
|
+
'lookup',
|
|
3880
|
+
'status',
|
|
3881
|
+
'phaseGate',
|
|
3882
|
+
'checkbox',
|
|
3883
|
+
'year',
|
|
3884
|
+
].includes(field.type);
|
|
3885
|
+
}
|
|
3886
|
+
getDropdownSelections(field) {
|
|
3887
|
+
const selection = field.configuration?.payload?.selection;
|
|
3888
|
+
if (!Array.isArray(selection))
|
|
3889
|
+
return this.emptySelections;
|
|
3890
|
+
return selection;
|
|
3891
|
+
}
|
|
3892
|
+
getSelectedProperties(field) {
|
|
3893
|
+
return field.configuration?.payload?.query?.selectedProperties ?? [];
|
|
3894
|
+
}
|
|
3895
|
+
getModulesPropertiesForField(index) {
|
|
3896
|
+
return this.fieldModulesProperties()[index] ?? this.emptyModulesProperties;
|
|
3897
|
+
}
|
|
3898
|
+
getPropertiesFlatForField(index) {
|
|
3899
|
+
const source = this.getModulesPropertiesForField(index);
|
|
3900
|
+
if (!source.length)
|
|
3901
|
+
return this.emptyProperties;
|
|
3902
|
+
const cached = this.propertiesFlatCache.get(index);
|
|
3903
|
+
if (cached?.source === source)
|
|
3904
|
+
return cached.value;
|
|
3905
|
+
const value = source.flatMap((module) => module.properties.map((property) => ({
|
|
3906
|
+
...property,
|
|
3907
|
+
groupingBy: module.selectorName || module.moduleName,
|
|
3908
|
+
})));
|
|
3909
|
+
this.propertiesFlatCache.set(index, { source, value });
|
|
3910
|
+
return value;
|
|
3911
|
+
}
|
|
3912
|
+
getDropdownSummary(field) {
|
|
3913
|
+
const selections = this.getDropdownSelections(field);
|
|
3914
|
+
const selectionCount = selections.filter((selection) => {
|
|
3915
|
+
return !!selection.selector || !!selection.moduleType;
|
|
3916
|
+
}).length;
|
|
3917
|
+
const selectedProperties = this.getSelectedProperties(field).length;
|
|
3918
|
+
if (!selectionCount && !selectedProperties) {
|
|
3919
|
+
return 'No selection configured';
|
|
3920
|
+
}
|
|
3921
|
+
return `${selectionCount} selection${selectionCount === 1 ? '' : 's'}, ${selectedProperties} propert${selectedProperties === 1 ? 'y' : 'ies'}`;
|
|
3922
|
+
}
|
|
3923
|
+
/** Notify parent of changes */
|
|
3924
|
+
notifyChange() {
|
|
3925
|
+
this.onChange(this.filterFields());
|
|
3923
3926
|
this.onTouched();
|
|
3924
3927
|
}
|
|
3925
|
-
|
|
3926
|
-
|
|
3928
|
+
normalizeField(field) {
|
|
3929
|
+
const type = field.type ?? 'dropdownTVService';
|
|
3930
|
+
return {
|
|
3931
|
+
...field,
|
|
3932
|
+
type,
|
|
3933
|
+
key: this.requiresKey(type) ? field.key : undefined,
|
|
3934
|
+
name: this.requiresName(type) ? (field.name ?? { en: '', ar: '' }) : undefined,
|
|
3935
|
+
configuration: this.createConfigurationForType(type, field.configuration),
|
|
3936
|
+
};
|
|
3937
|
+
}
|
|
3938
|
+
createConfigurationForType(type, current) {
|
|
3939
|
+
if (type === 'section' || type === 'separator') {
|
|
3940
|
+
return {};
|
|
3941
|
+
}
|
|
3942
|
+
const base = {
|
|
3943
|
+
isRequird: current?.isRequird ?? false,
|
|
3944
|
+
};
|
|
3945
|
+
if (this.supportsMultiple({ type })) {
|
|
3946
|
+
base.isMultiple = current?.isMultiple ?? false;
|
|
3947
|
+
}
|
|
3948
|
+
switch (type) {
|
|
3949
|
+
case 'dropdownTVService':
|
|
3950
|
+
return {
|
|
3951
|
+
...base,
|
|
3952
|
+
payload: this.ensurePayload(current?.payload),
|
|
3953
|
+
};
|
|
3954
|
+
case 'lookup':
|
|
3955
|
+
return {
|
|
3956
|
+
...base,
|
|
3957
|
+
lookupId: current?.lookupId,
|
|
3958
|
+
};
|
|
3959
|
+
case 'status':
|
|
3960
|
+
return {
|
|
3961
|
+
...base,
|
|
3962
|
+
schemaLevelId: current?.schemaLevelId,
|
|
3963
|
+
logId: current?.logId ?? undefined,
|
|
3964
|
+
};
|
|
3965
|
+
case 'phaseGate':
|
|
3966
|
+
return {
|
|
3967
|
+
...base,
|
|
3968
|
+
schemaLevelId: current?.schemaLevelId,
|
|
3969
|
+
};
|
|
3970
|
+
case 'checkbox':
|
|
3971
|
+
return {
|
|
3972
|
+
...base,
|
|
3973
|
+
checked: current?.checked ?? false,
|
|
3974
|
+
};
|
|
3975
|
+
case 'year':
|
|
3976
|
+
return {
|
|
3977
|
+
...base,
|
|
3978
|
+
minYear: current?.minYear,
|
|
3979
|
+
maxYear: current?.maxYear,
|
|
3980
|
+
};
|
|
3981
|
+
default:
|
|
3982
|
+
return base;
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
ensurePayload(current) {
|
|
3986
|
+
return {
|
|
3987
|
+
dashboardId: current?.dashboardId ?? 0,
|
|
3988
|
+
chartType: current?.chartType ?? 'TableView',
|
|
3989
|
+
selection: current?.selection?.length
|
|
3990
|
+
? this.normalizeSelections(current.selection)
|
|
3991
|
+
: [
|
|
3992
|
+
{
|
|
3993
|
+
id: 1,
|
|
3994
|
+
service: 'pplus',
|
|
3995
|
+
selector: null,
|
|
3996
|
+
selectorName: null,
|
|
3997
|
+
filters: [],
|
|
3998
|
+
},
|
|
3999
|
+
],
|
|
4000
|
+
query: {
|
|
4001
|
+
selectedProperties: current?.query?.selectedProperties ?? [],
|
|
4002
|
+
},
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
loadDropdownProperties(index, selections) {
|
|
4006
|
+
const items = (selections ?? [])
|
|
4007
|
+
.map((selection) => ({
|
|
4008
|
+
serviceName: selection.service || 'pplus',
|
|
4009
|
+
selector: selection.selector ??
|
|
4010
|
+
selectorFromLegacy(selection.moduleType, selection.moduleId),
|
|
4011
|
+
}))
|
|
4012
|
+
.filter((item) => {
|
|
4013
|
+
return !!item.serviceName && !!item.selector;
|
|
4014
|
+
});
|
|
4015
|
+
const signature = this.getSelectionSignature(selections);
|
|
4016
|
+
if (!items.length) {
|
|
4017
|
+
this.setFieldModulesProperties(index, []);
|
|
4018
|
+
this.dropdownPropertiesSignatureByIndex.set(index, '');
|
|
4019
|
+
return;
|
|
4020
|
+
}
|
|
4021
|
+
if (this.dropdownPropertiesSignatureByIndex.get(index) === signature) {
|
|
4022
|
+
return;
|
|
4023
|
+
}
|
|
4024
|
+
this.dropdownPropertiesSignatureByIndex.set(index, signature);
|
|
4025
|
+
this.dashboardService
|
|
4026
|
+
.getBulkProperties(items)
|
|
4027
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
4028
|
+
.subscribe({
|
|
4029
|
+
next: (response) => {
|
|
4030
|
+
const enriched = this.dashboardService.enrichPropertiesWithSelectorName(response.data || []);
|
|
4031
|
+
this.setFieldModulesProperties(index, enriched.map((item) => ({
|
|
4032
|
+
moduleName: this.extractModuleTypeFromSelector(item.selector),
|
|
4033
|
+
selectorName: item.selectorName || null,
|
|
4034
|
+
selector: item.selector,
|
|
4035
|
+
properties: item.properties || [],
|
|
4036
|
+
})));
|
|
4037
|
+
},
|
|
4038
|
+
error: () => {
|
|
4039
|
+
this.dropdownPropertiesSignatureByIndex.delete(index);
|
|
4040
|
+
this.setFieldModulesProperties(index, []);
|
|
4041
|
+
},
|
|
4042
|
+
});
|
|
4043
|
+
}
|
|
4044
|
+
setFieldModulesProperties(index, modulesProperties) {
|
|
4045
|
+
this.propertiesFlatCache.delete(index);
|
|
4046
|
+
this.fieldModulesProperties.update((current) => ({
|
|
4047
|
+
...current,
|
|
4048
|
+
[index]: modulesProperties,
|
|
4049
|
+
}));
|
|
4050
|
+
}
|
|
4051
|
+
extractModuleTypeFromSelector(selector) {
|
|
4052
|
+
if (!selector)
|
|
4053
|
+
return '';
|
|
4054
|
+
return selector.split(':')[0] ?? '';
|
|
4055
|
+
}
|
|
4056
|
+
normalizeSelections(selections) {
|
|
4057
|
+
return (selections ?? []).map((selection, index) => ({
|
|
4058
|
+
...selection,
|
|
4059
|
+
id: selection.id ?? index + 1,
|
|
4060
|
+
service: selection.service ?? 'pplus',
|
|
4061
|
+
selector: selection.selector ??
|
|
4062
|
+
selectorFromLegacy(selection.moduleType, selection.moduleId),
|
|
4063
|
+
selectorName: selection.selectorName ?? null,
|
|
4064
|
+
filters: selection.filters ?? [],
|
|
4065
|
+
}));
|
|
4066
|
+
}
|
|
4067
|
+
getSelectionSignature(selections) {
|
|
4068
|
+
return JSON.stringify(this.normalizeSelections(selections).map((selection) => ({
|
|
4069
|
+
id: selection.id,
|
|
4070
|
+
service: selection.service ?? 'pplus',
|
|
4071
|
+
selector: selection.selector ??
|
|
4072
|
+
selectorFromLegacy(selection.moduleType, selection.moduleId),
|
|
4073
|
+
filters: selection.filters ?? [],
|
|
4074
|
+
})));
|
|
4075
|
+
}
|
|
4076
|
+
removeCachedFieldState(index) {
|
|
4077
|
+
this.resetDropdownCaches();
|
|
4078
|
+
this.fieldModulesProperties.update((current) => {
|
|
4079
|
+
const next = {};
|
|
4080
|
+
Object.entries(current).forEach(([key, value]) => {
|
|
4081
|
+
const numericKey = Number(key);
|
|
4082
|
+
if (numericKey < index)
|
|
4083
|
+
next[numericKey] = value;
|
|
4084
|
+
if (numericKey > index)
|
|
4085
|
+
next[numericKey - 1] = value;
|
|
4086
|
+
});
|
|
4087
|
+
return next;
|
|
4088
|
+
});
|
|
4089
|
+
const activeIndex = this.activeDropdownConfigIndex();
|
|
4090
|
+
if (activeIndex === index) {
|
|
4091
|
+
this.activeDropdownConfigIndex.set(null);
|
|
4092
|
+
}
|
|
4093
|
+
else if (activeIndex !== null && activeIndex > index) {
|
|
4094
|
+
this.activeDropdownConfigIndex.set(activeIndex - 1);
|
|
4095
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
resetDropdownCaches() {
|
|
4098
|
+
this.propertiesFlatCache.clear();
|
|
4099
|
+
this.dropdownPropertiesSignatureByIndex.clear();
|
|
4100
|
+
}
|
|
4101
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicFiltersConfig, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4102
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DynamicFiltersConfig, isStandalone: true, selector: "mt-dynamic-filters-config", inputs: { lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, levelsSchema: { classPropertyName: "levelsSchema", publicName: "levelsSchema", isSignal: true, isRequired: false, transformFunction: null }, levelLogs: { classPropertyName: "levelLogs", publicName: "levelLogs", isSignal: true, isRequired: false, transformFunction: null }, productType: { classPropertyName: "productType", publicName: "productType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadLevelLogs: "loadLevelLogs" }, providers: [
|
|
3927
4103
|
{
|
|
3928
4104
|
provide: NG_VALUE_ACCESSOR,
|
|
3929
|
-
useExisting: forwardRef(() =>
|
|
4105
|
+
useExisting: forwardRef(() => DynamicFiltersConfig),
|
|
3930
4106
|
multi: true,
|
|
3931
4107
|
},
|
|
3932
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <mt-card [title]=\"t('propertyTranslations')\">\n <ng-template #cardEnd>\n <div class=\"flex items-center gap-1\">\n <mt-button\n icon=\"general.copy-01\"\n severity=\"secondary\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"copyConfig()\"\n [pTooltip]=\"t('copyConfig')\"\n />\n <mt-button\n icon=\"general.clipboard\"\n severity=\"secondary\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"togglePasteArea()\"\n [pTooltip]=\"t('pasteConfig')\"\n />\n </div>\n </ng-template>\n\n <!-- Paste Area -->\n @if (showPasteArea()) {\n <div class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\">\n <mt-textarea-field\n [label]=\"t('pasteConfiguration')\"\n [ngModel]=\"pasteText()\"\n (ngModelChange)=\"pasteText.set($event)\"\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\n [rows]=\"4\"\n [disabled]=\"disabled\"\n />\n @if (pasteError()) {\n <small class=\"text-red-500 mt-1 block\">{{ pasteError() }}</small>\n }\n <div class=\"flex justify-end gap-2 mt-3\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('apply')\"\n size=\"small\"\n (onClick)=\"applyPastedConfig()\"\n />\n </div>\n </div>\n }\n\n <!-- Add Property Dropdown -->\n <div class=\"mb-4\">\n <div class=\"flex items-end gap-2\">\n <div class=\"flex-1\">\n <mt-select-field\n [label]=\"t('selectProperty')\"\n [ngModel]=\"selectedProperty()\"\n (ngModelChange)=\"selectedProperty.set($event)\"\n [options]=\"availableProperties()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectPropertyToTranslate')\"\n [filter]=\"true\"\n [disabled]=\"disabled\"\n />\n </div>\n <mt-button\n icon=\"general.plus\"\n [outlined]=\"true\"\n size=\"small\"\n [disabled]=\"disabled || !selectedProperty()\"\n (onClick)=\"addTranslation()\"\n [pTooltip]=\"t('addTranslation')\"\n />\n </div>\n </div>\n\n <!-- Translations List -->\n <div class=\"flex flex-col gap-4\">\n @for (prop of translationKeys(); track prop) {\n <div class=\"p-4 rounded-lg border border-surface-200 bg-surface-50\">\n <!-- Property Header -->\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"font-medium text-sm\">{{ prop }}</span>\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"removeTranslation(prop)\"\n />\n </div>\n\n <!-- Translation Fields -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <mt-text-field\n [label]=\"t('arabicLabel')\"\n [ngModel]=\"translations()[prop].ar\"\n (ngModelChange)=\"updateTranslation(prop, 'ar', $event)\"\n [placeholder]=\"t('enterArabicTranslation')\"\n [disabled]=\"disabled\"\n />\n <mt-text-field\n [label]=\"t('englishLabel')\"\n [ngModel]=\"translations()[prop].en\"\n (ngModelChange)=\"updateTranslation(prop, 'en', $event)\"\n [placeholder]=\"t('enterEnglishTranslation')\"\n [disabled]=\"disabled\"\n />\n </div>\n </div>\n }\n\n @if (translationKeys().length === 0) {\n <div class=\"text-center py-8 text-muted-color\">\n <i class=\"mti mti-translate text-3xl mb-2 block\"></i>\n <p class=\"mb-2\">{{ t(\"noTranslationsConfigured\") }}</p>\n </div>\n }\n </div>\n </mt-card>\n</div>\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: 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4108
|
+
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-3\"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n>\n <div\n class=\"flex flex-wrap items-center justify-between gap-2 border-b border-surface-200 pb-3\"\n >\n <h3 class=\"text-base font-semibold text-surface-800\">\n {{ t(\"filterFieldsConfiguration\") }}\n </h3>\n <div class=\"flex items-center gap-1.5\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"primary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n <mt-button\n icon=\"general.copy-06\"\n [pTooltip]=\"t('copyConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"copyConfiguration()\"\n />\n <mt-button\n icon=\"general.clipboard\"\n [pTooltip]=\"t('pasteConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"togglePasteArea()\"\n />\n </div>\n </div>\n\n @if (showPasteArea()) {\n <div\n class=\"flex flex-col gap-2 rounded-md border border-surface-200 bg-surface-50 p-3\"\n >\n <mt-textarea-field\n [label]=\"t('pasteConfigurationHere')\"\n [rows]=\"6\"\n [ngModel]=\"pasteContent()\"\n (ngModelChange)=\"pasteContent.set($event)\"\n [placeholder]=\"t('pasteJsonConfiguration')\"\n />\n @if (pasteError()) {\n <div class=\"text-sm text-red-500\">{{ pasteError() }}</div>\n }\n <div class=\"flex justify-end gap-2\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('applyConfiguration')\"\n size=\"small\"\n (onClick)=\"applyPastedConfiguration()\"\n />\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n @for (field of filterFields(); track trackByIndex($index); let i = $index) {\n <section\n class=\"overflow-hidden rounded-md border border-surface-200 bg-surface-0\"\n >\n <div\n class=\"flex items-center justify-between gap-3 border-b border-surface-200 bg-surface-100 px-3 py-2\"\n >\n <div class=\"min-w-0\">\n <div class=\"truncate text-sm font-semibold text-surface-800\">\n {{ getFieldTitle(field, i) }}\n </div>\n <div class=\"text-xs text-muted-color\">\n {{ getFieldTypeLabel(field.type) }}\n </div>\n </div>\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n size=\"small\"\n [rounded]=\"true\"\n [text]=\"true\"\n (onClick)=\"removeFilterField(i)\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <div class=\"flex flex-col gap-3 p-3\">\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('fieldType')\"\n [options]=\"availableFieldTypes()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"field.type\"\n (ngModelChange)=\"onFieldTypeChange(i, $event)\"\n />\n\n @if (requiresKey(field.type)) {\n <mt-text-field\n [label]=\"t('fieldKey')\"\n [placeholder]=\"t('enterFieldKey')\"\n [ngModel]=\"field.key\"\n (ngModelChange)=\"updateField(i, 'key', $event)\"\n />\n }\n\n @if (requiresName(field.type)) {\n <mt-text-field\n [label]=\"t('nameEnglish')\"\n [placeholder]=\"t('enterEnglishName')\"\n [ngModel]=\"field.name?.en\"\n (ngModelChange)=\"updateFieldName(i, 'en', $event)\"\n />\n <mt-text-field\n [label]=\"t('nameArabic')\"\n [placeholder]=\"t('enterArabicName')\"\n [ngModel]=\"field.name?.ar\"\n (ngModelChange)=\"updateFieldName(i, 'ar', $event)\"\n />\n }\n </div>\n\n @if (hasTypeConfiguration(field)) {\n <div\n class=\"flex w-full flex-col gap-3 rounded-md border border-surface-200 bg-surface-50 p-3\"\n >\n <div class=\"text-sm font-semibold text-surface-700\">\n {{ t(\"settings\") }}\n </div>\n\n @switch (field.type) {\n @case (\"dropdownTVService\") {\n @if (isDropdownConfigOpen(i)) {\n <div class=\"flex justify-end\">\n <mt-button\n [label]=\"t('close')\"\n icon=\"general.x-close\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n (onClick)=\"closeDropdownConfig(i)\"\n />\n </div>\n\n <mt-selection-configuration\n class=\"block w-full\"\n [ngModel]=\"getDropdownSelections(field)\"\n (ngModelChange)=\"updateDropdownSelections(i, $event)\"\n (moduleChange)=\"onDropdownModuleChange(i, $event)\"\n [modulesProperties]=\"getModulesPropertiesForField(i)\"\n [propertiesFlat]=\"getPropertiesFlatForField(i)\"\n />\n\n <mt-multi-select-field\n class=\"block w-full\"\n [label]=\"t('selectedProperties')\"\n [options]=\"getPropertiesFlatForField(i)\"\n optionValue=\"key\"\n optionLabel=\"name\"\n [filter]=\"true\"\n [ngModel]=\"getSelectedProperties(field)\"\n (ngModelChange)=\"updateSelectedProperties(i, $event)\"\n />\n } @else {\n <div\n class=\"flex flex-wrap items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-0 px-3 py-2\"\n >\n <span class=\"text-sm text-muted-color\">\n {{ getDropdownSummary(field) }}\n </span>\n <mt-button\n [label]=\"t('selectionsConfiguration')\"\n icon=\"general.settings-01\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"openDropdownConfig(i, field)\"\n />\n </div>\n }\n }\n\n @case (\"lookup\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('lookupId')\"\n [options]=\"lookups()\"\n optionValue=\"id\"\n optionLabel=\"displayName\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.lookupId\"\n (ngModelChange)=\"updateFieldConfig(i, 'lookupId', $event)\"\n />\n </div>\n }\n\n @case (\"status\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n\n @if (field.configuration?.schemaLevelId) {\n <mt-select-field\n [label]=\"t('logId')\"\n [options]=\"levelLogs()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.logId\"\n (ngModelChange)=\"updateFieldConfig(i, 'logId', $event)\"\n />\n }\n </div>\n }\n\n @case (\"phaseGate\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n </div>\n }\n\n @case (\"checkbox\") {\n <mt-toggle-field\n [label]=\"t('defaultChecked')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.checked ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'checked', $event)\"\n />\n }\n\n @case (\"year\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-number-field\n [label]=\"t('minYear')\"\n [placeholder]=\"t('minYear')\"\n [ngModel]=\"field.configuration?.minYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'minYear', $event)\"\n />\n <mt-number-field\n [label]=\"t('maxYear')\"\n [placeholder]=\"t('maxYear')\"\n [ngModel]=\"field.configuration?.maxYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'maxYear', $event)\"\n />\n </div>\n }\n }\n </div>\n }\n\n <div class=\"flex flex-wrap items-center gap-4\">\n @if (supportsRequired(field)) {\n <mt-toggle-field\n [label]=\"t('isRequired')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.isRequird ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'isRequird', $event)\"\n />\n }\n\n @if (supportsMultiple(field)) {\n <mt-toggle-field\n [label]=\"t('isMultiple')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.isMultiple ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'isMultiple', $event)\"\n />\n }\n </div>\n </div>\n </section>\n } @empty {\n <div\n class=\"flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-surface-300 py-10 text-center text-muted-color\"\n >\n <mt-icon icon=\"general.filter-lines\" class=\"text-3xl\" />\n <p class=\"text-sm font-medium\">{{ t(\"noFilterFieldsConfigured\") }}</p>\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n </div>\n }\n </div>\n</div>\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: Icon, selector: "mt-icon", inputs: ["icon"] }, { 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { 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: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], 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: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { kind: "component", type: SelectionConfiguration, selector: "mt-selection-configuration", inputs: ["structureLocked", "workspaceId", "modulesProperties", "propertiesFlat"], outputs: ["moduleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3933
4109
|
}
|
|
3934
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type:
|
|
4110
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DynamicFiltersConfig, decorators: [{
|
|
3935
4111
|
type: Component,
|
|
3936
|
-
args: [{ selector: 'mt-
|
|
4112
|
+
args: [{ selector: 'mt-dynamic-filters-config', standalone: true, imports: [
|
|
3937
4113
|
CommonModule,
|
|
3938
4114
|
FormsModule,
|
|
3939
4115
|
TranslocoDirective,
|
|
3940
4116
|
Button,
|
|
4117
|
+
Icon,
|
|
3941
4118
|
SelectField,
|
|
3942
4119
|
TextField,
|
|
4120
|
+
NumberField,
|
|
4121
|
+
MultiSelectField,
|
|
4122
|
+
ToggleField,
|
|
3943
4123
|
TextareaField,
|
|
3944
|
-
|
|
3945
|
-
Tooltip,
|
|
4124
|
+
SelectionConfiguration,
|
|
3946
4125
|
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
3947
4126
|
{
|
|
3948
4127
|
provide: NG_VALUE_ACCESSOR,
|
|
3949
|
-
useExisting: forwardRef(() =>
|
|
4128
|
+
useExisting: forwardRef(() => DynamicFiltersConfig),
|
|
3950
4129
|
multi: true,
|
|
3951
4130
|
},
|
|
3952
|
-
], template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <mt-card [title]=\"t('propertyTranslations')\">\n <ng-template #cardEnd>\n <div class=\"flex items-center gap-1\">\n <mt-button\n icon=\"general.copy-01\"\n severity=\"secondary\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"copyConfig()\"\n [pTooltip]=\"t('copyConfig')\"\n />\n <mt-button\n icon=\"general.clipboard\"\n severity=\"secondary\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"togglePasteArea()\"\n [pTooltip]=\"t('pasteConfig')\"\n />\n </div>\n </ng-template>\n\n <!-- Paste Area -->\n @if (showPasteArea()) {\n <div class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\">\n <mt-textarea-field\n [label]=\"t('pasteConfiguration')\"\n [ngModel]=\"pasteText()\"\n (ngModelChange)=\"pasteText.set($event)\"\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\n [rows]=\"4\"\n [disabled]=\"disabled\"\n />\n @if (pasteError()) {\n <small class=\"text-red-500 mt-1 block\">{{ pasteError() }}</small>\n }\n <div class=\"flex justify-end gap-2 mt-3\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('apply')\"\n size=\"small\"\n (onClick)=\"applyPastedConfig()\"\n />\n </div>\n </div>\n }\n\n <!-- Add Property Dropdown -->\n <div class=\"mb-4\">\n <div class=\"flex items-end gap-2\">\n <div class=\"flex-1\">\n <mt-select-field\n [label]=\"t('selectProperty')\"\n [ngModel]=\"selectedProperty()\"\n (ngModelChange)=\"selectedProperty.set($event)\"\n [options]=\"availableProperties()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectPropertyToTranslate')\"\n [filter]=\"true\"\n [disabled]=\"disabled\"\n />\n </div>\n <mt-button\n icon=\"general.plus\"\n [outlined]=\"true\"\n size=\"small\"\n [disabled]=\"disabled || !selectedProperty()\"\n (onClick)=\"addTranslation()\"\n [pTooltip]=\"t('addTranslation')\"\n />\n </div>\n </div>\n\n <!-- Translations List -->\n <div class=\"flex flex-col gap-4\">\n @for (prop of translationKeys(); track prop) {\n <div class=\"p-4 rounded-lg border border-surface-200 bg-surface-50\">\n <!-- Property Header -->\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"font-medium text-sm\">{{ prop }}</span>\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [text]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"removeTranslation(prop)\"\n />\n </div>\n\n <!-- Translation Fields -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <mt-text-field\n [label]=\"t('arabicLabel')\"\n [ngModel]=\"translations()[prop].ar\"\n (ngModelChange)=\"updateTranslation(prop, 'ar', $event)\"\n [placeholder]=\"t('enterArabicTranslation')\"\n [disabled]=\"disabled\"\n />\n <mt-text-field\n [label]=\"t('englishLabel')\"\n [ngModel]=\"translations()[prop].en\"\n (ngModelChange)=\"updateTranslation(prop, 'en', $event)\"\n [placeholder]=\"t('enterEnglishTranslation')\"\n [disabled]=\"disabled\"\n />\n </div>\n </div>\n }\n\n @if (translationKeys().length === 0) {\n <div class=\"text-center py-8 text-muted-color\">\n <i class=\"mti mti-translate text-3xl mb-2 block\"></i>\n <p class=\"mb-2\">{{ t(\"noTranslationsConfigured\") }}</p>\n </div>\n }\n </div>\n </mt-card>\n</div>\n" }]
|
|
3953
|
-
}], propDecorators: {
|
|
4131
|
+
], template: "<div\n class=\"flex flex-col gap-3\"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n>\n <div\n class=\"flex flex-wrap items-center justify-between gap-2 border-b border-surface-200 pb-3\"\n >\n <h3 class=\"text-base font-semibold text-surface-800\">\n {{ t(\"filterFieldsConfiguration\") }}\n </h3>\n <div class=\"flex items-center gap-1.5\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"primary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n <mt-button\n icon=\"general.copy-06\"\n [pTooltip]=\"t('copyConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"copyConfiguration()\"\n />\n <mt-button\n icon=\"general.clipboard\"\n [pTooltip]=\"t('pasteConfiguration')\"\n tooltipPosition=\"top\"\n severity=\"secondary\"\n size=\"small\"\n [rounded]=\"true\"\n (onClick)=\"togglePasteArea()\"\n />\n </div>\n </div>\n\n @if (showPasteArea()) {\n <div\n class=\"flex flex-col gap-2 rounded-md border border-surface-200 bg-surface-50 p-3\"\n >\n <mt-textarea-field\n [label]=\"t('pasteConfigurationHere')\"\n [rows]=\"6\"\n [ngModel]=\"pasteContent()\"\n (ngModelChange)=\"pasteContent.set($event)\"\n [placeholder]=\"t('pasteJsonConfiguration')\"\n />\n @if (pasteError()) {\n <div class=\"text-sm text-red-500\">{{ pasteError() }}</div>\n }\n <div class=\"flex justify-end gap-2\">\n <mt-button\n [label]=\"t('cancel')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"togglePasteArea()\"\n />\n <mt-button\n [label]=\"t('applyConfiguration')\"\n size=\"small\"\n (onClick)=\"applyPastedConfiguration()\"\n />\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n @for (field of filterFields(); track trackByIndex($index); let i = $index) {\n <section\n class=\"overflow-hidden rounded-md border border-surface-200 bg-surface-0\"\n >\n <div\n class=\"flex items-center justify-between gap-3 border-b border-surface-200 bg-surface-100 px-3 py-2\"\n >\n <div class=\"min-w-0\">\n <div class=\"truncate text-sm font-semibold text-surface-800\">\n {{ getFieldTitle(field, i) }}\n </div>\n <div class=\"text-xs text-muted-color\">\n {{ getFieldTypeLabel(field.type) }}\n </div>\n </div>\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n size=\"small\"\n [rounded]=\"true\"\n [text]=\"true\"\n (onClick)=\"removeFilterField(i)\"\n [disabled]=\"disabled()\"\n />\n </div>\n\n <div class=\"flex flex-col gap-3 p-3\">\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('fieldType')\"\n [options]=\"availableFieldTypes()\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [ngModel]=\"field.type\"\n (ngModelChange)=\"onFieldTypeChange(i, $event)\"\n />\n\n @if (requiresKey(field.type)) {\n <mt-text-field\n [label]=\"t('fieldKey')\"\n [placeholder]=\"t('enterFieldKey')\"\n [ngModel]=\"field.key\"\n (ngModelChange)=\"updateField(i, 'key', $event)\"\n />\n }\n\n @if (requiresName(field.type)) {\n <mt-text-field\n [label]=\"t('nameEnglish')\"\n [placeholder]=\"t('enterEnglishName')\"\n [ngModel]=\"field.name?.en\"\n (ngModelChange)=\"updateFieldName(i, 'en', $event)\"\n />\n <mt-text-field\n [label]=\"t('nameArabic')\"\n [placeholder]=\"t('enterArabicName')\"\n [ngModel]=\"field.name?.ar\"\n (ngModelChange)=\"updateFieldName(i, 'ar', $event)\"\n />\n }\n </div>\n\n @if (hasTypeConfiguration(field)) {\n <div\n class=\"flex w-full flex-col gap-3 rounded-md border border-surface-200 bg-surface-50 p-3\"\n >\n <div class=\"text-sm font-semibold text-surface-700\">\n {{ t(\"settings\") }}\n </div>\n\n @switch (field.type) {\n @case (\"dropdownTVService\") {\n @if (isDropdownConfigOpen(i)) {\n <div class=\"flex justify-end\">\n <mt-button\n [label]=\"t('close')\"\n icon=\"general.x-close\"\n severity=\"secondary\"\n size=\"small\"\n [text]=\"true\"\n (onClick)=\"closeDropdownConfig(i)\"\n />\n </div>\n\n <mt-selection-configuration\n class=\"block w-full\"\n [ngModel]=\"getDropdownSelections(field)\"\n (ngModelChange)=\"updateDropdownSelections(i, $event)\"\n (moduleChange)=\"onDropdownModuleChange(i, $event)\"\n [modulesProperties]=\"getModulesPropertiesForField(i)\"\n [propertiesFlat]=\"getPropertiesFlatForField(i)\"\n />\n\n <mt-multi-select-field\n class=\"block w-full\"\n [label]=\"t('selectedProperties')\"\n [options]=\"getPropertiesFlatForField(i)\"\n optionValue=\"key\"\n optionLabel=\"name\"\n [filter]=\"true\"\n [ngModel]=\"getSelectedProperties(field)\"\n (ngModelChange)=\"updateSelectedProperties(i, $event)\"\n />\n } @else {\n <div\n class=\"flex flex-wrap items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-0 px-3 py-2\"\n >\n <span class=\"text-sm text-muted-color\">\n {{ getDropdownSummary(field) }}\n </span>\n <mt-button\n [label]=\"t('selectionsConfiguration')\"\n icon=\"general.settings-01\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"openDropdownConfig(i, field)\"\n />\n </div>\n }\n }\n\n @case (\"lookup\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('lookupId')\"\n [options]=\"lookups()\"\n optionValue=\"id\"\n optionLabel=\"displayName\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.lookupId\"\n (ngModelChange)=\"updateFieldConfig(i, 'lookupId', $event)\"\n />\n </div>\n }\n\n @case (\"status\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n\n @if (field.configuration?.schemaLevelId) {\n <mt-select-field\n [label]=\"t('logId')\"\n [options]=\"levelLogs()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.logId\"\n (ngModelChange)=\"updateFieldConfig(i, 'logId', $event)\"\n />\n }\n </div>\n }\n\n @case (\"phaseGate\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-select-field\n [label]=\"t('schemaLevelId')\"\n [options]=\"levelsSchema()\"\n optionValue=\"id\"\n optionLabel=\"description\"\n [filter]=\"true\"\n [ngModel]=\"field.configuration?.schemaLevelId\"\n (ngModelChange)=\"onSchemaLevelChange(i, $event)\"\n />\n </div>\n }\n\n @case (\"checkbox\") {\n <mt-toggle-field\n [label]=\"t('defaultChecked')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.checked ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'checked', $event)\"\n />\n }\n\n @case (\"year\") {\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\n <mt-number-field\n [label]=\"t('minYear')\"\n [placeholder]=\"t('minYear')\"\n [ngModel]=\"field.configuration?.minYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'minYear', $event)\"\n />\n <mt-number-field\n [label]=\"t('maxYear')\"\n [placeholder]=\"t('maxYear')\"\n [ngModel]=\"field.configuration?.maxYear\"\n (ngModelChange)=\"updateFieldConfig(i, 'maxYear', $event)\"\n />\n </div>\n }\n }\n </div>\n }\n\n <div class=\"flex flex-wrap items-center gap-4\">\n @if (supportsRequired(field)) {\n <mt-toggle-field\n [label]=\"t('isRequired')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.isRequird ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'isRequird', $event)\"\n />\n }\n\n @if (supportsMultiple(field)) {\n <mt-toggle-field\n [label]=\"t('isMultiple')\"\n size=\"small\"\n [ngModel]=\"field.configuration?.isMultiple ?? false\"\n (ngModelChange)=\"updateFieldConfig(i, 'isMultiple', $event)\"\n />\n }\n </div>\n </div>\n </section>\n } @empty {\n <div\n class=\"flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-surface-300 py-10 text-center text-muted-color\"\n >\n <mt-icon icon=\"general.filter-lines\" class=\"text-3xl\" />\n <p class=\"text-sm font-medium\">{{ t(\"noFilterFieldsConfigured\") }}</p>\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addField')\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"addFilterField()\"\n [disabled]=\"disabled()\"\n />\n </div>\n }\n </div>\n</div>\n" }]
|
|
4132
|
+
}], propDecorators: { lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], levelsSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelsSchema", required: false }] }], levelLogs: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelLogs", required: false }] }], productType: [{ type: i0.Input, args: [{ isSignal: true, alias: "productType", required: false }] }], loadLevelLogs: [{ type: i0.Output, args: ["loadLevelLogs"] }] } });
|
|
3954
4133
|
|
|
3955
4134
|
/**
|
|
3956
4135
|
* Manage Filter On Page Component
|
|
@@ -3969,50 +4148,14 @@ class ManageFilterOnPage {
|
|
|
3969
4148
|
ref = inject(ModalRef);
|
|
3970
4149
|
/** Input: Initial filters data */
|
|
3971
4150
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
3972
|
-
/** All charts and dialogs on the selected dashboard. */
|
|
3973
|
-
chartItems = input([], ...(ngDevMode ? [{ debugName: "chartItems" }] : /* istanbul ignore next */ []));
|
|
3974
4151
|
/** Input: Available lookups for dropdown */
|
|
3975
4152
|
lookups = input([], ...(ngDevMode ? [{ debugName: "lookups" }] : /* istanbul ignore next */ []));
|
|
3976
4153
|
/** Input: Available level schemas */
|
|
3977
4154
|
levelsSchema = input([], ...(ngDevMode ? [{ debugName: "levelsSchema" }] : /* istanbul ignore next */ []));
|
|
3978
4155
|
/** Filters configuration */
|
|
3979
4156
|
filtersConfig = signal([], ...(ngDevMode ? [{ debugName: "filtersConfig" }] : /* istanbul ignore next */ []));
|
|
3980
|
-
/** Bulk selection filters to apply/delete across matching charts. */
|
|
3981
|
-
bulkSelection = signal([], ...(ngDevMode ? [{ debugName: "bulkSelection" }] : /* istanbul ignore next */ []));
|
|
3982
|
-
/** Labels to apply to all table/dialog table charts. */
|
|
3983
|
-
bulkLabels = signal({}, ...(ngDevMode ? [{ debugName: "bulkLabels" }] : /* istanbul ignore next */ []));
|
|
3984
4157
|
/** Level logs for status filter */
|
|
3985
4158
|
levelLogs = signal([], ...(ngDevMode ? [{ debugName: "levelLogs" }] : /* istanbul ignore next */ []));
|
|
3986
|
-
bulkPropertyOptions = computed(() => {
|
|
3987
|
-
const properties = new Map();
|
|
3988
|
-
this.chartItems().forEach((item) => {
|
|
3989
|
-
const query = item.config?.serviceConfig?.query;
|
|
3990
|
-
[
|
|
3991
|
-
query?.['properties'],
|
|
3992
|
-
query?.['extraProperties'],
|
|
3993
|
-
query?.['groupByProperties'],
|
|
3994
|
-
].forEach((value) => {
|
|
3995
|
-
if (!Array.isArray(value))
|
|
3996
|
-
return;
|
|
3997
|
-
value.forEach((property) => {
|
|
3998
|
-
const key = typeof property === 'string'
|
|
3999
|
-
? property
|
|
4000
|
-
: (property?.key ?? property?.propertyKey ?? property?.value);
|
|
4001
|
-
if (!key || properties.has(String(key)))
|
|
4002
|
-
return;
|
|
4003
|
-
const name = typeof property === 'string'
|
|
4004
|
-
? property
|
|
4005
|
-
: (property?.name ?? property?.label ?? property?.displayName);
|
|
4006
|
-
properties.set(String(key), {
|
|
4007
|
-
key: String(key),
|
|
4008
|
-
name: String(name || key),
|
|
4009
|
-
});
|
|
4010
|
-
});
|
|
4011
|
-
});
|
|
4012
|
-
});
|
|
4013
|
-
return [...properties.values()];
|
|
4014
|
-
}, ...(ngDevMode ? [{ debugName: "bulkPropertyOptions" }] : /* istanbul ignore next */ []));
|
|
4015
|
-
bulkPropertyKeys = computed(() => this.bulkPropertyOptions().map((property) => property.key), ...(ngDevMode ? [{ debugName: "bulkPropertyKeys" }] : /* istanbul ignore next */ []));
|
|
4016
4159
|
ngOnInit() {
|
|
4017
4160
|
this.filtersConfig.set([...(this.data() || [])]);
|
|
4018
4161
|
}
|
|
@@ -4020,12 +4163,6 @@ class ManageFilterOnPage {
|
|
|
4020
4163
|
onFiltersChange(filters) {
|
|
4021
4164
|
this.filtersConfig.set(filters);
|
|
4022
4165
|
}
|
|
4023
|
-
onBulkSelectionChange(selections) {
|
|
4024
|
-
this.bulkSelection.set(selections ?? []);
|
|
4025
|
-
}
|
|
4026
|
-
onBulkLabelsChange(labels) {
|
|
4027
|
-
this.bulkLabels.set(labels ?? {});
|
|
4028
|
-
}
|
|
4029
4166
|
/**
|
|
4030
4167
|
* Hook for hosts that want to feed level-log values into the filter
|
|
4031
4168
|
* dialog. The host listens to `(loadLevelLogs)` (when consumers wire it)
|
|
@@ -4038,26 +4175,8 @@ class ManageFilterOnPage {
|
|
|
4038
4175
|
}
|
|
4039
4176
|
/** Save and close the dialog */
|
|
4040
4177
|
save() {
|
|
4041
|
-
this.ref.close({ filters: this.filtersConfig() });
|
|
4042
|
-
}
|
|
4043
|
-
applyBulkFilters() {
|
|
4044
4178
|
this.ref.close({
|
|
4045
4179
|
filters: this.filtersConfig(),
|
|
4046
|
-
bulkSelection: this.bulkSelection(),
|
|
4047
|
-
bulkOperation: 'applyFilters',
|
|
4048
|
-
});
|
|
4049
|
-
}
|
|
4050
|
-
deleteBulkFilters() {
|
|
4051
|
-
this.ref.close({
|
|
4052
|
-
filters: this.filtersConfig(),
|
|
4053
|
-
bulkSelection: this.bulkSelection(),
|
|
4054
|
-
bulkOperation: 'deleteFilters',
|
|
4055
|
-
});
|
|
4056
|
-
}
|
|
4057
|
-
applyBulkLabels() {
|
|
4058
|
-
this.ref.close({
|
|
4059
|
-
filters: this.filtersConfig(),
|
|
4060
|
-
labels: this.bulkLabels(),
|
|
4061
4180
|
});
|
|
4062
4181
|
}
|
|
4063
4182
|
/** Cancel and close the dialog */
|
|
@@ -4065,7 +4184,7 @@ class ManageFilterOnPage {
|
|
|
4065
4184
|
this.ref.close(null);
|
|
4066
4185
|
}
|
|
4067
4186
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageFilterOnPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4068
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: ManageFilterOnPage, isStandalone: true, selector: "mt-manage-filter-on-page", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null },
|
|
4187
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: ManageFilterOnPage, isStandalone: true, selector: "mt-manage-filter-on-page", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, levelsSchema: { classPropertyName: "levelsSchema", publicName: "levelsSchema", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n class=\"flex h-full min-h-0 flex-col\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\n class=\"flex-1 min-h-0 overflow-y-auto px-4 py-3\"\n [class]=\"modal.contentClass\"\n >\n <mt-dynamic-filters-config\n class=\"block\"\n [ngModel]=\"filtersConfig()\"\n (ngModelChange)=\"onFiltersChange($event)\"\n [lookups]=\"lookups()\"\n [levelsSchema]=\"levelsSchema()\"\n [levelLogs]=\"levelLogs()\"\n (loadLevelLogs)=\"onLoadLevelLogs($event)\"\n />\n </div>\n\n <div\n [class]=\"\r\n modal.footerClass +\r\n ' !h-auto !min-h-0 !justify-end !gap-2 !border-t !border-surface-200 !px-4 !py-3'\r\n \"\r\n >\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n <mt-button [label]=\"t('save')\" icon=\"general.save-02\" (onClick)=\"save()\" />\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: "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: DynamicFiltersConfig, selector: "mt-dynamic-filters-config", inputs: ["lookups", "levelsSchema", "levelLogs", "productType"], outputs: ["loadLevelLogs"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4069
4188
|
}
|
|
4070
4189
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageFilterOnPage, decorators: [{
|
|
4071
4190
|
type: Component,
|
|
@@ -4075,10 +4194,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4075
4194
|
TranslocoDirective,
|
|
4076
4195
|
Button,
|
|
4077
4196
|
DynamicFiltersConfig,
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\r\n class=\"flex h-full min-h-0 flex-col\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <!-- Content -->\r\n <div\r\n class=\"flex-1 min-h-0 overflow-y-auto p-4\"\r\n [class]=\"modal.contentClass\"\r\n >\r\n <div class=\"flex flex-col gap-5\">\r\n <section\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 p-4\"\r\n aria-labelledby=\"db-page-filters-title\"\r\n >\r\n <h3 id=\"db-page-filters-title\" class=\"mb-4 text-base font-semibold\">\r\n {{ t(\"pageFilters\") }}\r\n </h3>\r\n <mt-dynamic-filters-config\r\n [ngModel]=\"filtersConfig()\"\r\n (ngModelChange)=\"onFiltersChange($event)\"\r\n [lookups]=\"lookups()\"\r\n [levelsSchema]=\"levelsSchema()\"\r\n [levelLogs]=\"levelLogs()\"\r\n (loadLevelLogs)=\"onLoadLevelLogs($event)\"\r\n />\r\n </section>\r\n\r\n <section\r\n class=\"rounded-lg border border-surface-200 bg-surface-0 p-4\"\r\n aria-labelledby=\"db-bulk-chart-filters-title\"\r\n >\r\n <h3\r\n id=\"db-bulk-chart-filters-title\"\r\n class=\"mb-2 text-base font-semibold\"\r\n >\r\n {{ t(\"bulkChartFilters\") }}\r\n </h3>\r\n <div class=\"mb-4 text-sm text-muted-color\">\r\n {{ t(\"bulkChartFiltersDescription\") }}\r\n </div>\r\n <mt-selection-configuration\r\n [ngModel]=\"bulkSelection()\"\r\n (ngModelChange)=\"onBulkSelectionChange($event)\"\r\n />\r\n <div class=\"mt-4 flex flex-wrap justify-end gap-2\">\r\n <mt-button\r\n [label]=\"t('applyFilter')\"\r\n icon=\"general.filter-lines\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n (onClick)=\"applyBulkFilters()\"\r\n />\r\n <mt-button\r\n [label]=\"t('deleteFilters')\"\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [outlined]=\"true\"\r\n (onClick)=\"deleteBulkFilters()\"\r\n />\r\n </div>\r\n </section>\r\n\r\n <mt-property-translations\r\n [ngModel]=\"bulkLabels()\"\r\n (ngModelChange)=\"onBulkLabelsChange($event)\"\r\n [propertiesFlat]=\"bulkPropertyOptions()\"\r\n [selectedProperties]=\"bulkPropertyKeys()\"\r\n />\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n [label]=\"t('applyLabels')\"\r\n icon=\"general.check\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"applyBulkLabels()\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Footer Actions -->\r\n <div\r\n [class]=\"\r\n modal.footerClass +\r\n ' !h-auto !min-h-0 !justify-end !gap-2 !border-t !border-surface-200 !px-4 !py-3'\r\n \"\r\n >\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n <mt-button [label]=\"t('save')\" icon=\"general.save-02\" (onClick)=\"save()\" />\r\n </div>\r\n</div>\r\n" }]
|
|
4081
|
-
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], chartItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartItems", required: false }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], levelsSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelsSchema", required: false }] }] } });
|
|
4197
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\r\n class=\"flex h-full min-h-0 flex-col\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n>\r\n <div\n class=\"flex-1 min-h-0 overflow-y-auto px-4 py-3\"\n [class]=\"modal.contentClass\"\n >\n <mt-dynamic-filters-config\n class=\"block\"\n [ngModel]=\"filtersConfig()\"\n (ngModelChange)=\"onFiltersChange($event)\"\n [lookups]=\"lookups()\"\n [levelsSchema]=\"levelsSchema()\"\n [levelLogs]=\"levelLogs()\"\n (loadLevelLogs)=\"onLoadLevelLogs($event)\"\n />\n </div>\n\n <div\n [class]=\"\r\n modal.footerClass +\r\n ' !h-auto !min-h-0 !justify-end !gap-2 !border-t !border-surface-200 !px-4 !py-3'\r\n \"\r\n >\r\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"close()\" />\r\n <mt-button [label]=\"t('save')\" icon=\"general.save-02\" (onClick)=\"save()\" />\r\n </div>\r\n</div>\r\n" }]
|
|
4198
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], levelsSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelsSchema", required: false }] }] } });
|
|
4082
4199
|
|
|
4083
4200
|
/**
|
|
4084
4201
|
* Map a manifest entry to the public ChartTypeConfig shape so that
|
|
@@ -9114,7 +9231,7 @@ class DisplaySettings {
|
|
|
9114
9231
|
return '';
|
|
9115
9232
|
}
|
|
9116
9233
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DisplaySettings, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9117
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DisplaySettings, isStandalone: true, selector: "mt-display-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, availableProperties: { classPropertyName: "availableProperties", publicName: "availableProperties", isSignal: true, isRequired: false, transformFunction: null }, selectedProperties: { classPropertyName: "selectedProperties", publicName: "selectedProperties", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Header Configuration -->\r\n @if (\r\n shouldShowField(\"centerHeader\") || shouldShowField(\"advancedHeaderConfig\")\r\n ) {\r\n <mt-card [title]=\"t('headerConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-5\">\r\n @if (shouldShowField(\"centerHeader\")) {\r\n <mt-toggle-field\r\n [label]=\"t('centerHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderCentered || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderCentered', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"advancedHeaderConfig\")) {\r\n <mt-toggle-field\r\n [label]=\"t('hideHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderHidden || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderHidden', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerColor')\"\r\n [ngModel]=\"headerCardConfig().headerColor || ''\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerColor', $event)\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('headerFontSize')\"\r\n [ngModel]=\"headerCardConfig().headerFontSize || 14\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerFontSize', $event)\"\r\n [min]=\"10\"\r\n [max]=\"48\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Colors Section (for cards) -->\r\n @if (\r\n shouldShowField(\"bgColor\") ||\r\n shouldShowField(\"textColor\") ||\r\n shouldShowField(\"icon\")\r\n ) {\r\n <mt-card [title]=\"t('cardColors')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-5\">\r\n @if (shouldShowField(\"bgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"styleConfig()['background-color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('background-color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"textColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"styleConfig()['color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"icon\")) {\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"configAsType()['icon'] || ''\"\r\n (ngModelChange)=\"updateConfigAsType('icon', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"styleConfig()['iconColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconBgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconBgColor')\"\r\n [ngModel]=\"styleConfig()['iconBgColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconBgColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"positionTitle\")) {\r\n <mt-select-field\r\n [label]=\"t('positionTitle')\"\r\n [ngModel]=\"styleConfig()['justify-content'] || 'start'\"\r\n (ngModelChange)=\"updateStyleConfig('justify-content', $event)\"\r\n [options]=\"positionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Border Top Section -->\r\n @if (shouldShowField(\"borderTop\")) {\r\n <mt-card [title]=\"t('borderTop')\">\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-5\">\r\n <mt-toggle-field\r\n [label]=\"t('showBorderTop')\"\r\n [ngModel]=\"styleConfig()['border-top-show'] || false\"\r\n (ngModelChange)=\"updateBorderTopShow($event)\"\r\n />\r\n @if (styleConfig()[\"border-top-show\"]) {\r\n <mt-color-picker-field\r\n [label]=\"t('borderTopColor')\"\r\n [ngModel]=\"\r\n styleConfig()['border-top-color'] ||\r\n styleConfig()['border-color'] ||\r\n '#3b82f6'\r\n \"\r\n (ngModelChange)=\"updateBorderTopColor($event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Style Configuration -->\r\n @if (shouldShowField(\"cardStyleConfig\")) {\r\n <mt-card [title]=\"t('cardStyle')\">\r\n <div class=\"grid grid-cols-1 gap-5 mb-6\">\r\n <mt-slider-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"cardStyleConfig().borderRadius || 8\"\r\n (ngModelChange)=\"updateCardStyleConfig('borderRadius', $event)\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [step]=\"1\"\r\n unit=\"px\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cardBackgroundColor')\"\r\n [ngModel]=\"cardStyleConfig().backgroundColor || ''\"\r\n (ngModelChange)=\"updateCardStyleConfig('backgroundColor', $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Shadows -->\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"font-medium\">{{ t(\"shadows\") }}</span>\r\n <mt-button\r\n [label]=\"t('addShadow')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addShadow()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n shadow of cardStyleConfig().shadows || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"shadow\") }} {{ i + 1 }}</span\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 (onClick)=\"removeShadow(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-number-field\r\n [label]=\"t('x')\"\r\n [ngModel]=\"shadow.x\"\r\n (ngModelChange)=\"updateShadow(i, 'x', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('y')\"\r\n [ngModel]=\"shadow.y\"\r\n (ngModelChange)=\"updateShadow(i, 'y', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('blur')\"\r\n [ngModel]=\"shadow.blur\"\r\n (ngModelChange)=\"updateShadow(i, 'blur', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('spread')\"\r\n [ngModel]=\"shadow.spread\"\r\n (ngModelChange)=\"updateShadow(i, 'spread', $event)\"\r\n size=\"small\"\r\n />\r\n <div class=\"md:col-span-2\">\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"shadow.color\"\r\n (ngModelChange)=\"updateShadow(i, 'color', $event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Legend Settings -->\r\n @if (shouldShowField(\"legend\")) {\r\n <mt-card [title]=\"t('legendSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLegend')\"\r\n [ngModel]=\"legendConfig().show || false\"\r\n (ngModelChange)=\"updateLegend('show', $event)\"\r\n />\r\n @if (legendConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"legendConfig().position || 'bottom'\"\r\n (ngModelChange)=\"updateLegend('position', $event)\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"legendIconType\")) {\r\n <mt-select-field\r\n [label]=\"t('legendIconType')\"\r\n [ngModel]=\"legendConfig().iconType || 'circle'\"\r\n (ngModelChange)=\"updateLegend('iconType', $event)\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Settings -->\r\n @if (shouldShowField(\"label\")) {\r\n <mt-card [title]=\"t('labelSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabels')\"\r\n [ngModel]=\"labelConfig().show || false\"\r\n (ngModelChange)=\"updateLabel('show', $event)\"\r\n />\r\n @if (labelConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"labelConfig().position || 'inside'\"\r\n (ngModelChange)=\"updateLabel('position', $event)\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"showTotal\")) {\r\n <mt-toggle-field\r\n [label]=\"t('showTotalInTop')\"\r\n [ngModel]=\"labelConfig().showTotalInTop || false\"\r\n (ngModelChange)=\"updateLabel('showTotalInTop', $event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Center (for Pie/Donut charts) -->\r\n @if (shouldShowField(\"labelCenter\")) {\r\n <mt-card [title]=\"t('labelCenter')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideLabelCenter')\"\r\n [ngModel]=\"labelCenterConfig().hide || false\"\r\n (ngModelChange)=\"updateLabelCenterConfig('hide', $event)\"\r\n />\r\n @if (!labelCenterConfig().hide) {\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextEn')\"\r\n [ngModel]=\"labelCenterConfig().text?.en || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('en', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextAr')\"\r\n [ngModel]=\"labelCenterConfig().text?.ar || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('ar', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Override Labels -->\r\n @if (shouldShowField(\"overrideLabels\")) {\r\n <mt-card [title]=\"t('overrideLabels')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"overrideLabelsDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addLabel')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOverrideLabel()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n label of overrideLabels();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"label\") }} {{ i + 1 }}</span\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 (onClick)=\"removeOverrideLabel(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"label.en\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'en', $event)\"\r\n [placeholder]=\"t('enterLabelEn')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"label.ar\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'ar', $event)\"\r\n [placeholder]=\"t('enterLabelAr')\"\r\n dir=\"rtl\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (overrideLabels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOverrideLabels\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Sort Data Bars -->\r\n @if (shouldShowField(\"sortDataBars\")) {\r\n <mt-card [title]=\"t('sortDataBars')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableSorting')\"\r\n [ngModel]=\"sortDataBarsConfig().enable || false\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('enable', $event)\"\r\n />\r\n @if (sortDataBarsConfig().enable) {\r\n <mt-text-field\r\n [label]=\"t('sortBy')\"\r\n [ngModel]=\"sortDataBarsConfig().sortBy || ''\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('sortBy', $event)\"\r\n [placeholder]=\"t('propertyKey')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('order')\"\r\n [ngModel]=\"sortDataBarsConfig().order || 'asc'\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('order', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Default Colors (for charts) -->\r\n @if (shouldShowField(\"defaultColors\")) {\r\n <mt-card [title]=\"t('defaultColors')\">\r\n <div class=\"flex flex-wrap gap-2 mb-4\">\r\n @for (\r\n color of defaultColors();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 p-2 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-color-picker-field\r\n [ngModel]=\"color\"\r\n (ngModelChange)=\"updateDefaultColor(i, $event)\"\r\n />\r\n <mt-button\r\n icon=\"general.x-close\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeDefaultColor(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"flex flex-wrap gap-2 items-center\">\r\n <span class=\"text-sm text-muted-color xl:mr-2\"\r\n >{{ t(\"quickAdd\") }}:</span\r\n >\r\n @for (color of defaultColorPalette; track color) {\r\n <button\r\n type=\"button\"\r\n class=\"w-6 h-6 rounded cursor-pointer border border-surface-300 hover:scale-110 transition-transform\"\r\n [style.background-color]=\"color\"\r\n (click)=\"addDefaultColor(color)\"\r\n [pTooltip]=\"color\"\r\n tooltipPosition=\"top\"\r\n ></button>\r\n }\r\n </div>\r\n\r\n @if (defaultColors().length === 0) {\r\n <div class=\"text-center py-2 text-muted-color text-sm mt-2\">\r\n {{ t(\"noColorsSelected\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Info -->\r\n @if (shouldShowField(\"cardInfo\")) {\r\n <mt-card [title]=\"t('cardInfo')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showCardInfo')\"\r\n [ngModel]=\"cardInfo().show || false\"\r\n (ngModelChange)=\"updateCardInfoConfig('show', $event)\"\r\n />\r\n @if (cardInfo().show) {\r\n <mt-text-field\r\n [label]=\"t('cardInfoValue')\"\r\n [ngModel]=\"cardInfo().value || ''\"\r\n (ngModelChange)=\"updateCardInfoConfig('value', $event)\"\r\n [placeholder]=\"t('enterCardInfoValue')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Settings -->\r\n @if (shouldShowField(\"hideIndex\")) {\r\n <mt-card [title]=\"t('tableSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideIndex')\"\r\n [ngModel]=\"configAsType()['hideIndex'] || false\"\r\n (ngModelChange)=\"updateConfigAsType('hideIndex', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Map Settings -->\r\n @if (shouldShowField(\"mapChart\")) {\r\n <mt-card [title]=\"t('mapSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('mapType')\"\r\n [ngModel]=\"config()?.clientConfig?.['map'] || 'SaudiArabia'\"\r\n (ngModelChange)=\"updateMapType($event)\"\r\n [options]=\"mapOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Format Configuration -->\r\n @if (shouldShowField(\"format\")) {\r\n <mt-card [title]=\"t('formatConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatConfig().type\"\r\n (ngModelChange)=\"updateFormatConfig('type', $event)\"\r\n [options]=\"formatTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n\r\n @if (formatConfig().type === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"formatConfig().showCurrency || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrency', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showCurrencyTooltip')\"\r\n [ngModel]=\"formatConfig().showCurrencyTooltip || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrencyTooltip', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('handleLanguage')\"\r\n [ngModel]=\"formatConfig().handleLang || false\"\r\n (ngModelChange)=\"updateFormatConfig('handleLang', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hideSuffixes')\"\r\n [ngModel]=\"formatConfig().hideSuffixes || false\"\r\n (ngModelChange)=\"updateFormatConfig('hideSuffixes', $event)\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"custom\") {\r\n <mt-text-field\r\n [label]=\"t('customText')\"\r\n [ngModel]=\"formatConfig().customText || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customText', $event)\"\r\n [placeholder]=\"t('enterCustomText')\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"date\") {\r\n <mt-text-field\r\n [label]=\"t('dateFormat')\"\r\n [ngModel]=\"formatConfig().customDateFormat || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customDateFormat', $event)\"\r\n [placeholder]=\"'YYYY-MM-DD'\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Format Configuration -->\r\n @if (shouldShowField(\"tableFormat\")) {\r\n <mt-card [title]=\"t('tableFormatConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Colors -->\r\n <mt-color-picker-field\r\n [label]=\"t('headerTextColor')\"\r\n [ngModel]=\"tableFormatConfig().thTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().thBackgroundColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thBackgroundColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cellTextColor')\"\r\n [ngModel]=\"tableFormatConfig().tdTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().groupBackgroundColor || ''\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('groupBackgroundColor', $event)\r\n \"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupTextColor')\"\r\n [ngModel]=\"tableFormatConfig().groupTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('groupTextColor', $event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Font Settings -->\r\n <mt-toggle-field\r\n [label]=\"t('boldHeaderFont')\"\r\n [ngModel]=\"tableFormatConfig().thFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontBold', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('boldCellFont')\"\r\n [ngModel]=\"tableFormatConfig().tdFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontBold', $event)\"\r\n />\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"headerFontSize\") }}:\r\n {{ tableFormatConfig().thFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().thFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"cellFontSize\") }}:\r\n {{ tableFormatConfig().tdFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().tdFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Options -->\r\n <mt-toggle-field\r\n [label]=\"t('hideTableSubheader')\"\r\n [ngModel]=\"tableFormatConfig().hideTableSubheader || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('hideTableSubheader', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('disableCurrencyFormat')\"\r\n [ngModel]=\"tableFormatConfig().disableCurrencyFormat || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('disableCurrencyFormat', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageAsProgressBar')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageAsProgressBar || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageAsProgressBar', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageStatus')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageStatus || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageStatus', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Sort & Hidden Columns -->\r\n <mt-select-field\r\n [label]=\"t('sortColumn')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.column || ''\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('column', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumn')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('sortDirection')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.direction || 'asc'\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('direction', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenColumns')\"\r\n [ngModel]=\"tableFormatConfig().hiddenColumns || []\"\r\n (ngModelChange)=\"updateTableFormatConfig('hiddenColumns', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumns')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <mt-button\r\n [label]=\"t('resetToDefault')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"resetTableFormat()\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Color By Condition -->\r\n @if (shouldShowField(\"colorByCondition\")) {\r\n <mt-card [title]=\"t('colorByCondition')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"colorByConditionDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('add')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addColorConditionIndex()\"\r\n />\r\n </div>\r\n\r\n @for (barIndex of getColorConditionIndexes(); track barIndex) {\r\n <div class=\"mb-4 border border-surface-200 rounded-lg\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n type=\"button\"\r\n class=\"text-sm text-muted-color\"\r\n (click)=\"toggleColorConditionExpanded(barIndex)\"\r\n >\r\n {{ isColorConditionExpanded(barIndex) ? \"-\" : \"+\" }}\r\n </button>\r\n <span class=\"font-medium text-sm\"\r\n >{{ t(\"bar\") }} {{ barIndex }}</span\r\n >\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n addColorCondition(barIndex); $event.stopPropagation()\r\n \"\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 (onClick)=\"\r\n removeColorConditionIndex(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (isColorConditionExpanded(barIndex)) {\r\n <div class=\"p-3\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-2 mb-3\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ t(\"conditions\") }}</span>\r\n <mt-button\r\n [label]=\"t('addCondition')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addColorCondition(barIndex)\"\r\n />\r\n </div>\r\n\r\n @for (\r\n condition of colorByCondition()[barIndex] || [];\r\n track trackByIndex($index);\r\n let condIndex = $index\r\n ) {\r\n <div class=\"p-3 border border-surface-200 rounded-lg mb-3\">\r\n <div\r\n class=\"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-3 items-end\"\r\n >\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"condition.color\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'color',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('condition')\"\r\n [ngModel]=\"condition.type\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'type',\r\n $event\r\n )\r\n \"\r\n [options]=\"colorConditionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-number-field\r\n [label]=\"\r\n condition.type === 'between' ? t('from') : t('value')\r\n \"\r\n [ngModel]=\"condition.value1\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value1',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n @if (condition.type === \"between\") {\r\n <mt-number-field\r\n [label]=\"t('to')\"\r\n [ngModel]=\"condition.value2\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value2',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\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 (onClick)=\"removeColorCondition(barIndex, condIndex)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3 mt-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"condition.labelEn || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelEn',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"condition.labelAr || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelAr',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((colorByCondition()[barIndex] || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (getColorConditionIndexes().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Timeline Header Colors -->\r\n @if (shouldShowField(\"timelineHeaderColorsConfig\")) {\r\n <mt-card [title]=\"t('timelineHeaderColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().bgColor || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('bgColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().color || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('color', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Ring Gauge Configuration -->\r\n @if (shouldShowField(\"ringGaugeConfig\")) {\r\n <mt-card [title]=\"t('ringGaugeConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('centerProperty')\"\r\n [ngModel]=\"ringGaugeConfig().centerProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('centerProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('statusProperty')\"\r\n [ngModel]=\"ringGaugeConfig().statusProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('statusProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"mt-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenProperties')\"\r\n [ngModel]=\"ringGaugeConfig().hiddenProperties || []\"\r\n (ngModelChange)=\"updateRingGaugeConfig('hiddenProperties', $event)\"\r\n [options]=\"ringGaugeHiddenOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Order Configuration -->\r\n @if (shouldShowField(\"orderConfig\")) {\r\n <mt-card [title]=\"t('orderConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4 mb-4\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n [ngModel]=\"orderConfig().operation || 'deleteNotEqual'\"\r\n (ngModelChange)=\"updateOrderConfig('operation', $event)\"\r\n [options]=\"orderOperationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('orderBy')\"\r\n [ngModel]=\"orderConfig().orderBy || ''\"\r\n (ngModelChange)=\"updateOrderConfig('orderBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"orderConfigurationDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addOrderItem')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOrderItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of orderConfig().order || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 flex flex-col gap-3 rounded-lg border border-surface-200 bg-surface-50 p-4 xl:flex-row xl:items-center\"\r\n >\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n <span class=\"text-sm font-medium w-auto xl:w-8\">{{ i + 1 }}.</span>\r\n <mt-select-field\r\n [ngModel]=\"item\"\r\n (ngModelChange)=\"updateOrderItem(i, $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n class=\"min-w-0 flex-1\"\r\n />\r\n </div>\r\n <div class=\"flex items-center justify-end gap-1\">\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === 0\"\r\n (onClick)=\"moveOrderItemUp(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === (orderConfig().order || []).length - 1\"\r\n (onClick)=\"moveOrderItemDown(i)\"\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 (onClick)=\"removeOrderItem(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((orderConfig().order || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOrderItems\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card List Configuration -->\r\n @if (shouldShowField(\"cardListConfig\")) {\r\n <mt-card [title]=\"t('cardListConfiguration')\">\r\n <mt-multi-select-field\r\n [label]=\"t('hideProperties')\"\r\n [ngModel]=\"cardListConfig().hideProperties || []\"\r\n (ngModelChange)=\"updateCardListHideProperties($event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertiesToHide')\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Props Config As Index -->\r\n @if (shouldShowPropertiesViewSettings()) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n @if (propertiesViewRows().length === 0) {\r\n <div class=\"py-4 text-sm text-muted-color\">\r\n {{ t(\"selectPropertiesFirst\") }}\r\n </div>\r\n } @else {\r\n <div class=\"space-y-4\">\r\n @for (property of propertiesViewRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"property.config.width || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'width', $event)\r\n \"\r\n [placeholder]=\"'100%'\"\r\n size=\"small\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"property.config.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(\r\n property.index,\r\n 'colorAsProperty',\r\n $event\r\n )\r\n \"\r\n [options]=\"selectedPropertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColorProperty')\"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"!!property.config.border\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'border', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hidden')\"\r\n [ngModel]=\"property.config.hidden || false\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'hidden', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Toggle Association -->\r\n @if (shouldShowField(\"toggleAssociation\")) {\r\n <mt-card [title]=\"t('toggleAssociation')\">\r\n <mt-toggle-field\r\n [label]=\"t('enableToggleAssociation')\"\r\n [ngModel]=\"toggleAssociation()\"\r\n (ngModelChange)=\"updateToggleAssociation($event)\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Translations -->\r\n @if (\r\n shouldShowField(\"propertyTranslations\") &&\r\n resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyTranslations')\">\r\n <div class=\"space-y-4\">\r\n @for (property of propertyTranslationRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"property.translation.en\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'en', $event)\r\n \"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"property.translation.ar\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'ar', $event)\r\n \"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (propertyTranslationRows().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Colors -->\r\n @if (\r\n shouldShowField(\"propertyColors\") && resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyColors')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyColors()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyColorsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyColorsPasteText()\"\r\n (ngModelChange)=\"propertyColorsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyColorsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyColorsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyColorsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForColor()\"\r\n (ngModelChange)=\"selectedPropertyForColor.set($event)\"\r\n [options]=\"availableColorOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForColor()\"\r\n (onClick)=\"\r\n addPropertyColor(selectedPropertyForColor());\r\n selectedPropertyForColor.set('')\r\n \"\r\n [pTooltip]=\"t('addProperty')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Property Color List -->\r\n @for (propKey of getPropertyColorKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyColor(propKey)\"\r\n />\r\n </div>\r\n <mt-select-field\r\n [label]=\"t('selectColorProperty')\"\r\n [ngModel]=\"propertyColors()[propKey]?.selectedKey || ''\"\r\n (ngModelChange)=\"updatePropertyColor(propKey, $event)\"\r\n [options]=\"allPropertyKeyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (getPropertyColorKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyColors\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Format X-Axis Configuration -->\r\n @if (shouldShowField(\"formatXAxis\")) {\r\n <mt-card [title]=\"t('formatXAxisConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatXAxisConfig().type\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('type', $event)\"\r\n [options]=\"formatXAxisTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n @if (\r\n formatXAxisConfig().type === \"dateToMonth\" ||\r\n formatXAxisConfig().type === \"month\"\r\n ) {\r\n <mt-toggle-field\r\n [label]=\"t('shortFormat')\"\r\n [ngModel]=\"formatXAxisConfig().shortFormate || false\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('shortFormate', $event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Extra Column From Lookup -->\r\n @if (shouldShowField(\"extraColumnFromLookup\")) {\r\n <mt-card [title]=\"t('extraColumnFromLookup')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableExtraColumnFromLookup')\"\r\n [ngModel]=\"tableColumnsConfig().extraCoulmnFromLookup || false\"\r\n (ngModelChange)=\"\r\n updateTableColumnsConfig('extraCoulmnFromLookup', $event)\r\n \"\r\n />\r\n\r\n @if (tableColumnsConfig().extraCoulmnFromLookup) {\r\n <mt-select-field\r\n [label]=\"t('lookup')\"\r\n [ngModel]=\"tableColumnsConfig().lookupId\"\r\n (ngModelChange)=\"updateTableColumnsConfig('lookupId', $event)\"\r\n [options]=\"lookups()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectLookup')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('groupedBy')\"\r\n [ngModel]=\"tableColumnsConfig().groupedBy\"\r\n (ngModelChange)=\"updateTableColumnsConfig('groupedBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"tableColumnsConfig().propKey\"\r\n (ngModelChange)=\"updateTableColumnsConfig('propKey', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { 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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "required"] }, { 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: IconField, selector: "mt-icon-field", inputs: ["label", "required"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9234
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DisplaySettings, isStandalone: true, selector: "mt-display-settings", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, chartType: { classPropertyName: "chartType", publicName: "chartType", isSignal: true, isRequired: false, transformFunction: null }, availableProperties: { classPropertyName: "availableProperties", publicName: "availableProperties", isSignal: true, isRequired: false, transformFunction: null }, selectedProperties: { classPropertyName: "selectedProperties", publicName: "selectedProperties", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clientConfigChange: "clientConfigChange" }, ngImport: i0, template: "<div class=\"flex flex-col gap-6\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Header Configuration -->\r\n @if (\r\n shouldShowField(\"centerHeader\") || shouldShowField(\"advancedHeaderConfig\")\r\n ) {\r\n <mt-card [title]=\"t('headerConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-5\">\r\n @if (shouldShowField(\"centerHeader\")) {\r\n <mt-toggle-field\r\n [label]=\"t('centerHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderCentered || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderCentered', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"advancedHeaderConfig\")) {\r\n <mt-toggle-field\r\n [label]=\"t('hideHeader')\"\r\n [ngModel]=\"headerCardConfig().isHeaderHidden || false\"\r\n (ngModelChange)=\"updateHeaderCardConfig('isHeaderHidden', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerColor')\"\r\n [ngModel]=\"headerCardConfig().headerColor || ''\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerColor', $event)\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('headerFontSize')\"\r\n [ngModel]=\"headerCardConfig().headerFontSize || 14\"\r\n (ngModelChange)=\"updateHeaderCardConfig('headerFontSize', $event)\"\r\n [min]=\"10\"\r\n [max]=\"48\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Colors Section (for cards) -->\r\n @if (\r\n shouldShowField(\"bgColor\") ||\r\n shouldShowField(\"textColor\") ||\r\n shouldShowField(\"icon\")\r\n ) {\r\n <mt-card [title]=\"t('cardColors')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-5\">\r\n @if (shouldShowField(\"bgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"styleConfig()['background-color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('background-color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"textColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"styleConfig()['color'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('color', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"icon\")) {\r\n <mt-icon-field\r\n [label]=\"t('icon')\"\r\n [ngModel]=\"configAsType()['icon'] || ''\"\r\n (ngModelChange)=\"updateConfigAsType('icon', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconColor')\"\r\n [ngModel]=\"styleConfig()['iconColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"iconBgColor\")) {\r\n <mt-color-picker-field\r\n [label]=\"t('iconBgColor')\"\r\n [ngModel]=\"styleConfig()['iconBgColor'] || ''\"\r\n (ngModelChange)=\"updateStyleConfig('iconBgColor', $event)\"\r\n />\r\n }\r\n @if (shouldShowField(\"positionTitle\")) {\r\n <mt-select-field\r\n [label]=\"t('positionTitle')\"\r\n [ngModel]=\"styleConfig()['justify-content'] || 'start'\"\r\n (ngModelChange)=\"updateStyleConfig('justify-content', $event)\"\r\n [options]=\"positionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Border Top Section -->\r\n @if (shouldShowField(\"borderTop\")) {\r\n <mt-card [title]=\"t('borderTop')\">\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-5\">\r\n <mt-toggle-field\r\n [label]=\"t('showBorderTop')\"\r\n [ngModel]=\"styleConfig()['border-top-show'] || false\"\r\n (ngModelChange)=\"updateBorderTopShow($event)\"\r\n />\r\n @if (styleConfig()[\"border-top-show\"]) {\r\n <mt-color-picker-field\r\n [label]=\"t('borderTopColor')\"\r\n [ngModel]=\"\r\n styleConfig()['border-top-color'] ||\r\n styleConfig()['border-color'] ||\r\n '#3b82f6'\r\n \"\r\n (ngModelChange)=\"updateBorderTopColor($event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Style Configuration -->\r\n @if (shouldShowField(\"cardStyleConfig\")) {\r\n <mt-card [title]=\"t('cardStyle')\">\r\n <div class=\"grid grid-cols-1 gap-5 mb-6\">\r\n <mt-slider-field\r\n [label]=\"t('borderRadius')\"\r\n [ngModel]=\"cardStyleConfig().borderRadius || 8\"\r\n (ngModelChange)=\"updateCardStyleConfig('borderRadius', $event)\"\r\n [min]=\"0\"\r\n [max]=\"24\"\r\n [step]=\"1\"\r\n unit=\"px\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cardBackgroundColor')\"\r\n [ngModel]=\"cardStyleConfig().backgroundColor || ''\"\r\n (ngModelChange)=\"updateCardStyleConfig('backgroundColor', $event)\"\r\n />\r\n </div>\r\n\r\n <!-- Shadows -->\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-3\">\r\n <span class=\"font-medium\">{{ t(\"shadows\") }}</span>\r\n <mt-button\r\n [label]=\"t('addShadow')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addShadow()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n shadow of cardStyleConfig().shadows || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"shadow\") }} {{ i + 1 }}</span\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 (onClick)=\"removeShadow(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-number-field\r\n [label]=\"t('x')\"\r\n [ngModel]=\"shadow.x\"\r\n (ngModelChange)=\"updateShadow(i, 'x', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('y')\"\r\n [ngModel]=\"shadow.y\"\r\n (ngModelChange)=\"updateShadow(i, 'y', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('blur')\"\r\n [ngModel]=\"shadow.blur\"\r\n (ngModelChange)=\"updateShadow(i, 'blur', $event)\"\r\n size=\"small\"\r\n />\r\n <mt-number-field\r\n [label]=\"t('spread')\"\r\n [ngModel]=\"shadow.spread\"\r\n (ngModelChange)=\"updateShadow(i, 'spread', $event)\"\r\n size=\"small\"\r\n />\r\n <div class=\"md:col-span-2\">\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"shadow.color\"\r\n (ngModelChange)=\"updateShadow(i, 'color', $event)\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Legend Settings -->\r\n @if (shouldShowField(\"legend\")) {\r\n <mt-card [title]=\"t('legendSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLegend')\"\r\n [ngModel]=\"legendConfig().show || false\"\r\n (ngModelChange)=\"updateLegend('show', $event)\"\r\n />\r\n @if (legendConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('legendPosition')\"\r\n [ngModel]=\"legendConfig().position || 'bottom'\"\r\n (ngModelChange)=\"updateLegend('position', $event)\"\r\n [options]=\"legendPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"legendIconType\")) {\r\n <mt-select-field\r\n [label]=\"t('legendIconType')\"\r\n [ngModel]=\"legendConfig().iconType || 'circle'\"\r\n (ngModelChange)=\"updateLegend('iconType', $event)\"\r\n [options]=\"legendIconOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Settings -->\r\n @if (shouldShowField(\"label\")) {\r\n <mt-card [title]=\"t('labelSettings')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showLabels')\"\r\n [ngModel]=\"labelConfig().show || false\"\r\n (ngModelChange)=\"updateLabel('show', $event)\"\r\n />\r\n @if (labelConfig().show) {\r\n <mt-select-field\r\n [label]=\"t('labelPosition')\"\r\n [ngModel]=\"labelConfig().position || 'inside'\"\r\n (ngModelChange)=\"updateLabel('position', $event)\"\r\n [options]=\"labelPositionOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n @if (shouldShowField(\"showTotal\")) {\r\n <mt-toggle-field\r\n [label]=\"t('showTotalInTop')\"\r\n [ngModel]=\"labelConfig().showTotalInTop || false\"\r\n (ngModelChange)=\"updateLabel('showTotalInTop', $event)\"\r\n />\r\n }\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Label Center (for Pie/Donut charts) -->\r\n @if (shouldShowField(\"labelCenter\")) {\r\n <mt-card [title]=\"t('labelCenter')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideLabelCenter')\"\r\n [ngModel]=\"labelCenterConfig().hide || false\"\r\n (ngModelChange)=\"updateLabelCenterConfig('hide', $event)\"\r\n />\r\n @if (!labelCenterConfig().hide) {\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextEn')\"\r\n [ngModel]=\"labelCenterConfig().text?.en || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('en', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelCenterTextAr')\"\r\n [ngModel]=\"labelCenterConfig().text?.ar || ''\"\r\n (ngModelChange)=\"updateLabelCenterText('ar', $event)\"\r\n [placeholder]=\"t('enterLabelCenterText')\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Override Labels -->\r\n @if (shouldShowField(\"overrideLabels\")) {\r\n <mt-card [title]=\"t('overrideLabels')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"overrideLabelsDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addLabel')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOverrideLabel()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n label of overrideLabels();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"text-sm font-medium\"\r\n >{{ t(\"label\") }} {{ i + 1 }}</span\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 (onClick)=\"removeOverrideLabel(i)\"\r\n />\r\n </div>\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"label.en\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'en', $event)\"\r\n [placeholder]=\"t('enterLabelEn')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"label.ar\"\r\n (ngModelChange)=\"updateOverrideLabel(i, 'ar', $event)\"\r\n [placeholder]=\"t('enterLabelAr')\"\r\n dir=\"rtl\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (overrideLabels().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOverrideLabels\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Sort Data Bars -->\r\n @if (shouldShowField(\"sortDataBars\")) {\r\n <mt-card [title]=\"t('sortDataBars')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableSorting')\"\r\n [ngModel]=\"sortDataBarsConfig().enable || false\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('enable', $event)\"\r\n />\r\n @if (sortDataBarsConfig().enable) {\r\n <mt-text-field\r\n [label]=\"t('sortBy')\"\r\n [ngModel]=\"sortDataBarsConfig().sortBy || ''\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('sortBy', $event)\"\r\n [placeholder]=\"t('propertyKey')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('order')\"\r\n [ngModel]=\"sortDataBarsConfig().order || 'asc'\"\r\n (ngModelChange)=\"updateSortDataBarsConfig('order', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Default Colors (for charts) -->\r\n @if (shouldShowField(\"defaultColors\")) {\r\n <mt-card [title]=\"t('defaultColors')\">\r\n <div class=\"flex flex-wrap gap-2 mb-4\">\r\n @for (\r\n color of defaultColors();\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 p-2 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-color-picker-field\r\n [ngModel]=\"color\"\r\n (ngModelChange)=\"updateDefaultColor(i, $event)\"\r\n />\r\n <mt-button\r\n icon=\"general.x-close\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removeDefaultColor(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"flex flex-wrap gap-2 items-center\">\r\n <span class=\"text-sm text-muted-color xl:mr-2\"\r\n >{{ t(\"quickAdd\") }}:</span\r\n >\r\n @for (color of defaultColorPalette; track color) {\r\n <button\r\n type=\"button\"\r\n class=\"w-6 h-6 rounded cursor-pointer border border-surface-300 hover:scale-110 transition-transform\"\r\n [style.background-color]=\"color\"\r\n (click)=\"addDefaultColor(color)\"\r\n [pTooltip]=\"color\"\r\n tooltipPosition=\"top\"\r\n ></button>\r\n }\r\n </div>\r\n\r\n @if (defaultColors().length === 0) {\r\n <div class=\"text-center py-2 text-muted-color text-sm mt-2\">\r\n {{ t(\"noColorsSelected\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card Info -->\r\n @if (shouldShowField(\"cardInfo\")) {\r\n <mt-card [title]=\"t('cardInfo')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('showCardInfo')\"\r\n [ngModel]=\"cardInfo().show || false\"\r\n (ngModelChange)=\"updateCardInfoConfig('show', $event)\"\r\n />\r\n @if (cardInfo().show) {\r\n <mt-text-field\r\n [label]=\"t('cardInfoValue')\"\r\n [ngModel]=\"cardInfo().value || ''\"\r\n (ngModelChange)=\"updateCardInfoConfig('value', $event)\"\r\n [placeholder]=\"t('enterCardInfoValue')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Settings -->\r\n @if (shouldShowField(\"hideIndex\")) {\r\n <mt-card [title]=\"t('tableSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('hideIndex')\"\r\n [ngModel]=\"configAsType()['hideIndex'] || false\"\r\n (ngModelChange)=\"updateConfigAsType('hideIndex', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Map Settings -->\r\n @if (shouldShowField(\"mapChart\")) {\r\n <mt-card [title]=\"t('mapSettings')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('mapType')\"\r\n [ngModel]=\"config()?.clientConfig?.['map'] || 'SaudiArabia'\"\r\n (ngModelChange)=\"updateMapType($event)\"\r\n [options]=\"mapOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Format Configuration -->\r\n @if (shouldShowField(\"format\")) {\r\n <mt-card [title]=\"t('formatConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatConfig().type\"\r\n (ngModelChange)=\"updateFormatConfig('type', $event)\"\r\n [options]=\"formatTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n\r\n @if (formatConfig().type === \"currency\") {\r\n <mt-toggle-field\r\n [label]=\"t('showCurrency')\"\r\n [ngModel]=\"formatConfig().showCurrency || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrency', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showCurrencyTooltip')\"\r\n [ngModel]=\"formatConfig().showCurrencyTooltip || false\"\r\n (ngModelChange)=\"updateFormatConfig('showCurrencyTooltip', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('handleLanguage')\"\r\n [ngModel]=\"formatConfig().handleLang || false\"\r\n (ngModelChange)=\"updateFormatConfig('handleLang', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hideSuffixes')\"\r\n [ngModel]=\"formatConfig().hideSuffixes || false\"\r\n (ngModelChange)=\"updateFormatConfig('hideSuffixes', $event)\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"custom\") {\r\n <mt-text-field\r\n [label]=\"t('customText')\"\r\n [ngModel]=\"formatConfig().customText || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customText', $event)\"\r\n [placeholder]=\"t('enterCustomText')\"\r\n />\r\n }\r\n\r\n @if (formatConfig().type === \"date\") {\r\n <mt-text-field\r\n [label]=\"t('dateFormat')\"\r\n [ngModel]=\"formatConfig().customDateFormat || ''\"\r\n (ngModelChange)=\"updateFormatConfig('customDateFormat', $event)\"\r\n [placeholder]=\"'YYYY-MM-DD'\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Table Format Configuration -->\r\n @if (shouldShowField(\"tableFormat\")) {\r\n <mt-card [title]=\"t('tableFormatConfiguration')\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Colors -->\r\n <mt-color-picker-field\r\n [label]=\"t('headerTextColor')\"\r\n [ngModel]=\"tableFormatConfig().thTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('headerBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().thBackgroundColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('thBackgroundColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('cellTextColor')\"\r\n [ngModel]=\"tableFormatConfig().tdTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdTextColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupBackgroundColor')\"\r\n [ngModel]=\"tableFormatConfig().groupBackgroundColor || ''\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('groupBackgroundColor', $event)\r\n \"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('groupTextColor')\"\r\n [ngModel]=\"tableFormatConfig().groupTextColor || ''\"\r\n (ngModelChange)=\"updateTableFormatConfig('groupTextColor', $event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Font Settings -->\r\n <mt-toggle-field\r\n [label]=\"t('boldHeaderFont')\"\r\n [ngModel]=\"tableFormatConfig().thFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontBold', $event)\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('boldCellFont')\"\r\n [ngModel]=\"tableFormatConfig().tdFontBold || false\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontBold', $event)\"\r\n />\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"headerFontSize\") }}:\r\n {{ tableFormatConfig().thFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().thFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('thFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n <div>\r\n <label class=\"block text-sm font-medium mb-2\"\r\n >{{ t(\"cellFontSize\") }}:\r\n {{ tableFormatConfig().tdFontSize || 14 }}px</label\r\n >\r\n <mt-slider-field\r\n [ngModel]=\"tableFormatConfig().tdFontSize || 14\"\r\n (ngModelChange)=\"updateTableFormatConfig('tdFontSize', $event)\"\r\n [min]=\"8\"\r\n [max]=\"32\"\r\n [step]=\"1\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Options -->\r\n <mt-toggle-field\r\n [label]=\"t('hideTableSubheader')\"\r\n [ngModel]=\"tableFormatConfig().hideTableSubheader || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('hideTableSubheader', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('disableCurrencyFormat')\"\r\n [ngModel]=\"tableFormatConfig().disableCurrencyFormat || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('disableCurrencyFormat', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageAsProgressBar')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageAsProgressBar || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageAsProgressBar', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('showPercentageStatus')\"\r\n [ngModel]=\"tableFormatConfig().showPercentageStatus || false\"\r\n (ngModelChange)=\"\r\n updateTableFormatConfig('showPercentageStatus', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <!-- Sort & Hidden Columns -->\r\n <mt-select-field\r\n [label]=\"t('sortColumn')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.column || ''\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('column', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumn')\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('sortDirection')\"\r\n [ngModel]=\"tableFormatConfig().sortConfig?.direction || 'asc'\"\r\n (ngModelChange)=\"updateTableFormatSortConfig('direction', $event)\"\r\n [options]=\"orderTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenColumns')\"\r\n [ngModel]=\"tableFormatConfig().hiddenColumns || []\"\r\n (ngModelChange)=\"updateTableFormatConfig('hiddenColumns', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColumns')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"border-t border-surface-200 pt-4 mt-4\">\r\n <mt-button\r\n [label]=\"t('resetToDefault')\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"resetTableFormat()\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Color By Condition -->\r\n @if (shouldShowField(\"colorByCondition\")) {\r\n <mt-card [title]=\"t('colorByCondition')\">\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"colorByConditionDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('add')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addColorConditionIndex()\"\r\n />\r\n </div>\r\n\r\n @for (barIndex of getColorConditionIndexes(); track barIndex) {\r\n <div class=\"mb-4 border border-surface-200 rounded-lg\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-2 p-3 bg-surface-50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n type=\"button\"\r\n class=\"text-sm text-muted-color\"\r\n (click)=\"toggleColorConditionExpanded(barIndex)\"\r\n >\r\n {{ isColorConditionExpanded(barIndex) ? \"-\" : \"+\" }}\r\n </button>\r\n <span class=\"font-medium text-sm\"\r\n >{{ t(\"bar\") }} {{ barIndex }}</span\r\n >\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"\r\n addColorCondition(barIndex); $event.stopPropagation()\r\n \"\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 (onClick)=\"\r\n removeColorConditionIndex(barIndex); $event.stopPropagation()\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (isColorConditionExpanded(barIndex)) {\r\n <div class=\"p-3\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-2 mb-3\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ t(\"conditions\") }}</span>\r\n <mt-button\r\n [label]=\"t('addCondition')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addColorCondition(barIndex)\"\r\n />\r\n </div>\r\n\r\n @for (\r\n condition of colorByCondition()[barIndex] || [];\r\n track trackByIndex($index);\r\n let condIndex = $index\r\n ) {\r\n <div class=\"p-3 border border-surface-200 rounded-lg mb-3\">\r\n <div\r\n class=\"grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-3 items-end\"\r\n >\r\n <mt-color-picker-field\r\n [label]=\"t('color')\"\r\n [ngModel]=\"condition.color\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'color',\r\n $event\r\n )\r\n \"\r\n />\r\n <mt-select-field\r\n [label]=\"t('condition')\"\r\n [ngModel]=\"condition.type\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'type',\r\n $event\r\n )\r\n \"\r\n [options]=\"colorConditionTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-number-field\r\n [label]=\"\r\n condition.type === 'between' ? t('from') : t('value')\r\n \"\r\n [ngModel]=\"condition.value1\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value1',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n @if (condition.type === \"between\") {\r\n <mt-number-field\r\n [label]=\"t('to')\"\r\n [ngModel]=\"condition.value2\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'value2',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\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 (onClick)=\"removeColorCondition(barIndex, condIndex)\"\r\n />\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-3 mt-3\">\r\n <mt-text-field\r\n [label]=\"t('labelEn')\"\r\n [ngModel]=\"condition.labelEn || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelEn',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('labelAr')\"\r\n [ngModel]=\"condition.labelAr || ''\"\r\n (ngModelChange)=\"\r\n updateColorCondition(\r\n barIndex,\r\n condIndex,\r\n 'labelAr',\r\n $event\r\n )\r\n \"\r\n size=\"small\"\r\n dir=\"rtl\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((colorByCondition()[barIndex] || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (getColorConditionIndexes().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noColorConditions\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Timeline Header Colors -->\r\n @if (shouldShowField(\"timelineHeaderColorsConfig\")) {\r\n <mt-card [title]=\"t('timelineHeaderColors')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-color-picker-field\r\n [label]=\"t('backgroundColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().bgColor || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('bgColor', $event)\"\r\n />\r\n <mt-color-picker-field\r\n [label]=\"t('textColor')\"\r\n [ngModel]=\"timelineHeaderColorsSingle().color || ''\"\r\n (ngModelChange)=\"updateTimelineHeaderColorSingle('color', $event)\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Ring Gauge Configuration -->\r\n @if (shouldShowField(\"ringGaugeConfig\")) {\r\n <mt-card [title]=\"t('ringGaugeConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('centerProperty')\"\r\n [ngModel]=\"ringGaugeConfig().centerProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('centerProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('statusProperty')\"\r\n [ngModel]=\"ringGaugeConfig().statusProperty || ''\"\r\n (ngModelChange)=\"updateRingGaugeConfig('statusProperty', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"mt-4\">\r\n <mt-multi-select-field\r\n [label]=\"t('hiddenProperties')\"\r\n [ngModel]=\"ringGaugeConfig().hiddenProperties || []\"\r\n (ngModelChange)=\"updateRingGaugeConfig('hiddenProperties', $event)\"\r\n [options]=\"ringGaugeHiddenOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Order Configuration -->\r\n @if (shouldShowField(\"orderConfig\")) {\r\n <mt-card [title]=\"t('orderConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4 mb-4\">\r\n <mt-select-field\r\n [label]=\"t('operation')\"\r\n [ngModel]=\"orderConfig().operation || 'deleteNotEqual'\"\r\n (ngModelChange)=\"updateOrderConfig('operation', $event)\"\r\n [options]=\"orderOperationOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('orderBy')\"\r\n [ngModel]=\"orderConfig().orderBy || ''\"\r\n (ngModelChange)=\"updateOrderConfig('orderBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-4\">\r\n <span class=\"text-sm text-muted-color\">{{\r\n t(\"orderConfigurationDescription\")\r\n }}</span>\r\n <mt-button\r\n [label]=\"t('addOrderItem')\"\r\n icon=\"general.plus\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n (onClick)=\"addOrderItem()\"\r\n />\r\n </div>\r\n\r\n @for (\r\n item of orderConfig().order || [];\r\n track trackByIndex($index);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"mb-3 flex flex-col gap-3 rounded-lg border border-surface-200 bg-surface-50 p-4 xl:flex-row xl:items-center\"\r\n >\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n <span class=\"text-sm font-medium w-auto xl:w-8\">{{ i + 1 }}.</span>\r\n <mt-select-field\r\n [ngModel]=\"item\"\r\n (ngModelChange)=\"updateOrderItem(i, $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n class=\"min-w-0 flex-1\"\r\n />\r\n </div>\r\n <div class=\"flex items-center justify-end gap-1\">\r\n <mt-button\r\n icon=\"general.chevron-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === 0\"\r\n (onClick)=\"moveOrderItemUp(i)\"\r\n />\r\n <mt-button\r\n icon=\"general.chevron-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"i === (orderConfig().order || []).length - 1\"\r\n (onClick)=\"moveOrderItemDown(i)\"\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 (onClick)=\"removeOrderItem(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if ((orderConfig().order || []).length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noOrderItems\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Card List Configuration -->\r\n @if (shouldShowField(\"cardListConfig\")) {\r\n <mt-card [title]=\"t('cardListConfiguration')\">\r\n <mt-multi-select-field\r\n [label]=\"t('hideProperties')\"\r\n [ngModel]=\"cardListConfig().hideProperties || []\"\r\n (ngModelChange)=\"updateCardListHideProperties($event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectPropertiesToHide')\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Props Config As Index -->\r\n @if (shouldShowPropertiesViewSettings()) {\r\n <mt-card [title]=\"t('entityPreviewSettings')\">\r\n @if (propertiesViewRows().length === 0) {\r\n <div class=\"py-4 text-sm text-muted-color\">\r\n {{ t(\"selectPropertiesFirst\") }}\r\n </div>\r\n } @else {\r\n <div class=\"space-y-4\">\r\n @for (property of propertiesViewRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('width')\"\r\n [ngModel]=\"property.config.width || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'width', $event)\r\n \"\r\n [placeholder]=\"'100%'\"\r\n size=\"small\"\r\n />\r\n <mt-select-field\r\n [label]=\"t('colorProperty')\"\r\n [ngModel]=\"property.config.colorAsProperty || ''\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(\r\n property.index,\r\n 'colorAsProperty',\r\n $event\r\n )\r\n \"\r\n [options]=\"selectedPropertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectColorProperty')\"\r\n [showClear]=\"true\"\r\n [filter]=\"true\"\r\n size=\"small\"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('border')\"\r\n [ngModel]=\"!!property.config.border\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'border', $event)\r\n \"\r\n />\r\n <mt-toggle-field\r\n [label]=\"t('hidden')\"\r\n [ngModel]=\"property.config.hidden || false\"\r\n (ngModelChange)=\"\r\n updatePropsConfigItem(property.index, 'hidden', $event)\r\n \"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Toggle Association -->\r\n @if (shouldShowField(\"toggleAssociation\")) {\r\n <mt-card [title]=\"t('toggleAssociation')\">\r\n <mt-toggle-field\r\n [label]=\"t('enableToggleAssociation')\"\r\n [ngModel]=\"toggleAssociation()\"\r\n (ngModelChange)=\"updateToggleAssociation($event)\"\r\n />\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Translations -->\r\n @if (\r\n shouldShowField(\"propertyTranslations\") &&\r\n resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyTranslations')\">\r\n <div class=\"space-y-4\">\r\n @for (property of propertyTranslationRows(); track property.key) {\r\n <div class=\"rounded-xl border border-surface-200 bg-surface-50 p-5\">\r\n <div class=\"mb-4\">\r\n <div class=\"text-sm font-semibold text-surface-900\">\r\n {{ property.label }}\r\n </div>\r\n @if (property.label !== property.key) {\r\n <div class=\"mt-1 text-xs text-muted-color\">\r\n {{ property.key }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-text-field\r\n [label]=\"t('englishLabel')\"\r\n [ngModel]=\"property.translation.en\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'en', $event)\r\n \"\r\n [placeholder]=\"t('enterEnglishLabel')\"\r\n size=\"small\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('arabicLabel')\"\r\n [ngModel]=\"property.translation.ar\"\r\n (ngModelChange)=\"\r\n updatePropertyTranslation(property.key, 'ar', $event)\r\n \"\r\n [placeholder]=\"t('enterArabicLabel')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (propertyTranslationRows().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyTranslations\") }}\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Property Colors -->\r\n @if (\r\n shouldShowField(\"propertyColors\") && resolvedSelectedProperties().length > 0\r\n ) {\r\n <mt-card [title]=\"t('propertyColors')\">\r\n <ng-template #cardEnd>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"general.copy-01\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"copyPropertyColors()\"\r\n [pTooltip]=\"t('copyConfig')\"\r\n />\r\n <mt-button\r\n icon=\"general.clipboard\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n [pTooltip]=\"t('pasteConfig')\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n @if (showPropertyColorsPaste()) {\r\n <div\r\n class=\"mb-4 p-4 bg-surface-50 rounded-lg border border-surface-200\"\r\n >\r\n <mt-textarea-field\r\n [label]=\"t('pasteConfiguration')\"\r\n [ngModel]=\"propertyColorsPasteText()\"\r\n (ngModelChange)=\"propertyColorsPasteText.set($event)\"\r\n [placeholder]=\"t('pasteConfigurationPlaceholder')\"\r\n [rows]=\"4\"\r\n />\r\n @if (propertyColorsPasteError()) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n propertyColorsPasteError()\r\n }}</small>\r\n }\r\n <div class=\"flex justify-end gap-2 mt-3\">\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n (onClick)=\"togglePropertyColorsPaste()\"\r\n />\r\n <mt-button\r\n [label]=\"t('apply')\"\r\n size=\"small\"\r\n (onClick)=\"applyPropertyColorsPaste()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Property Selection -->\r\n <div class=\"mb-4\">\r\n <div class=\"flex flex-wrap items-end gap-2 xl:flex-nowrap\">\r\n <div class=\"flex-1\">\r\n <mt-select-field\r\n [label]=\"t('selectProperty')\"\r\n [ngModel]=\"selectedPropertyForColor()\"\r\n (ngModelChange)=\"selectedPropertyForColor.set($event)\"\r\n [options]=\"availableColorOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n [filter]=\"true\"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"!selectedPropertyForColor()\"\r\n (onClick)=\"\r\n addPropertyColor(selectedPropertyForColor());\r\n selectedPropertyForColor.set('')\r\n \"\r\n [pTooltip]=\"t('addProperty')\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- Property Color List -->\r\n @for (propKey of getPropertyColorKeys(); track propKey) {\r\n <div\r\n class=\"mb-3 rounded-lg border border-surface-200 bg-surface-50 p-4\"\r\n >\r\n <div class=\"flex flex-wrap items-center justify-between gap-2 mb-2\">\r\n <span class=\"font-medium text-sm\">{{ propKey }}</span>\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"removePropertyColor(propKey)\"\r\n />\r\n </div>\r\n <mt-select-field\r\n [label]=\"t('selectColorProperty')\"\r\n [ngModel]=\"propertyColors()[propKey]?.selectedKey || ''\"\r\n (ngModelChange)=\"updatePropertyColor(propKey, $event)\"\r\n [options]=\"allPropertyKeyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n size=\"small\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (getPropertyColorKeys().length === 0) {\r\n <div class=\"text-center py-4 text-muted-color\">\r\n {{ t(\"noPropertyColors\") }}\r\n </div>\r\n }\r\n </mt-card>\r\n }\r\n\r\n <!-- Format X-Axis Configuration -->\r\n @if (shouldShowField(\"formatXAxis\")) {\r\n <mt-card [title]=\"t('formatXAxisConfiguration')\">\r\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('formatType')\"\r\n [ngModel]=\"formatXAxisConfig().type\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('type', $event)\"\r\n [options]=\"formatXAxisTypeOptions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectFormat')\"\r\n />\r\n @if (\r\n formatXAxisConfig().type === \"dateToMonth\" ||\r\n formatXAxisConfig().type === \"month\"\r\n ) {\r\n <mt-toggle-field\r\n [label]=\"t('shortFormat')\"\r\n [ngModel]=\"formatXAxisConfig().shortFormate || false\"\r\n (ngModelChange)=\"updateFormatXAxisConfig('shortFormate', $event)\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\r\n\r\n <!-- Extra Column From Lookup -->\r\n @if (shouldShowField(\"extraColumnFromLookup\")) {\r\n <mt-card [title]=\"t('extraColumnFromLookup')\">\r\n <div class=\"grid grid-cols-1 gap-4\">\r\n <mt-toggle-field\r\n [label]=\"t('enableExtraColumnFromLookup')\"\r\n [ngModel]=\"tableColumnsConfig().extraCoulmnFromLookup || false\"\r\n (ngModelChange)=\"\r\n updateTableColumnsConfig('extraCoulmnFromLookup', $event)\r\n \"\r\n />\r\n\r\n @if (tableColumnsConfig().extraCoulmnFromLookup) {\r\n <mt-select-field\r\n [label]=\"t('lookup')\"\r\n [ngModel]=\"tableColumnsConfig().lookupId\"\r\n (ngModelChange)=\"updateTableColumnsConfig('lookupId', $event)\"\r\n [options]=\"lookups()\"\r\n optionLabel=\"displayName\"\r\n optionValue=\"id\"\r\n [placeholder]=\"t('selectLookup')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('groupedBy')\"\r\n [ngModel]=\"tableColumnsConfig().groupedBy\"\r\n (ngModelChange)=\"updateTableColumnsConfig('groupedBy', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n\r\n <mt-select-field\r\n [label]=\"t('propertyValue')\"\r\n [ngModel]=\"tableColumnsConfig().propKey\"\r\n (ngModelChange)=\"updateTableColumnsConfig('propKey', $event)\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [placeholder]=\"t('selectProperty')\"\r\n />\r\n }\r\n </div>\r\n </mt-card>\r\n }\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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows", "required", "maxLength"] }, { 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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "required"] }, { 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: IconField, selector: "mt-icon-field", inputs: ["label", "required"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9118
9235
|
}
|
|
9119
9236
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DisplaySettings, decorators: [{
|
|
9120
9237
|
type: Component,
|
|
@@ -9337,7 +9454,7 @@ class PieControlUi {
|
|
|
9337
9454
|
useExisting: forwardRef(() => PieControlUi),
|
|
9338
9455
|
multi: true,
|
|
9339
9456
|
},
|
|
9340
|
-
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\n>\n <!-- Basic Chart Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"pieSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('radius')\"\n [ngModel]=\"config().radius\"\n (ngModelChange)=\"updateConfig({ radius: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('thickness')\"\n [ngModel]=\"config().thickness\"\n (ngModelChange)=\"updateConfig({ thickness: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('padAngle')\"\n [ngModel]=\"config().padAngle\"\n (ngModelChange)=\"updateConfig({ padAngle: $event })\"\n [min]=\"0\"\n [max]=\"20\"\n />\n\n <mt-number-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n [min]=\"0\"\n [max]=\"50\"\n />\n\n <mt-number-field\n [label]=\"t('centerX')\"\n [ngModel]=\"config().centerX\"\n (ngModelChange)=\"updateConfig({ centerX: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('centerY')\"\n [ngModel]=\"config().centerY\"\n (ngModelChange)=\"updateConfig({ centerY: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('startAngle')\"\n [ngModel]=\"config().startAngle\"\n (ngModelChange)=\"updateConfig({ startAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-number-field\n [label]=\"t('endAngle')\"\n [ngModel]=\"config().endAngle\"\n (ngModelChange)=\"updateConfig({ endAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-select-field\n [label]=\"t('roseType')\"\n [ngModel]=\"config().roseType\"\n (ngModelChange)=\"updateConfig({ roseType: $event })\"\n [options]=\"roseTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Legend Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"legendSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('useEnhancedLegend')\"\n [ngModel]=\"config().useEnhancedLegend\"\n (ngModelChange)=\"updateConfig({ useEnhancedLegend: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('legendPosition')\"\n [ngModel]=\"config().legendPosition\"\n (ngModelChange)=\"updateConfig({ legendPosition: $event })\"\n [options]=\"legendPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendVerticalAlign')\"\n [ngModel]=\"config().legendVerticalAlign\"\n (ngModelChange)=\"updateConfig({ legendVerticalAlign: $event })\"\n [options]=\"legendVerticalAlignOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendOrientation')\"\n [ngModel]=\"config().legendOrientation\"\n (ngModelChange)=\"updateConfig({ legendOrientation: $event })\"\n [options]=\"legendOrientationOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendType')\"\n [ngModel]=\"config().legendType\"\n (ngModelChange)=\"updateConfig({ legendType: $event })\"\n [options]=\"legendTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendFontSize')\"\n [ngModel]=\"config().legendFontSize\"\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('legendFontColor')\"\n [ngModel]=\"config().legendFontColor\"\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('legendIcon')\"\n [ngModel]=\"config().legendIcon\"\n (ngModelChange)=\"updateConfig({ legendIcon: $event })\"\n [options]=\"legendIconOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('totalValueFontSize')\"\n [ngModel]=\"config().totalValueFontSize\"\n (ngModelChange)=\"updateConfig({ totalValueFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('showLabelLine')\"\n [ngModel]=\"config().showLabelLine\"\n (ngModelChange)=\"updateConfig({ showLabelLine: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n\n <!-- Animation Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"animationSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('animation')\"\n [ngModel]=\"config().animation\"\n (ngModelChange)=\"updateConfig({ animation: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('animationDuration')\"\n [ngModel]=\"config().animationDuration\"\n (ngModelChange)=\"updateConfig({ animationDuration: $event })\"\n [min]=\"0\"\n [max]=\"5000\"\n />\n\n <mt-toggle-field\n [label]=\"t('explode')\"\n [ngModel]=\"config().explode\"\n (ngModelChange)=\"updateConfig({ explode: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n</div>\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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
|
|
9457
|
+
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\n>\n <!-- Basic Chart Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"pieSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('radius')\"\n [ngModel]=\"config().radius\"\n (ngModelChange)=\"updateConfig({ radius: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('thickness')\"\n [ngModel]=\"config().thickness\"\n (ngModelChange)=\"updateConfig({ thickness: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('padAngle')\"\n [ngModel]=\"config().padAngle\"\n (ngModelChange)=\"updateConfig({ padAngle: $event })\"\n [min]=\"0\"\n [max]=\"20\"\n />\n\n <mt-number-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n [min]=\"0\"\n [max]=\"50\"\n />\n\n <mt-number-field\n [label]=\"t('centerX')\"\n [ngModel]=\"config().centerX\"\n (ngModelChange)=\"updateConfig({ centerX: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('centerY')\"\n [ngModel]=\"config().centerY\"\n (ngModelChange)=\"updateConfig({ centerY: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('startAngle')\"\n [ngModel]=\"config().startAngle\"\n (ngModelChange)=\"updateConfig({ startAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-number-field\n [label]=\"t('endAngle')\"\n [ngModel]=\"config().endAngle\"\n (ngModelChange)=\"updateConfig({ endAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-select-field\n [label]=\"t('roseType')\"\n [ngModel]=\"config().roseType\"\n (ngModelChange)=\"updateConfig({ roseType: $event })\"\n [options]=\"roseTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Legend Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"legendSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('useEnhancedLegend')\"\n [ngModel]=\"config().useEnhancedLegend\"\n (ngModelChange)=\"updateConfig({ useEnhancedLegend: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('legendPosition')\"\n [ngModel]=\"config().legendPosition\"\n (ngModelChange)=\"updateConfig({ legendPosition: $event })\"\n [options]=\"legendPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendVerticalAlign')\"\n [ngModel]=\"config().legendVerticalAlign\"\n (ngModelChange)=\"updateConfig({ legendVerticalAlign: $event })\"\n [options]=\"legendVerticalAlignOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendOrientation')\"\n [ngModel]=\"config().legendOrientation\"\n (ngModelChange)=\"updateConfig({ legendOrientation: $event })\"\n [options]=\"legendOrientationOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendType')\"\n [ngModel]=\"config().legendType\"\n (ngModelChange)=\"updateConfig({ legendType: $event })\"\n [options]=\"legendTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendFontSize')\"\n [ngModel]=\"config().legendFontSize\"\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('legendFontColor')\"\n [ngModel]=\"config().legendFontColor\"\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('legendIcon')\"\n [ngModel]=\"config().legendIcon\"\n (ngModelChange)=\"updateConfig({ legendIcon: $event })\"\n [options]=\"legendIconOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('totalValueFontSize')\"\n [ngModel]=\"config().totalValueFontSize\"\n (ngModelChange)=\"updateConfig({ totalValueFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('showLabelLine')\"\n [ngModel]=\"config().showLabelLine\"\n (ngModelChange)=\"updateConfig({ showLabelLine: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n\n <!-- Animation Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"animationSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('animation')\"\n [ngModel]=\"config().animation\"\n (ngModelChange)=\"updateConfig({ animation: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('animationDuration')\"\n [ngModel]=\"config().animationDuration\"\n (ngModelChange)=\"updateConfig({ animationDuration: $event })\"\n [min]=\"0\"\n [max]=\"5000\"\n />\n\n <mt-toggle-field\n [label]=\"t('explode')\"\n [ngModel]=\"config().explode\"\n (ngModelChange)=\"updateConfig({ explode: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n</div>\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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
|
|
9341
9458
|
}
|
|
9342
9459
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PieControlUi, decorators: [{
|
|
9343
9460
|
type: Component,
|
|
@@ -9355,7 +9472,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
9355
9472
|
useExisting: forwardRef(() => PieControlUi),
|
|
9356
9473
|
multi: true,
|
|
9357
9474
|
},
|
|
9358
|
-
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\n>\n <!-- Basic Chart Settings -->\n <div class=\"
|
|
9475
|
+
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.pie'\"\n>\n <!-- Basic Chart Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"pieSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('radius')\"\n [ngModel]=\"config().radius\"\n (ngModelChange)=\"updateConfig({ radius: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('thickness')\"\n [ngModel]=\"config().thickness\"\n (ngModelChange)=\"updateConfig({ thickness: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('padAngle')\"\n [ngModel]=\"config().padAngle\"\n (ngModelChange)=\"updateConfig({ padAngle: $event })\"\n [min]=\"0\"\n [max]=\"20\"\n />\n\n <mt-number-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n [min]=\"0\"\n [max]=\"50\"\n />\n\n <mt-number-field\n [label]=\"t('centerX')\"\n [ngModel]=\"config().centerX\"\n (ngModelChange)=\"updateConfig({ centerX: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('centerY')\"\n [ngModel]=\"config().centerY\"\n (ngModelChange)=\"updateConfig({ centerY: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('startAngle')\"\n [ngModel]=\"config().startAngle\"\n (ngModelChange)=\"updateConfig({ startAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-number-field\n [label]=\"t('endAngle')\"\n [ngModel]=\"config().endAngle\"\n (ngModelChange)=\"updateConfig({ endAngle: $event })\"\n [min]=\"0\"\n [max]=\"360\"\n />\n\n <mt-select-field\n [label]=\"t('roseType')\"\n [ngModel]=\"config().roseType\"\n (ngModelChange)=\"updateConfig({ roseType: $event })\"\n [options]=\"roseTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Legend Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"legendSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('useEnhancedLegend')\"\n [ngModel]=\"config().useEnhancedLegend\"\n (ngModelChange)=\"updateConfig({ useEnhancedLegend: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('legendPosition')\"\n [ngModel]=\"config().legendPosition\"\n (ngModelChange)=\"updateConfig({ legendPosition: $event })\"\n [options]=\"legendPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendVerticalAlign')\"\n [ngModel]=\"config().legendVerticalAlign\"\n (ngModelChange)=\"updateConfig({ legendVerticalAlign: $event })\"\n [options]=\"legendVerticalAlignOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendOrientation')\"\n [ngModel]=\"config().legendOrientation\"\n (ngModelChange)=\"updateConfig({ legendOrientation: $event })\"\n [options]=\"legendOrientationOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendType')\"\n [ngModel]=\"config().legendType\"\n (ngModelChange)=\"updateConfig({ legendType: $event })\"\n [options]=\"legendTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendFontSize')\"\n [ngModel]=\"config().legendFontSize\"\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('legendFontColor')\"\n [ngModel]=\"config().legendFontColor\"\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('legendIcon')\"\n [ngModel]=\"config().legendIcon\"\n (ngModelChange)=\"updateConfig({ legendIcon: $event })\"\n [options]=\"legendIconOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('totalValueFontSize')\"\n [ngModel]=\"config().totalValueFontSize\"\n (ngModelChange)=\"updateConfig({ totalValueFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('showLabelLine')\"\n [ngModel]=\"config().showLabelLine\"\n (ngModelChange)=\"updateConfig({ showLabelLine: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n\n <!-- Animation Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"animationSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('animation')\"\n [ngModel]=\"config().animation\"\n (ngModelChange)=\"updateConfig({ animation: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('animationDuration')\"\n [ngModel]=\"config().animationDuration\"\n (ngModelChange)=\"updateConfig({ animationDuration: $event })\"\n [min]=\"0\"\n [max]=\"5000\"\n />\n\n <mt-toggle-field\n [label]=\"t('explode')\"\n [ngModel]=\"config().explode\"\n (ngModelChange)=\"updateConfig({ explode: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n</div>\n" }]
|
|
9359
9476
|
}] });
|
|
9360
9477
|
|
|
9361
9478
|
class BarControlUi {
|
|
@@ -9465,7 +9582,7 @@ class BarControlUi {
|
|
|
9465
9582
|
useExisting: forwardRef(() => BarControlUi),
|
|
9466
9583
|
multi: true,
|
|
9467
9584
|
},
|
|
9468
|
-
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\n>\n <!-- Bar Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"barSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('barWidth')\"\n [ngModel]=\"config().barWidth\"\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-toggle-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('barType')\"\n [ngModel]=\"config().barType\"\n (ngModelChange)=\"updateConfig({ barType: $event })\"\n [options]=\"barTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('isGrouped')\"\n [ngModel]=\"config().isGrouped\"\n (ngModelChange)=\"updateConfig({ isGrouped: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- X-Axis Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"xAxisSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('xAxisShow')\"\n [ngModel]=\"config().xAxisShow\"\n (ngModelChange)=\"updateConfig({ xAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('xAxisFontSize')\"\n [ngModel]=\"config().xAxisFontSize\"\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisFontColor')\"\n [ngModel]=\"config().xAxisFontColor\"\n (ngModelChange)=\"updateConfig({ xAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisLineColor')\"\n [ngModel]=\"config().xAxisLineColor\"\n (ngModelChange)=\"updateConfig({ xAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Y-Axis Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"yAxisSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('yAxisShow')\"\n [ngModel]=\"config().yAxisShow\"\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n @if (config().yAxisShow) {\n <mt-select-field\n [label]=\"t('yAxisFormat')\"\n [ngModel]=\"config().yAxisFormat\"\n (ngModelChange)=\"onYAxisFormatChange($event)\"\n [options]=\"yAxisFormatOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n @if (config().yAxisFormat === \"currency\") {\n <mt-toggle-field\n [label]=\"t('showCurrency')\"\n [ngModel]=\"config().showCurrency\"\n (ngModelChange)=\"updateConfig({ showCurrency: $event })\"\n labelPosition=\"start\"\n />\n }\n }\n\n <mt-select-field\n [label]=\"t('yAxisFontSize')\"\n [ngModel]=\"config().yAxisFontSize\"\n (ngModelChange)=\"updateConfig({ yAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisFontColor')\"\n [ngModel]=\"config().yAxisFontColor\"\n (ngModelChange)=\"updateConfig({ yAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisLineColor')\"\n [ngModel]=\"config().yAxisLineColor\"\n (ngModelChange)=\"updateConfig({ yAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Grid Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"gridSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('gridTop')\"\n [ngModel]=\"config().gridTop\"\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridBottom')\"\n [ngModel]=\"config().gridBottom\"\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridLeft')\"\n [ngModel]=\"config().gridLeft\"\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridRight')\"\n [ngModel]=\"config().gridRight\"\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('labelShow')\"\n [ngModel]=\"config().labelShow\"\n (ngModelChange)=\"updateConfig({ labelShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"rounded-xl border border-surface-200 bg-surface-0 p-4\">\n <h4 class=\"mb-4 text-sm font-semibold text-color\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('tooltipShow')\"\n [ngModel]=\"config().tooltipShow\"\n (ngModelChange)=\"updateConfig({ tooltipShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-toggle-field\n [label]=\"t('showValueOnlyInTooltip')\"\n [ngModel]=\"config().showValueOnlyInTooltip\"\n (ngModelChange)=\"updateConfig({ showValueOnlyInTooltip: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('maxCharsPerLine')\"\n [ngModel]=\"config().maxCharsPerLine\"\n (ngModelChange)=\"updateConfig({ maxCharsPerLine: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n</div>\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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
|
|
9585
|
+
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\n>\n <!-- Bar Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"barSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('barWidth')\"\n [ngModel]=\"config().barWidth\"\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-toggle-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('barType')\"\n [ngModel]=\"config().barType\"\n (ngModelChange)=\"updateConfig({ barType: $event })\"\n [options]=\"barTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('isGrouped')\"\n [ngModel]=\"config().isGrouped\"\n (ngModelChange)=\"updateConfig({ isGrouped: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- X-Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"xAxisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('xAxisShow')\"\n [ngModel]=\"config().xAxisShow\"\n (ngModelChange)=\"updateConfig({ xAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('xAxisFontSize')\"\n [ngModel]=\"config().xAxisFontSize\"\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisFontColor')\"\n [ngModel]=\"config().xAxisFontColor\"\n (ngModelChange)=\"updateConfig({ xAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisLineColor')\"\n [ngModel]=\"config().xAxisLineColor\"\n (ngModelChange)=\"updateConfig({ xAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Y-Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"yAxisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('yAxisShow')\"\n [ngModel]=\"config().yAxisShow\"\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n @if (config().yAxisShow) {\n <mt-select-field\n [label]=\"t('yAxisFormat')\"\n [ngModel]=\"config().yAxisFormat\"\n (ngModelChange)=\"onYAxisFormatChange($event)\"\n [options]=\"yAxisFormatOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n @if (config().yAxisFormat === \"currency\") {\n <mt-toggle-field\n [label]=\"t('showCurrency')\"\n [ngModel]=\"config().showCurrency\"\n (ngModelChange)=\"updateConfig({ showCurrency: $event })\"\n labelPosition=\"start\"\n />\n }\n }\n\n <mt-select-field\n [label]=\"t('yAxisFontSize')\"\n [ngModel]=\"config().yAxisFontSize\"\n (ngModelChange)=\"updateConfig({ yAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisFontColor')\"\n [ngModel]=\"config().yAxisFontColor\"\n (ngModelChange)=\"updateConfig({ yAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisLineColor')\"\n [ngModel]=\"config().yAxisLineColor\"\n (ngModelChange)=\"updateConfig({ yAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Grid Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"gridSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('gridTop')\"\n [ngModel]=\"config().gridTop\"\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridBottom')\"\n [ngModel]=\"config().gridBottom\"\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridLeft')\"\n [ngModel]=\"config().gridLeft\"\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridRight')\"\n [ngModel]=\"config().gridRight\"\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('labelShow')\"\n [ngModel]=\"config().labelShow\"\n (ngModelChange)=\"updateConfig({ labelShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('tooltipShow')\"\n [ngModel]=\"config().tooltipShow\"\n (ngModelChange)=\"updateConfig({ tooltipShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-toggle-field\n [label]=\"t('showValueOnlyInTooltip')\"\n [ngModel]=\"config().showValueOnlyInTooltip\"\n (ngModelChange)=\"updateConfig({ showValueOnlyInTooltip: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('maxCharsPerLine')\"\n [ngModel]=\"config().maxCharsPerLine\"\n (ngModelChange)=\"updateConfig({ maxCharsPerLine: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n</div>\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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
|
|
9469
9586
|
}
|
|
9470
9587
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: BarControlUi, decorators: [{
|
|
9471
9588
|
type: Component,
|
|
@@ -9483,7 +9600,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
9483
9600
|
useExisting: forwardRef(() => BarControlUi),
|
|
9484
9601
|
multi: true,
|
|
9485
9602
|
},
|
|
9486
|
-
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\n>\n <!-- Bar Settings -->\n <div class=\"
|
|
9603
|
+
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.bar'\"\n>\n <!-- Bar Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"barSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('barWidth')\"\n [ngModel]=\"config().barWidth\"\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-toggle-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('barType')\"\n [ngModel]=\"config().barType\"\n (ngModelChange)=\"updateConfig({ barType: $event })\"\n [options]=\"barTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-toggle-field\n [label]=\"t('isGrouped')\"\n [ngModel]=\"config().isGrouped\"\n (ngModelChange)=\"updateConfig({ isGrouped: $event })\"\n labelPosition=\"start\"\n />\n </div>\n </div>\n\n <!-- X-Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"xAxisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('xAxisShow')\"\n [ngModel]=\"config().xAxisShow\"\n (ngModelChange)=\"updateConfig({ xAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('xAxisFontSize')\"\n [ngModel]=\"config().xAxisFontSize\"\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisFontColor')\"\n [ngModel]=\"config().xAxisFontColor\"\n (ngModelChange)=\"updateConfig({ xAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('xAxisLineColor')\"\n [ngModel]=\"config().xAxisLineColor\"\n (ngModelChange)=\"updateConfig({ xAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Y-Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"yAxisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('yAxisShow')\"\n [ngModel]=\"config().yAxisShow\"\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n @if (config().yAxisShow) {\n <mt-select-field\n [label]=\"t('yAxisFormat')\"\n [ngModel]=\"config().yAxisFormat\"\n (ngModelChange)=\"onYAxisFormatChange($event)\"\n [options]=\"yAxisFormatOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n @if (config().yAxisFormat === \"currency\") {\n <mt-toggle-field\n [label]=\"t('showCurrency')\"\n [ngModel]=\"config().showCurrency\"\n (ngModelChange)=\"updateConfig({ showCurrency: $event })\"\n labelPosition=\"start\"\n />\n }\n }\n\n <mt-select-field\n [label]=\"t('yAxisFontSize')\"\n [ngModel]=\"config().yAxisFontSize\"\n (ngModelChange)=\"updateConfig({ yAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisFontColor')\"\n [ngModel]=\"config().yAxisFontColor\"\n (ngModelChange)=\"updateConfig({ yAxisFontColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('yAxisLineColor')\"\n [ngModel]=\"config().yAxisLineColor\"\n (ngModelChange)=\"updateConfig({ yAxisLineColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Grid Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"gridSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('gridTop')\"\n [ngModel]=\"config().gridTop\"\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridBottom')\"\n [ngModel]=\"config().gridBottom\"\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridLeft')\"\n [ngModel]=\"config().gridLeft\"\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridRight')\"\n [ngModel]=\"config().gridRight\"\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('labelShow')\"\n [ngModel]=\"config().labelShow\"\n (ngModelChange)=\"updateConfig({ labelShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('labelPosition')\"\n [ngModel]=\"config().labelPosition\"\n (ngModelChange)=\"updateConfig({ labelPosition: $event })\"\n [options]=\"labelPositionOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n\n <mt-select-field\n [label]=\"t('labelFormatter')\"\n [ngModel]=\"config().labelFormatter\"\n (ngModelChange)=\"updateConfig({ labelFormatter: $event })\"\n [options]=\"labelFormatterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('tooltipShow')\"\n [ngModel]=\"config().tooltipShow\"\n (ngModelChange)=\"updateConfig({ tooltipShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-toggle-field\n [label]=\"t('showValueOnlyInTooltip')\"\n [ngModel]=\"config().showValueOnlyInTooltip\"\n (ngModelChange)=\"updateConfig({ showValueOnlyInTooltip: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-number-field\n [label]=\"t('maxCharsPerLine')\"\n [ngModel]=\"config().maxCharsPerLine\"\n (ngModelChange)=\"updateConfig({ maxCharsPerLine: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-select-field\n [label]=\"t('tooltipTrigger')\"\n [ngModel]=\"config().tooltipTrigger\"\n (ngModelChange)=\"updateConfig({ tooltipTrigger: $event })\"\n [options]=\"tooltipTriggerOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n</div>\n" }]
|
|
9487
9604
|
}] });
|
|
9488
9605
|
|
|
9489
9606
|
class StackBarControlUi {
|
|
@@ -9576,7 +9693,7 @@ class StackBarControlUi {
|
|
|
9576
9693
|
useExisting: forwardRef(() => StackBarControlUi),
|
|
9577
9694
|
multi: true,
|
|
9578
9695
|
},
|
|
9579
|
-
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\n>\n <!-- Bar Settings -->\n <div class=\"
|
|
9696
|
+
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\n>\n <!-- Bar Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"barSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('isStacked')\"\n [ngModel]=\"config().isStacked\"\n (ngModelChange)=\"updateConfig({ isStacked: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-toggle-field\n [label]=\"t('hasLines')\"\n [ngModel]=\"config().hasLines\"\n (ngModelChange)=\"updateConfig({ hasLines: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('barType')\"\n [ngModel]=\"config().barType\"\n (ngModelChange)=\"updateConfig({ barType: $event })\"\n [options]=\"barTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-number-field\n [label]=\"t('barWidth')\"\n [ngModel]=\"config().barWidth\"\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Grid Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"gridSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('gridLeft')\"\n [ngModel]=\"config().gridLeft\"\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridRight')\"\n [ngModel]=\"config().gridRight\"\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridTop')\"\n [ngModel]=\"config().gridTop\"\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridBottom')\"\n [ngModel]=\"config().gridBottom\"\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"axisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('yAxisShow')\"\n [ngModel]=\"config().yAxisShow\"\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('yAxisFormat')\"\n [ngModel]=\"config().yAxisFormat?.type\"\n (ngModelChange)=\"onYAxisFormatChange($event)\"\n [options]=\"yAxisFormatOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-number-field\n [label]=\"t('xAxisLabelRotate')\"\n [ngModel]=\"config().xAxisLabelRotate\"\n (ngModelChange)=\"updateConfig({ xAxisLabelRotate: $event })\"\n [min]=\"-90\"\n [max]=\"90\"\n />\n\n <mt-select-field\n [label]=\"t('xAxisFontSize')\"\n [ngModel]=\"config().xAxisFontSize\"\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Legend Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"legendSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('legendPositionY')\"\n [ngModel]=\"config().legendPositionY\"\n (ngModelChange)=\"updateConfig({ legendPositionY: $event })\"\n [options]=\"legendPositionYOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendPositionX')\"\n [ngModel]=\"config().legendPositionX\"\n (ngModelChange)=\"updateConfig({ legendPositionX: $event })\"\n [options]=\"legendPositionXOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendFontSize')\"\n [ngModel]=\"config().legendFontSize\"\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('legendFontColor')\"\n [ngModel]=\"config().legendFontColor\"\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('showLabel')\"\n [ngModel]=\"config().showLabel\"\n (ngModelChange)=\"updateConfig({ showLabel: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n</div>\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: 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }] });
|
|
9580
9697
|
}
|
|
9581
9698
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StackBarControlUi, decorators: [{
|
|
9582
9699
|
type: Component,
|
|
@@ -9594,7 +9711,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
9594
9711
|
useExisting: forwardRef(() => StackBarControlUi),
|
|
9595
9712
|
multi: true,
|
|
9596
9713
|
},
|
|
9597
|
-
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\n>\n <!-- Bar Settings -->\n <div class=\"
|
|
9714
|
+
], template: "<div\n class=\"flex flex-col gap-5\"\n *transloco=\"let t; prefix: 'dashboardBuilder.chartControls.stackBar'\"\n>\n <!-- Bar Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"barSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('isStacked')\"\n [ngModel]=\"config().isStacked\"\n (ngModelChange)=\"updateConfig({ isStacked: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-toggle-field\n [label]=\"t('hasLines')\"\n [ngModel]=\"config().hasLines\"\n (ngModelChange)=\"updateConfig({ hasLines: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('barType')\"\n [ngModel]=\"config().barType\"\n (ngModelChange)=\"updateConfig({ barType: $event })\"\n [options]=\"barTypeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-number-field\n [label]=\"t('barWidth')\"\n [ngModel]=\"config().barWidth\"\n (ngModelChange)=\"updateConfig({ barWidth: $event })\"\n [min]=\"10\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('borderRadius')\"\n [ngModel]=\"config().borderRadius\"\n (ngModelChange)=\"updateConfig({ borderRadius: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Grid Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"gridSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-number-field\n [label]=\"t('gridLeft')\"\n [ngModel]=\"config().gridLeft\"\n (ngModelChange)=\"updateConfig({ gridLeft: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridRight')\"\n [ngModel]=\"config().gridRight\"\n (ngModelChange)=\"updateConfig({ gridRight: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridTop')\"\n [ngModel]=\"config().gridTop\"\n (ngModelChange)=\"updateConfig({ gridTop: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n\n <mt-number-field\n [label]=\"t('gridBottom')\"\n [ngModel]=\"config().gridBottom\"\n (ngModelChange)=\"updateConfig({ gridBottom: $event })\"\n [min]=\"0\"\n [max]=\"100\"\n />\n </div>\n </div>\n\n <!-- Axis Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"axisSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('yAxisShow')\"\n [ngModel]=\"config().yAxisShow\"\n (ngModelChange)=\"updateConfig({ yAxisShow: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('yAxisFormat')\"\n [ngModel]=\"config().yAxisFormat?.type\"\n (ngModelChange)=\"onYAxisFormatChange($event)\"\n [options]=\"yAxisFormatOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-number-field\n [label]=\"t('xAxisLabelRotate')\"\n [ngModel]=\"config().xAxisLabelRotate\"\n (ngModelChange)=\"updateConfig({ xAxisLabelRotate: $event })\"\n [min]=\"-90\"\n [max]=\"90\"\n />\n\n <mt-select-field\n [label]=\"t('xAxisFontSize')\"\n [ngModel]=\"config().xAxisFontSize\"\n (ngModelChange)=\"updateConfig({ xAxisFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n </div>\n\n <!-- Legend Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"legendSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-select-field\n [label]=\"t('legendPositionY')\"\n [ngModel]=\"config().legendPositionY\"\n (ngModelChange)=\"updateConfig({ legendPositionY: $event })\"\n [options]=\"legendPositionYOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendPositionX')\"\n [ngModel]=\"config().legendPositionX\"\n (ngModelChange)=\"updateConfig({ legendPositionX: $event })\"\n [options]=\"legendPositionXOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-select-field\n [label]=\"t('legendFontSize')\"\n [ngModel]=\"config().legendFontSize\"\n (ngModelChange)=\"updateConfig({ legendFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('legendFontColor')\"\n [ngModel]=\"config().legendFontColor\"\n (ngModelChange)=\"updateConfig({ legendFontColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Label Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"labelSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-toggle-field\n [label]=\"t('showLabel')\"\n [ngModel]=\"config().showLabel\"\n (ngModelChange)=\"updateConfig({ showLabel: $event })\"\n labelPosition=\"start\"\n />\n\n <mt-select-field\n [label]=\"t('labelFontSize')\"\n [ngModel]=\"config().labelFontSize\"\n (ngModelChange)=\"updateConfig({ labelFontSize: $event })\"\n [options]=\"fontSizeOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n\n <mt-color-picker-field\n [label]=\"t('labelFontColor')\"\n [ngModel]=\"config().labelFontColor\"\n (ngModelChange)=\"updateConfig({ labelFontColor: $event })\"\n />\n </div>\n </div>\n\n <!-- Tooltip Settings -->\n <div class=\"db-control-section\">\n <h4 class=\"db-control-section__header\">\n {{ t(\"tooltipSettings\") }}\n </h4>\n\n <div class=\"db-control-section__body flex flex-col gap-4\">\n <mt-color-picker-field\n [label]=\"t('tooltipBackgroundColor')\"\n [ngModel]=\"config().tooltipBackgroundColor\"\n (ngModelChange)=\"updateConfig({ tooltipBackgroundColor: $event })\"\n />\n\n <mt-color-picker-field\n [label]=\"t('tooltipBorderColor')\"\n [ngModel]=\"config().tooltipBorderColor\"\n (ngModelChange)=\"updateConfig({ tooltipBorderColor: $event })\"\n />\n\n <mt-number-field\n [label]=\"t('tooltipBorderWidth')\"\n [ngModel]=\"config().tooltipBorderWidth\"\n (ngModelChange)=\"updateConfig({ tooltipBorderWidth: $event })\"\n [min]=\"0\"\n [max]=\"10\"\n />\n </div>\n </div>\n</div>\n" }]
|
|
9598
9715
|
}] });
|
|
9599
9716
|
|
|
9600
9717
|
/**
|
|
@@ -11281,7 +11398,7 @@ class SchemaControlRendererComponent {
|
|
|
11281
11398
|
</section>
|
|
11282
11399
|
}
|
|
11283
11400
|
</div>
|
|
11284
|
-
`, isInline: true, styles: [".db-schema-controls{display:flex;flex-direction:column;gap:1rem}.db-schema-section{display:flex;flex-direction:column;gap
|
|
11401
|
+
`, isInline: true, styles: [".db-schema-controls{display:flex;flex-direction:column;gap:1rem}.db-schema-section{display:flex;flex-direction:column;gap:0;overflow:hidden;background:var(--p-surface-0, #fff);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.375rem}.db-schema-section__header{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-schema-section__header i{color:var(--p-primary-500, #3b82f6)}.db-schema-section__title{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #1f2937)}.db-schema-section__hint{margin:0;padding:.75rem 1rem 0;font-size:.75rem;color:var(--p-text-muted-color, #6b7280)}.db-schema-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));padding:1rem;gap:.5rem 1rem}.db-schema-field{display:flex;flex-direction:column;gap:.25rem;font-size:.75rem}.db-schema-field__label{font-weight:500;color:var(--p-text-color, #1f2937);display:inline-flex;gap:.25rem}.db-schema-field__required{color:var(--p-red-500, #ef4444)}.db-schema-field__input,.db-schema-field__select,.db-schema-field__textarea,.db-schema-field__json{font-size:.8rem;padding:.35rem .5rem;border-radius:.375rem;border:1px solid var(--p-surface-300, #d1d5db);background:var(--p-surface-0, #fff)}.db-schema-field__color{width:3rem;height:1.75rem;padding:0;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.375rem;background:transparent}.db-schema-field__json{font-family:ui-monospace,SFMono-Regular,monospace}.db-schema-field__multiselect{display:flex;flex-wrap:wrap;gap:.5rem}.db-schema-field__multiselect-option{display:inline-flex;align-items:center;gap:.25rem}.db-schema-field[data-type=boolean]{flex-direction:row;align-items:center;gap:.5rem}.db-schema-field[data-type=boolean] .db-schema-field__label{order:2}.db-schema-field__hint{color:var(--p-text-muted-color, #6b7280)}.db-schema-field__error{color:var(--p-red-600, #dc2626)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
11285
11402
|
}
|
|
11286
11403
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SchemaControlRendererComponent, decorators: [{
|
|
11287
11404
|
type: Component,
|
|
@@ -11437,7 +11554,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
11437
11554
|
</section>
|
|
11438
11555
|
}
|
|
11439
11556
|
</div>
|
|
11440
|
-
`, styles: [".db-schema-controls{display:flex;flex-direction:column;gap:1rem}.db-schema-section{display:flex;flex-direction:column;gap
|
|
11557
|
+
`, styles: [".db-schema-controls{display:flex;flex-direction:column;gap:1rem}.db-schema-section{display:flex;flex-direction:column;gap:0;overflow:hidden;background:var(--p-surface-0, #fff);border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.375rem}.db-schema-section__header{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-schema-section__header i{color:var(--p-primary-500, #3b82f6)}.db-schema-section__title{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #1f2937)}.db-schema-section__hint{margin:0;padding:.75rem 1rem 0;font-size:.75rem;color:var(--p-text-muted-color, #6b7280)}.db-schema-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));padding:1rem;gap:.5rem 1rem}.db-schema-field{display:flex;flex-direction:column;gap:.25rem;font-size:.75rem}.db-schema-field__label{font-weight:500;color:var(--p-text-color, #1f2937);display:inline-flex;gap:.25rem}.db-schema-field__required{color:var(--p-red-500, #ef4444)}.db-schema-field__input,.db-schema-field__select,.db-schema-field__textarea,.db-schema-field__json{font-size:.8rem;padding:.35rem .5rem;border-radius:.375rem;border:1px solid var(--p-surface-300, #d1d5db);background:var(--p-surface-0, #fff)}.db-schema-field__color{width:3rem;height:1.75rem;padding:0;border:1px solid var(--p-surface-300, #d1d5db);border-radius:.375rem;background:transparent}.db-schema-field__json{font-family:ui-monospace,SFMono-Regular,monospace}.db-schema-field__multiselect{display:flex;flex-wrap:wrap;gap:.5rem}.db-schema-field__multiselect-option{display:inline-flex;align-items:center;gap:.25rem}.db-schema-field[data-type=boolean]{flex-direction:row;align-items:center;gap:.5rem}.db-schema-field[data-type=boolean] .db-schema-field__label{order:2}.db-schema-field__hint{color:var(--p-text-muted-color, #6b7280)}.db-schema-field__error{color:var(--p-red-600, #dc2626)}\n"] }]
|
|
11441
11558
|
}], propDecorators: { schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: true }] }], persisted: [{ type: i0.Input, args: [{ isSignal: true, alias: "persisted", required: true }] }], capability: [{ type: i0.Input, args: [{ isSignal: true, alias: "capability", required: false }] }], scope: [{ type: i0.Input, args: [{ isSignal: true, alias: "scope", required: false }] }], patch: [{ type: i0.Output, args: ["patch"] }] } });
|
|
11442
11559
|
|
|
11443
11560
|
/**
|
|
@@ -11516,8 +11633,11 @@ class EChartComponent {
|
|
|
11516
11633
|
/** Show custom legend */
|
|
11517
11634
|
showCustomLegend = computed(() => {
|
|
11518
11635
|
const item = this.configurationItem();
|
|
11519
|
-
|
|
11520
|
-
|
|
11636
|
+
const legendVisible = item?.clientConfig?.configAsType?.['legend']?.show;
|
|
11637
|
+
if (!legendVisible)
|
|
11638
|
+
return false;
|
|
11639
|
+
return Boolean(item?.clientConfig?.pieConfigOverried?.useEnhancedLegend ||
|
|
11640
|
+
this.hasPieSeries(this.chartOptions()));
|
|
11521
11641
|
}, ...(ngDevMode ? [{ debugName: "showCustomLegend" }] : /* istanbul ignore next */ []));
|
|
11522
11642
|
customLegendIconIsRect = computed(() => {
|
|
11523
11643
|
const iconType = this.configurationItem()?.clientConfig?.configAsType?.['legend']?.['iconType'];
|
|
@@ -11582,6 +11702,14 @@ class EChartComponent {
|
|
|
11582
11702
|
}
|
|
11583
11703
|
this.legendItems.set(legends);
|
|
11584
11704
|
}
|
|
11705
|
+
hasPieSeries(option) {
|
|
11706
|
+
const series = Array.isArray(option?.series)
|
|
11707
|
+
? option.series
|
|
11708
|
+
: option?.series
|
|
11709
|
+
? [option.series]
|
|
11710
|
+
: [];
|
|
11711
|
+
return series.some((item) => item?.type === 'pie');
|
|
11712
|
+
}
|
|
11585
11713
|
/**
|
|
11586
11714
|
* Toggle legend item visibility
|
|
11587
11715
|
*/
|
|
@@ -11801,26 +11929,7 @@ class EChartComponent {
|
|
|
11801
11929
|
const mapped = seriesList.map((series) => {
|
|
11802
11930
|
const type = series?.type;
|
|
11803
11931
|
if (type === 'pie') {
|
|
11804
|
-
return
|
|
11805
|
-
...series,
|
|
11806
|
-
radius: this.getResponsivePieRadius(series.radius, compact, veryCompact),
|
|
11807
|
-
center: series.center,
|
|
11808
|
-
avoidLabelOverlap: series.avoidLabelOverlap ?? true,
|
|
11809
|
-
labelLayout: {
|
|
11810
|
-
...(series.labelLayout || {}),
|
|
11811
|
-
hideOverlap: true,
|
|
11812
|
-
},
|
|
11813
|
-
label: {
|
|
11814
|
-
...(series.label || {}),
|
|
11815
|
-
show: veryCompact ? false : series.label?.show,
|
|
11816
|
-
fontFamily: series.label?.fontFamily ?? fontFamily,
|
|
11817
|
-
fontSize: series.label?.fontSize ?? fontSizes.label,
|
|
11818
|
-
},
|
|
11819
|
-
labelLine: {
|
|
11820
|
-
...(series.labelLine || {}),
|
|
11821
|
-
show: veryCompact ? false : series.labelLine?.show,
|
|
11822
|
-
},
|
|
11823
|
-
};
|
|
11932
|
+
return series;
|
|
11824
11933
|
}
|
|
11825
11934
|
if (type === 'bar' || type === 'line') {
|
|
11826
11935
|
return {
|
|
@@ -12170,14 +12279,6 @@ class EChartComponent {
|
|
|
12170
12279
|
}
|
|
12171
12280
|
return next;
|
|
12172
12281
|
}
|
|
12173
|
-
getResponsivePieRadius(radius, compact, veryCompact) {
|
|
12174
|
-
if (!compact)
|
|
12175
|
-
return radius;
|
|
12176
|
-
if (Array.isArray(radius)) {
|
|
12177
|
-
return veryCompact ? ['40%', '62%'] : ['36%', '66%'];
|
|
12178
|
-
}
|
|
12179
|
-
return veryCompact ? '58%' : '64%';
|
|
12180
|
-
}
|
|
12181
12282
|
estimateCategoryCount(option) {
|
|
12182
12283
|
const xAxis = Array.isArray(option?.xAxis)
|
|
12183
12284
|
? option.xAxis[0]
|
|
@@ -12234,7 +12335,7 @@ class EChartComponent {
|
|
|
12234
12335
|
}
|
|
12235
12336
|
</div>
|
|
12236
12337
|
}
|
|
12237
|
-
`, isInline: true, styles: [":host{display:block;width:100%;height:100%;min-height:0;position:relative}.chart-wrapper{width:100%;height:
|
|
12338
|
+
`, isInline: true, styles: [":host{display:block;width:100%;height:100%;min-height:0;position:relative}.chart-wrapper{width:100%;height:96%;display:flex;justify-content:center;align-items:center;position:relative;min-height:0}.chart-wrapper.in-group-with-header{height:86%}.scroll-wrapper{width:100%;height:96%;overflow-x:auto;overflow-y:hidden;position:relative;min-height:0}.scroll-wrapper.in-group-with-header{height:86%}.chart{width:100%;height:100%;min-height:0}.chart-scroll{width:100%;height:100%;min-height:0;overflow-y:hidden}.custom-legend{position:absolute;bottom:10px;left:0;right:0;z-index:1000;background:transparent;padding:4px 8px;display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:4px;width:100%;max-width:100%}.custom-legend.has-scroll{bottom:25px}.legend-item{display:flex;align-items:center;gap:3px;padding:2px 4px;border-radius:3px;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:11px;white-space:nowrap;background:transparent;line-height:1.2;flex-direction:row}.legend-item:hover{background-color:#0000000d}.legend-item.disabled{opacity:.5}.legend-item.disabled .legend-text{text-decoration:line-through}.legend-icon{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-text{font-family:inherit}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12238
12339
|
}
|
|
12239
12340
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: EChartComponent, decorators: [{
|
|
12240
12341
|
type: Component,
|
|
@@ -12282,7 +12383,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
12282
12383
|
}
|
|
12283
12384
|
</div>
|
|
12284
12385
|
}
|
|
12285
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%;height:100%;min-height:0;position:relative}.chart-wrapper{width:100%;height:
|
|
12386
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%;height:100%;min-height:0;position:relative}.chart-wrapper{width:100%;height:96%;display:flex;justify-content:center;align-items:center;position:relative;min-height:0}.chart-wrapper.in-group-with-header{height:86%}.scroll-wrapper{width:100%;height:96%;overflow-x:auto;overflow-y:hidden;position:relative;min-height:0}.scroll-wrapper.in-group-with-header{height:86%}.chart{width:100%;height:100%;min-height:0}.chart-scroll{width:100%;height:100%;min-height:0;overflow-y:hidden}.custom-legend{position:absolute;bottom:10px;left:0;right:0;z-index:1000;background:transparent;padding:4px 8px;display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:4px;width:100%;max-width:100%}.custom-legend.has-scroll{bottom:25px}.legend-item{display:flex;align-items:center;gap:3px;padding:2px 4px;border-radius:3px;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-size:11px;white-space:nowrap;background:transparent;line-height:1.2;flex-direction:row}.legend-item:hover{background-color:#0000000d}.legend-item.disabled{opacity:.5}.legend-item.disabled .legend-text{text-decoration:line-through}.legend-icon{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-text{font-family:inherit}\n"] }]
|
|
12286
12387
|
}], ctorParameters: () => [], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: false }] }], chartConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartConfig", required: false }] }], configurationItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "configurationItem", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], headerHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerHidden", required: false }] }], chartClick: [{ type: i0.Output, args: ["chartClick"] }] } });
|
|
12287
12388
|
|
|
12288
12389
|
/**
|
|
@@ -15060,6 +15161,8 @@ class PieChartHandler {
|
|
|
15060
15161
|
pieOverride?.outerRadiusPercent ??
|
|
15061
15162
|
undefined;
|
|
15062
15163
|
const labelPosition = this.normalizePieLabelPosition(pieOverride?.labelPosition);
|
|
15164
|
+
const hasCanvasLegend = showLegend && !pieOverride?.useEnhancedLegend;
|
|
15165
|
+
const suppressCanvasSliceLabels = hasCanvasLegend;
|
|
15063
15166
|
// Chart settings
|
|
15064
15167
|
const chartSettings = {
|
|
15065
15168
|
radius: [
|
|
@@ -15071,14 +15174,16 @@ class PieChartHandler {
|
|
|
15071
15174
|
totalValueFontSize: labelInCenter
|
|
15072
15175
|
? pieOverride?.totalValueFontSize || 22
|
|
15073
15176
|
: pieOverride?.totalValueFontSize || 30,
|
|
15074
|
-
labelFormatter: this.resolvePieLabelFormatter(Boolean(displayPercentage), Boolean(isPercentage), pieOverride?.labelFormatter, labelPosition, clientConfig?.['format'], languageCode),
|
|
15177
|
+
labelFormatter: this.resolvePieLabelFormatter(Boolean(displayPercentage), Boolean(isPercentage), pieOverride?.labelFormatter, labelPosition, clientConfig?.['format'], languageCode, hasCanvasLegend),
|
|
15075
15178
|
};
|
|
15076
15179
|
// Build legends
|
|
15077
15180
|
const allLegend = [
|
|
15078
15181
|
{
|
|
15079
|
-
show:
|
|
15182
|
+
show: hasCanvasLegend, // will use custom legend instead
|
|
15080
15183
|
align: languageCode === 'en' ? 'left' : 'right',
|
|
15081
|
-
|
|
15184
|
+
left: 'center',
|
|
15185
|
+
bottom: '3%',
|
|
15186
|
+
orient: 'horizontal',
|
|
15082
15187
|
type: pieOverride?.legendType ||
|
|
15083
15188
|
(seriesData.length > 8 ? 'scroll' : 'plain'),
|
|
15084
15189
|
icon: configAsType?.['legend']?.['iconType'] || 'circle',
|
|
@@ -15121,7 +15226,9 @@ class PieChartHandler {
|
|
|
15121
15226
|
legends = legendChunks.map((chunk, index) => ({
|
|
15122
15227
|
show: true,
|
|
15123
15228
|
align: 'right',
|
|
15229
|
+
left: 'center',
|
|
15124
15230
|
bottom: (legendChunks?.length - index) * 18,
|
|
15231
|
+
orient: 'horizontal',
|
|
15125
15232
|
type: seriesData.length > 8 ? 'scroll' : 'plain',
|
|
15126
15233
|
icon: 'circle',
|
|
15127
15234
|
data: chunk,
|
|
@@ -15164,6 +15271,7 @@ class PieChartHandler {
|
|
|
15164
15271
|
radius: chartSettings.radius,
|
|
15165
15272
|
center: ['50%', '45%'], // default; might be overridden below
|
|
15166
15273
|
padAngle: pieOverride?.padAngle || 0,
|
|
15274
|
+
minShowLabelAngle: hasCanvasLegend ? 8 : 0,
|
|
15167
15275
|
avoidLabelOverlap: true,
|
|
15168
15276
|
itemStyle: {
|
|
15169
15277
|
borderRadius: pieOverride?.borderRadius ?? 8,
|
|
@@ -15172,7 +15280,9 @@ class PieChartHandler {
|
|
|
15172
15280
|
hideOverlap: true,
|
|
15173
15281
|
},
|
|
15174
15282
|
label: {
|
|
15175
|
-
show:
|
|
15283
|
+
show: suppressCanvasSliceLabels
|
|
15284
|
+
? false
|
|
15285
|
+
: (configAsType?.['label']?.show ?? true),
|
|
15176
15286
|
position: labelPosition,
|
|
15177
15287
|
formatter: chartSettings.labelFormatter,
|
|
15178
15288
|
fontFamily: generalConfiguration?.fontConfig?.fontFamily,
|
|
@@ -15180,7 +15290,7 @@ class PieChartHandler {
|
|
|
15180
15290
|
},
|
|
15181
15291
|
emphasis: {
|
|
15182
15292
|
label: {
|
|
15183
|
-
show:
|
|
15293
|
+
show: !suppressCanvasSliceLabels,
|
|
15184
15294
|
fontSize: '16',
|
|
15185
15295
|
fontWeight: 'bold',
|
|
15186
15296
|
},
|
|
@@ -15192,9 +15302,11 @@ class PieChartHandler {
|
|
|
15192
15302
|
noData: seriesData.length === 0 ||
|
|
15193
15303
|
seriesData.every((d) => d.value === 0 || d.isStaticProperty),
|
|
15194
15304
|
};
|
|
15305
|
+
if (suppressCanvasSliceLabels) {
|
|
15306
|
+
baseConfig.series[0].labelLine = { show: false };
|
|
15307
|
+
}
|
|
15195
15308
|
const genericLegendPosition = this.normalizeLegendPosition(configAsType?.['legend']?.position);
|
|
15196
15309
|
if (genericLegendPosition &&
|
|
15197
|
-
genericLegendPosition !== 'bottom' &&
|
|
15198
15310
|
!pieOverride?.legendPosition) {
|
|
15199
15311
|
this.applyPieLegendPosition(baseConfig.legend, genericLegendPosition);
|
|
15200
15312
|
}
|
|
@@ -15246,7 +15358,7 @@ class PieChartHandler {
|
|
|
15246
15358
|
legend.left = legend.left ?? 'center';
|
|
15247
15359
|
break;
|
|
15248
15360
|
case 'bottom':
|
|
15249
|
-
legend.bottom = '
|
|
15361
|
+
legend.bottom = '3%';
|
|
15250
15362
|
legend.left = legend.left ?? 'center';
|
|
15251
15363
|
break;
|
|
15252
15364
|
}
|
|
@@ -15273,9 +15385,7 @@ class PieChartHandler {
|
|
|
15273
15385
|
if (pieOverride.legendVerticalAlign) {
|
|
15274
15386
|
applyLegendOverride((legend) => {
|
|
15275
15387
|
const appliedPosition = pieOverride?.legendPosition;
|
|
15276
|
-
if (
|
|
15277
|
-
appliedPosition === 'left' ||
|
|
15278
|
-
appliedPosition === 'right') {
|
|
15388
|
+
if (appliedPosition === 'left' || appliedPosition === 'right') {
|
|
15279
15389
|
legend.top = pieOverride.legendVerticalAlign;
|
|
15280
15390
|
delete legend.bottom;
|
|
15281
15391
|
}
|
|
@@ -15321,11 +15431,14 @@ class PieChartHandler {
|
|
|
15321
15431
|
series.avoidLabelOverlap = pieOverride.avoidLabelOverlap;
|
|
15322
15432
|
if (pieOverride.labelPosition) {
|
|
15323
15433
|
series.label.position = labelPosition;
|
|
15324
|
-
series.label.show =
|
|
15434
|
+
series.label.show = !suppressCanvasSliceLabels;
|
|
15325
15435
|
}
|
|
15326
15436
|
if (pieOverride.labelFontColor)
|
|
15327
15437
|
series.label.color = pieOverride.labelFontColor;
|
|
15328
|
-
if (
|
|
15438
|
+
if (suppressCanvasSliceLabels) {
|
|
15439
|
+
series.labelLine = { show: false };
|
|
15440
|
+
}
|
|
15441
|
+
else if (pieOverride.showLabelLine !== undefined) {
|
|
15329
15442
|
series.labelLine = { show: pieOverride.showLabelLine };
|
|
15330
15443
|
}
|
|
15331
15444
|
if (pieOverride.selectedMode !== undefined)
|
|
@@ -15362,7 +15475,6 @@ class PieChartHandler {
|
|
|
15362
15475
|
}
|
|
15363
15476
|
}
|
|
15364
15477
|
const finalLegendPosition = this.normalizeLegendPosition(pieOverride?.legendPosition ?? genericLegendPosition);
|
|
15365
|
-
const hasCanvasLegend = showLegend && !pieOverride?.useEnhancedLegend;
|
|
15366
15478
|
if (finalLegendPosition &&
|
|
15367
15479
|
!this.hasExplicitPieCenter(pieOverride) &&
|
|
15368
15480
|
(finalLegendPosition !== 'bottom' || hasCanvasLegend)) {
|
|
@@ -15426,7 +15538,7 @@ class PieChartHandler {
|
|
|
15426
15538
|
}
|
|
15427
15539
|
return baseConfig;
|
|
15428
15540
|
}
|
|
15429
|
-
resolvePieLabelFormatter(displayPercentage, isPercentage, configuredFormatter, labelPosition, clientFormat, languageCode) {
|
|
15541
|
+
resolvePieLabelFormatter(displayPercentage, isPercentage, configuredFormatter, labelPosition, clientFormat, languageCode, hasCanvasLegend) {
|
|
15430
15542
|
const valueFormatter = (params) => {
|
|
15431
15543
|
if (params.data?.isStaticProperty === true && isPercentage) {
|
|
15432
15544
|
return '';
|
|
@@ -15441,6 +15553,9 @@ class PieChartHandler {
|
|
|
15441
15553
|
return ` ${params.percent}%`;
|
|
15442
15554
|
};
|
|
15443
15555
|
}
|
|
15556
|
+
if (hasCanvasLegend && labelPosition === 'inside') {
|
|
15557
|
+
return valueFormatter;
|
|
15558
|
+
}
|
|
15444
15559
|
if (typeof configuredFormatter === 'string' &&
|
|
15445
15560
|
this.pieLabelFormatterUsesName(configuredFormatter)) {
|
|
15446
15561
|
return valueFormatter;
|
|
@@ -15451,7 +15566,7 @@ class PieChartHandler {
|
|
|
15451
15566
|
return position === 'outside' ? 'outside' : 'inside';
|
|
15452
15567
|
}
|
|
15453
15568
|
pieLabelFormatterUsesName(formatter) {
|
|
15454
|
-
return /\{b(?:\d*)?\}
|
|
15569
|
+
return /\{(?:b|name)(?:\d*)?\}/i.test(formatter);
|
|
15455
15570
|
}
|
|
15456
15571
|
normalizeLegendPosition(position) {
|
|
15457
15572
|
return position === 'top' ||
|
|
@@ -15488,7 +15603,7 @@ class PieChartHandler {
|
|
|
15488
15603
|
legend.orient = legend.orient ?? 'horizontal';
|
|
15489
15604
|
break;
|
|
15490
15605
|
case 'bottom':
|
|
15491
|
-
legend.bottom = '
|
|
15606
|
+
legend.bottom = '3%';
|
|
15492
15607
|
legend.left = legend.left ?? 'center';
|
|
15493
15608
|
legend.orient = legend.orient ?? 'horizontal';
|
|
15494
15609
|
break;
|
|
@@ -22081,7 +22196,7 @@ class ChartSettingsDrawer {
|
|
|
22081
22196
|
this.item.set(item);
|
|
22082
22197
|
}
|
|
22083
22198
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ChartSettingsDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
22084
|
-
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 <!-- Isolated Preview Tab -->\r\n <div [hidden]=\"activeTab() !== 'preview'\" class=\"flex flex-col gap-3\">\r\n @if (activeTab() === \"preview\") {\r\n @if (canRenderChartPreview()) {\r\n <div\r\n class=\"h-[28rem] min-h-[28rem] rounded-lg border border-surface-200 bg-surface-50 p-3\"\r\n >\r\n <mt-card-content\r\n class=\"block h-full w-full\"\r\n [headerConfig]=\"previewHeaderConfig()\"\r\n [styleConfig]=\"previewStyleConfig()\"\r\n [cardStyleConfig]=\"previewCardStyleConfig()\"\r\n [density]=\"previewDensity()\"\r\n [title]=\"previewTitle()\"\r\n [isNoTopEnd]=\"true\"\r\n [isChart]=\"true\"\r\n >\r\n <ng-container body>\r\n <mt-echart\r\n class=\"block h-full w-full\"\r\n [dashboardId]=\"previewDashboardId\"\r\n [chartConfig]=\"previewChartData()\"\r\n [configurationItem]=\"itemConfig()\"\r\n height=\"100%\"\r\n />\r\n </ng-container>\r\n </mt-card-content>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[16rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 text-center\"\r\n >\r\n <div class=\"max-w-sm\">\r\n <p class=\"text-sm font-medium text-color\">\r\n {{ t(\"noPreviewAvailable\") }}\r\n </p>\r\n <p class=\"mt-1 text-xs text-muted-color\">\r\n {{ t(\"configureChartToPreview\") }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Advanced Override (JSON) - 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 {{ t(\"pass4.advanced.hint\") }}\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]=\"t('pass4.advanced.apply')\"\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"] }, { kind: "component", type: EChartComponent, selector: "mt-echart", inputs: ["dashboardId", "chartConfig", "configurationItem", "height", "inGroup", "headerHidden"], outputs: ["chartClick"] }, { kind: "component", type: CardContentComponent, selector: "mt-card-content", inputs: ["title", "inGroup", "headerConfig", "styleConfig", "cardStyleConfig", "density", "showHeader", "headerClickable", "isNoTopEnd", "isChart", "titleEditable"], outputs: ["headerClick", "titleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
22199
|
+
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\n [class]=\"\n modal.contentClass + ' db-sectioned-drawer flex h-full min-h-0 flex-col p-0'\n \"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n>\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 <!-- Isolated Preview Tab -->\r\n <div [hidden]=\"activeTab() !== 'preview'\" class=\"flex flex-col gap-3\">\r\n @if (activeTab() === \"preview\") {\r\n @if (canRenderChartPreview()) {\r\n <div\r\n class=\"h-[28rem] min-h-[28rem] rounded-lg border border-surface-200 bg-surface-50 p-3\"\r\n >\r\n <mt-card-content\r\n class=\"block h-full w-full\"\r\n [headerConfig]=\"previewHeaderConfig()\"\r\n [styleConfig]=\"previewStyleConfig()\"\r\n [cardStyleConfig]=\"previewCardStyleConfig()\"\r\n [density]=\"previewDensity()\"\r\n [title]=\"previewTitle()\"\r\n [isNoTopEnd]=\"true\"\r\n [isChart]=\"true\"\r\n >\r\n <ng-container body>\r\n <mt-echart\r\n class=\"block h-full w-full\"\r\n [dashboardId]=\"previewDashboardId\"\r\n [chartConfig]=\"previewChartData()\"\r\n [configurationItem]=\"itemConfig()\"\r\n height=\"100%\"\r\n />\r\n </ng-container>\r\n </mt-card-content>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[16rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 text-center\"\r\n >\r\n <div class=\"max-w-sm\">\r\n <p class=\"text-sm font-medium text-color\">\r\n {{ t(\"noPreviewAvailable\") }}\r\n </p>\r\n <p class=\"mt-1 text-xs text-muted-color\">\r\n {{ t(\"configureChartToPreview\") }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Advanced Override (JSON) - 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 {{ t(\"pass4.advanced.hint\") }}\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]=\"t('pass4.advanced.apply')\"\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", styles: [".db-sectioned-drawer mt-card{overflow:hidden;border-color:var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);border-radius:.375rem}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1){padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1) h3{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}.db-control-section{display:flex;flex-direction:column;gap:0;overflow:hidden;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.375rem;background:var(--p-surface-0, #fff)}.db-control-section__header{margin:0;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb);font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}.db-control-section__body{padding:1rem}\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"] }, { kind: "component", type: EChartComponent, selector: "mt-echart", inputs: ["dashboardId", "chartConfig", "configurationItem", "height", "inGroup", "headerHidden"], outputs: ["chartClick"] }, { kind: "component", type: CardContentComponent, selector: "mt-card-content", inputs: ["title", "inGroup", "headerConfig", "styleConfig", "cardStyleConfig", "density", "showHeader", "headerClickable", "isNoTopEnd", "isChart", "titleEditable"], outputs: ["headerClick", "titleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
22085
22200
|
}
|
|
22086
22201
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ChartSettingsDrawer, decorators: [{
|
|
22087
22202
|
type: Component,
|
|
@@ -22099,7 +22214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
22099
22214
|
SchemaControlRendererComponent,
|
|
22100
22215
|
EChartComponent,
|
|
22101
22216
|
CardContentComponent,
|
|
22102
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\
|
|
22217
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n [class]=\"\n modal.contentClass + ' db-sectioned-drawer flex h-full min-h-0 flex-col p-0'\n \"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n>\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 <!-- Isolated Preview Tab -->\r\n <div [hidden]=\"activeTab() !== 'preview'\" class=\"flex flex-col gap-3\">\r\n @if (activeTab() === \"preview\") {\r\n @if (canRenderChartPreview()) {\r\n <div\r\n class=\"h-[28rem] min-h-[28rem] rounded-lg border border-surface-200 bg-surface-50 p-3\"\r\n >\r\n <mt-card-content\r\n class=\"block h-full w-full\"\r\n [headerConfig]=\"previewHeaderConfig()\"\r\n [styleConfig]=\"previewStyleConfig()\"\r\n [cardStyleConfig]=\"previewCardStyleConfig()\"\r\n [density]=\"previewDensity()\"\r\n [title]=\"previewTitle()\"\r\n [isNoTopEnd]=\"true\"\r\n [isChart]=\"true\"\r\n >\r\n <ng-container body>\r\n <mt-echart\r\n class=\"block h-full w-full\"\r\n [dashboardId]=\"previewDashboardId\"\r\n [chartConfig]=\"previewChartData()\"\r\n [configurationItem]=\"itemConfig()\"\r\n height=\"100%\"\r\n />\r\n </ng-container>\r\n </mt-card-content>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[16rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 text-center\"\r\n >\r\n <div class=\"max-w-sm\">\r\n <p class=\"text-sm font-medium text-color\">\r\n {{ t(\"noPreviewAvailable\") }}\r\n </p>\r\n <p class=\"mt-1 text-xs text-muted-color\">\r\n {{ t(\"configureChartToPreview\") }}\r\n </p>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n <!-- Advanced Override (JSON) - 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 {{ t(\"pass4.advanced.hint\") }}\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]=\"t('pass4.advanced.apply')\"\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", styles: [".db-sectioned-drawer mt-card{overflow:hidden;border-color:var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);border-radius:.375rem}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1){padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1) h3{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}.db-control-section{display:flex;flex-direction:column;gap:0;overflow:hidden;border:1px solid var(--p-surface-200, #e5e7eb);border-radius:.375rem;background:var(--p-surface-0, #fff)}.db-control-section__header{margin:0;padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb);font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}.db-control-section__body{padding:1rem}\n"] }]
|
|
22103
22218
|
}], ctorParameters: () => [] });
|
|
22104
22219
|
/**
|
|
22105
22220
|
* Deep-merge two plain object trees. Arrays and primitives in the source
|
|
@@ -23033,7 +23148,7 @@ class GeneralQuery {
|
|
|
23033
23148
|
useExisting: forwardRef(() => GeneralQuery),
|
|
23034
23149
|
multi: true,
|
|
23035
23150
|
},
|
|
23036
|
-
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-4\"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n [formGroup]=\"queryForm\"\n>\n <!-- Category Property (shown for certain chart types) -->\n @if (shouldShowField(\"categoryProperty\")) {\n <div class=\"mb-2\">\n <mt-select-field\n [label]=\"t('categoryProperty')\"\n formControlName=\"categoryProperty\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectCategoryProperty')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Add Series Button -->\n @if (chartType() !== \"overview\" || seriesArray.length === 0) {\n <div class=\"flex justify-end\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addSeries')\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addSeries()\"\n />\n </div>\n }\n\n <!-- Series List -->\n <div formArrayName=\"series\" class=\"flex flex-col gap-4\">\n @for (\n series of seriesArray.controls;\n track trackByIndex(i);\n let i = $index\n ) {\n <div\n class=\"p-4 rounded-lg border transition-all\"\n [class.border-red-500]=\"series.invalid\"\n [class.border-surface-200]=\"!series.invalid\"\n [formGroupName]=\"i\"\n >\n <!-- Series Header -->\n <div class=\"flex items-center justify-between mb-4\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\n >\n {{ i + 1 }}\n </span>\n <span class=\"text-sm font-medium text-muted-color\">{{\n t(\"series\")\n }}</span>\n </div>\n <div class=\"flex items-center gap-2\">\n <mt-button\n icon=\"general.settings-02\"\n severity=\"secondary\"\n [rounded]=\"true\"\n size=\"small\"\n (onClick)=\"toggleAdvanced(i)\"\n [pTooltip]=\"t('advancedSettings')\"\n />\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"deleteSeries(i)\"\n />\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n <!-- Auto Stack Toggle -->\n @if (shouldShowField(\"autoStack\")) {\n <div class=\"md:col-span-2 lg:col-span-3\">\n <mt-toggle-field\n [label]=\"t('autoStack')\"\n formControlName=\"autoStack\"\n />\n </div>\n }\n\n <!-- Value Property -->\n @if (shouldShowField(\"valueProperty\") || series.value.autoStack) {\n <mt-select-field\n [label]=\"t('valueProperty')\"\n formControlName=\"valueProperty\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectValueProperty')\"\n [filter]=\"true\"\n />\n }\n\n <!-- Aggregate Function -->\n @if (shouldShowField(\"aggregateFunction\")) {\n <mt-select-field\n [label]=\"t('aggregateFunction')\"\n formControlName=\"aggregateFunction\"\n [options]=\"aggregateFunctions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n }\n\n <!-- Color Picker -->\n @if (shouldShowField(\"color\")) {\n <mt-color-picker-field\n [label]=\"t('seriesColor')\"\n formControlName=\"color\"\n />\n }\n\n <!-- Bar Type (for stacked bar charts) -->\n @if (shouldShowField(\"barType\")) {\n <mt-select-field\n [label]=\"t('barType')\"\n formControlName=\"barType\"\n [options]=\"barTypes\"\n optionLabel=\"name\"\n optionValue=\"key\"\n />\n }\n\n <!-- Auto Stack By Property -->\n @if (\n shouldShowField(\"autoStackByProperty\") && series.value.autoStack\n ) {\n <mt-select-field\n [label]=\"t('autoStackByProperty')\"\n formControlName=\"autoStackByProperty\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperty')\"\n [filter]=\"true\"\n />\n }\n\n <!-- Group By Properties -->\n @if (shouldShowField(\"groupByProperties\")) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('groupByProperties')\"\n formControlName=\"groupByProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Stack Properties (for stacked charts) -->\n @if (shouldShowField(\"stackProperties\") && !series.value.autoStack) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('stackProperties')\"\n formControlName=\"stackProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Extra Properties -->\n @if (shouldShowField(\"extraProperties\")) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n formControlName=\"extraProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n </div>\n\n <!-- Advanced Settings (Formula) -->\n @if (series.value.showAdvancedSettings && shouldShowField(\"formula\")) {\n <div\n class=\"mt-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\n >\n <div class=\"text-sm font-medium mb-2\">\n {{ t(\"advancedSettings\") }}\n </div>\n <mt-text-field\n [label]=\"t('formula')\"\n formControlName=\"formula\"\n [placeholder]=\"t('enterFormula')\"\n />\n </div>\n }\n\n <!-- Filters Section -->\n @if (shouldShowField(\"filters\")) {\n <div class=\"mt-4 border border-surface-200 rounded-lg p-4\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium\">{{ t(\"seriesFilters\") }}</span>\n <mt-button\n icon=\"general.plus\"\n severity=\"secondary\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addFilter(i)\"\n [pTooltip]=\"t('addFilter')\"\n />\n </div>\n\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\n @for (\n filter of getFilters(series).controls;\n track trackByIndex(j);\n let j = $index\n ) {\n <div\n class=\"grid grid-cols-12 gap-2 p-3 bg-surface-50 rounded-lg border border-surface-100\"\n [formGroupName]=\"j\"\n >\n <!-- Property Key -->\n <div class=\"col-span-4\">\n <mt-select-field\n [label]=\"j === 0 ? t('property') : ''\"\n formControlName=\"propertyKey\"\n [options]=\"\n useGroupedSelect()\n ? propertiesGrouped()\n : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperty')\"\n [filter]=\"true\"\n />\n </div>\n\n <!-- Operator -->\n <div class=\"col-span-2\">\n <mt-select-field\n [label]=\"j === 0 ? t('operator') : ''\"\n formControlName=\"operator\"\n [options]=\"operators\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n\n <!-- Value -->\n <div class=\"col-span-4\">\n <mt-text-field\n [label]=\"j === 0 ? t('value') : ''\"\n formControlName=\"value\"\n [placeholder]=\"t('enterValue')\"\n />\n </div>\n\n <!-- Remove Filter -->\n <div class=\"col-span-2 flex items-end justify-end pb-1\">\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"removeFilter(i, j)\"\n />\n </div>\n </div>\n }\n\n @if (getFilters(series).length === 0) {\n <div class=\"text-center py-3 text-muted-color text-sm\">\n {{ t(\"noFiltersConfigured\") }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (seriesArray.length === 0) {\n <div\n class=\"text-center py-8 text-muted-color border border-dashed border-surface-300 rounded-lg\"\n >\n <i class=\"mti mti-chart-bar text-3xl mb-2 block\"></i>\n <p class=\"mb-2\">{{ t(\"noSeriesConfigured\") }}</p>\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addSeries')\"\n severity=\"secondary\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addSeries()\"\n />\n </div>\n }\n </div>\n</div>\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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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: "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 });
|
|
23151
|
+
], ngImport: i0, template: "<div\n class=\"flex flex-col gap-4\"\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\n [formGroup]=\"queryForm\"\n>\n <!-- Category Property (shown for certain chart types) -->\n @if (shouldShowField(\"categoryProperty\")) {\n <div class=\"mb-2\">\n <mt-select-field\n [label]=\"t('categoryProperty')\"\n formControlName=\"categoryProperty\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectCategoryProperty')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Add Series Button -->\n @if (chartType() !== \"overview\" || seriesArray.length === 0) {\n <div class=\"flex justify-end\">\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addSeries')\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addSeries()\"\n />\n </div>\n }\n\n <!-- Series List -->\n <div formArrayName=\"series\" class=\"flex flex-col gap-4\">\n @for (\n series of seriesArray.controls;\n track trackByIndex(i);\n let i = $index\n ) {\n <div\n class=\"p-4 rounded-lg border transition-all\"\n [class.border-red-500]=\"series.invalid\"\n [class.border-surface-200]=\"!series.invalid\"\n [formGroupName]=\"i\"\n >\n <!-- Series Header -->\n <div class=\"flex items-center justify-between mb-4\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-100 text-primary-600 text-sm font-semibold\"\n >\n {{ i + 1 }}\n </span>\n <span class=\"text-sm font-medium text-muted-color\">{{\n t(\"series\")\n }}</span>\n </div>\n <div class=\"flex items-center gap-2\">\n <mt-button\n icon=\"general.settings-02\"\n severity=\"secondary\"\n [rounded]=\"true\"\n size=\"small\"\n (onClick)=\"toggleAdvanced(i)\"\n [pTooltip]=\"t('advancedSettings')\"\n />\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"deleteSeries(i)\"\n />\n </div>\n </div>\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n <!-- Auto Stack Toggle -->\n @if (shouldShowField(\"autoStack\")) {\n <div class=\"md:col-span-2 lg:col-span-3\">\n <mt-toggle-field\n [label]=\"t('autoStack')\"\n formControlName=\"autoStack\"\n />\n </div>\n }\n\n <!-- Value Property -->\n @if (shouldShowField(\"valueProperty\") || series.value.autoStack) {\n <mt-select-field\n [label]=\"t('valueProperty')\"\n formControlName=\"valueProperty\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectValueProperty')\"\n [filter]=\"true\"\n />\n }\n\n <!-- Aggregate Function -->\n @if (shouldShowField(\"aggregateFunction\")) {\n <mt-select-field\n [label]=\"t('aggregateFunction')\"\n formControlName=\"aggregateFunction\"\n [options]=\"aggregateFunctions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n }\n\n <!-- Color Picker -->\n @if (shouldShowField(\"color\")) {\n <mt-color-picker-field\n [label]=\"t('seriesColor')\"\n formControlName=\"color\"\n />\n }\n\n <!-- Bar Type (for stacked bar charts) -->\n @if (shouldShowField(\"barType\")) {\n <mt-select-field\n [label]=\"t('barType')\"\n formControlName=\"barType\"\n [options]=\"barTypes\"\n optionLabel=\"name\"\n optionValue=\"key\"\n />\n }\n\n <!-- Auto Stack By Property -->\n @if (\n shouldShowField(\"autoStackByProperty\") && series.value.autoStack\n ) {\n <mt-select-field\n [label]=\"t('autoStackByProperty')\"\n formControlName=\"autoStackByProperty\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperty')\"\n [filter]=\"true\"\n />\n }\n\n <!-- Group By Properties -->\n @if (shouldShowField(\"groupByProperties\")) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('groupByProperties')\"\n formControlName=\"groupByProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Stack Properties (for stacked charts) -->\n @if (shouldShowField(\"stackProperties\") && !series.value.autoStack) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('stackProperties')\"\n formControlName=\"stackProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n\n <!-- Extra Properties -->\n @if (shouldShowField(\"extraProperties\")) {\n <div class=\"col-span-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n formControlName=\"extraProperties\"\n [options]=\"\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperties')\"\n [filter]=\"true\"\n />\n </div>\n }\n </div>\n\n <!-- Advanced Settings (Formula) -->\n @if (series.value.showAdvancedSettings && shouldShowField(\"formula\")) {\n <div\n class=\"mt-4 p-3 bg-surface-50 rounded-lg border border-surface-200\"\n >\n <div class=\"text-sm font-medium mb-2\">\n {{ t(\"advancedSettings\") }}\n </div>\n <mt-text-field\n [label]=\"t('formula')\"\n formControlName=\"formula\"\n [placeholder]=\"t('enterFormula')\"\n />\n </div>\n }\n\n <!-- Filters Section -->\n @if (shouldShowField(\"filters\")) {\n <div class=\"mt-4 border border-surface-200 rounded-lg p-4\">\n <div class=\"flex items-center justify-between mb-3\">\n <span class=\"text-sm font-medium\">{{ t(\"seriesFilters\") }}</span>\n <mt-button\n icon=\"general.plus\"\n severity=\"secondary\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addFilter(i)\"\n [pTooltip]=\"t('addFilter')\"\n />\n </div>\n\n <div class=\"flex flex-col gap-3\" formArrayName=\"filters\">\n @for (\n filter of getFilters(series).controls;\n track trackByIndex(j);\n let j = $index\n ) {\n <div\n class=\"grid grid-cols-12 gap-2 p-3 bg-surface-50 rounded-lg border border-surface-100\"\n [formGroupName]=\"j\"\n >\n <!-- Property Key -->\n <div class=\"col-span-4\">\n <mt-select-field\n [label]=\"j === 0 ? t('property') : ''\"\n formControlName=\"propertyKey\"\n [options]=\"\n useGroupedSelect()\n ? propertiesGrouped()\n : propertiesFlat()\n \"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [placeholder]=\"t('selectProperty')\"\n [filter]=\"true\"\n />\n </div>\n\n <!-- Operator -->\n <div class=\"col-span-2\">\n <mt-select-field\n [label]=\"j === 0 ? t('operator') : ''\"\n formControlName=\"operator\"\n [options]=\"operators\"\n optionLabel=\"label\"\n optionValue=\"value\"\n />\n </div>\n\n <!-- Value -->\n <div class=\"col-span-4\">\n <mt-text-field\n [label]=\"j === 0 ? t('value') : ''\"\n formControlName=\"value\"\n [placeholder]=\"t('enterValue')\"\n />\n </div>\n\n <!-- Remove Filter -->\n <div class=\"col-span-2 flex items-end justify-end pb-1\">\n <mt-button\n icon=\"general.trash-01\"\n severity=\"danger\"\n [rounded]=\"true\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"removeFilter(i, j)\"\n />\n </div>\n </div>\n }\n\n @if (getFilters(series).length === 0) {\n <div class=\"text-center py-3 text-muted-color text-sm\">\n {{ t(\"noFiltersConfigured\") }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (seriesArray.length === 0) {\n <div\n class=\"text-center py-8 text-muted-color border border-dashed border-surface-300 rounded-lg\"\n >\n <i class=\"mti mti-chart-bar text-3xl mb-2 block\"></i>\n <p class=\"mb-2\">{{ t(\"noSeriesConfigured\") }}</p>\n <mt-button\n icon=\"general.plus\"\n [label]=\"t('addSeries')\"\n severity=\"secondary\"\n size=\"small\"\n [disabled]=\"disabled\"\n (onClick)=\"addSeries()\"\n />\n </div>\n }\n </div>\n</div>\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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { 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: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], 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", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["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 });
|
|
23037
23152
|
}
|
|
23038
23153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GeneralQuery, decorators: [{
|
|
23039
23154
|
type: Component,
|
|
@@ -23232,7 +23347,7 @@ class TableQuery {
|
|
|
23232
23347
|
useExisting: forwardRef(() => TableQuery),
|
|
23233
23348
|
multi: true,
|
|
23234
23349
|
},
|
|
23235
|
-
], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Lookup Property -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n formControlName=\"lookupProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectLookupProperty')\"\r\n [filter]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Selected Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('properties')\"\r\n formControlName=\"selectedProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (\r\n queryForm.get(\"selectedProperties\")?.invalid &&\r\n queryForm.get(\"selectedProperties\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n t(\"atLeastOnePropertyRequired\")\r\n }}</small>\r\n }\r\n @if (selectedProperties().length > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"propertyOrder\") }}\r\n </span>\r\n @for (propertyKey of selectedProperties(); track propertyKey + $index) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"moveSelectedProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"\r\n disabled || $index === selectedProperties().length - 1\r\n \"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"moveSelectedProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Pivot Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('pivotProperties')\"\r\n formControlName=\"PivotProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectPivotProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (pivotProperties().length > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"pivotPropertyOrder\") }}\r\n </span>\r\n @for (propertyKey of pivotProperties(); track propertyKey + $index) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"movePivotProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === pivotProperties().length - 1\"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"movePivotProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Aggregation Properties -->\r\n <mt-card [title]=\"t('aggregationProperties')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addAggregation()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addAggregation')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"AggregationProperties\">\r\n @for (\r\n agg of aggregationArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-3 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\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 <!-- Aggregate Function -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('aggregateFunction') : ''\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Remove -->\r\n <div class=\"col-span-3 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeAggregation(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (aggregationArray.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noAggregationsConfigured\") }}\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: 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: "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 });
|
|
23350
|
+
], ngImport: i0, template: "<div\r\n class=\"flex flex-col gap-4\"\r\n *transloco=\"let t; prefix: 'dashboardBuilder'\"\r\n [formGroup]=\"queryForm\"\r\n>\r\n <!-- Lookup Property -->\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <mt-select-field\r\n [label]=\"t('lookupProperty')\"\r\n formControlName=\"lookupProperty\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectLookupProperty')\"\r\n [filter]=\"true\"\r\n [showClear]=\"true\"\r\n />\r\n </div>\r\n\r\n <!-- Selected Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('properties')\"\r\n formControlName=\"selectedProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (\r\n queryForm.get(\"selectedProperties\")?.invalid &&\r\n queryForm.get(\"selectedProperties\")?.touched\r\n ) {\r\n <small class=\"text-red-500 mt-1 block\">{{\r\n t(\"atLeastOnePropertyRequired\")\r\n }}</small>\r\n }\r\n @if (selectedProperties().length > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"propertyOrder\") }}\r\n </span>\r\n @for (propertyKey of selectedProperties(); track propertyKey + $index) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"moveSelectedProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"\r\n disabled || $index === selectedProperties().length - 1\r\n \"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"moveSelectedProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Pivot Properties -->\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('pivotProperties')\"\r\n formControlName=\"PivotProperties\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [placeholder]=\"t('selectPivotProperties')\"\r\n [filter]=\"true\"\r\n />\r\n @if (pivotProperties().length > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"pivotPropertyOrder\") }}\r\n </span>\r\n @for (propertyKey of pivotProperties(); track propertyKey + $index) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"movePivotProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === pivotProperties().length - 1\"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"movePivotProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Aggregation Properties -->\r\n <mt-card [title]=\"t('aggregationProperties')\">\r\n <ng-template #cardEnd>\r\n <mt-button\r\n icon=\"general.plus\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n (onClick)=\"addAggregation()\"\r\n [disabled]=\"disabled\"\r\n [pTooltip]=\"t('addAggregation')\"\r\n />\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-3\" formArrayName=\"AggregationProperties\">\r\n @for (\r\n agg of aggregationArray.controls;\r\n track trackByIndex(i);\r\n let i = $index\r\n ) {\r\n <div\r\n class=\"grid grid-cols-12 gap-3 p-3 bg-surface-50 rounded-lg border border-surface-100\"\r\n [formGroupName]=\"i\"\r\n >\r\n <!-- Property Key -->\r\n <div class=\"col-span-5\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('property') : ''\"\r\n formControlName=\"propertyKey\"\r\n [options]=\"\r\n useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\r\n \"\r\n [group]=\"useGroupedSelect()\"\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 <!-- Aggregate Function -->\r\n <div class=\"col-span-4\">\r\n <mt-select-field\r\n [label]=\"i === 0 ? t('aggregateFunction') : ''\"\r\n formControlName=\"aggregateFunction\"\r\n [options]=\"aggregateFunctions\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n />\r\n </div>\r\n\r\n <!-- Remove -->\r\n <div class=\"col-span-3 flex items-end justify-end pb-1\">\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [rounded]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled\"\r\n (onClick)=\"removeAggregation(i)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (aggregationArray.length === 0) {\r\n <div class=\"text-center py-4 text-muted-color text-sm\">\r\n {{ t(\"noAggregationsConfigured\") }}\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: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23236
23351
|
}
|
|
23237
23352
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableQuery, decorators: [{
|
|
23238
23353
|
type: Component,
|
|
@@ -23323,7 +23438,7 @@ class TimelineQuery {
|
|
|
23323
23438
|
useExisting: forwardRef(() => TimelineQuery),
|
|
23324
23439
|
multi: true,
|
|
23325
23440
|
},
|
|
23326
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Pivot Property -->\n <mt-select-field\n [label]=\"t('pivotProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().pivotProperty\"\n (ngModelChange)=\"updateField('pivotProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Lookup Property -->\n <mt-select-field\n [label]=\"t('lookupProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().lookupProperty\"\n (ngModelChange)=\"updateField('lookupProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Time Frame -->\n <mt-select-field\n [label]=\"t('timeFrame')\"\n [options]=\"timeFrameOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectTimeFrame')\"\n [ngModel]=\"query().timeFrame\"\n (ngModelChange)=\"updateField('timeFrame', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Start Point Time Property -->\n <mt-select-field\n [label]=\"t('startPointTimeProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().startPoint_timeProperty\"\n (ngModelChange)=\"updateField('startPoint_timeProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- End Point Time Property -->\n <mt-select-field\n [label]=\"t('endPointTimeProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().endPoint_timeProperty\"\n (ngModelChange)=\"updateField('endPoint_timeProperty', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n\n <!-- Extra Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().extraProperties\"\n (ngModelChange)=\"updateField('extraProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23441
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Pivot Property -->\n <mt-select-field\n [label]=\"t('pivotProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().pivotProperty\"\n (ngModelChange)=\"updateField('pivotProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Lookup Property -->\n <mt-select-field\n [label]=\"t('lookupProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().lookupProperty\"\n (ngModelChange)=\"updateField('lookupProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Time Frame -->\n <mt-select-field\n [label]=\"t('timeFrame')\"\n [options]=\"timeFrameOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectTimeFrame')\"\n [ngModel]=\"query().timeFrame\"\n (ngModelChange)=\"updateField('timeFrame', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Start Point Time Property -->\n <mt-select-field\n [label]=\"t('startPointTimeProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().startPoint_timeProperty\"\n (ngModelChange)=\"updateField('startPoint_timeProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- End Point Time Property -->\n <mt-select-field\n [label]=\"t('endPointTimeProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().endPoint_timeProperty\"\n (ngModelChange)=\"updateField('endPoint_timeProperty', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n\n <!-- Extra Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().extraProperties\"\n (ngModelChange)=\"updateField('extraProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23327
23442
|
}
|
|
23328
23443
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TimelineQuery, decorators: [{
|
|
23329
23444
|
type: Component,
|
|
@@ -23419,7 +23534,7 @@ class PropertiesQuery {
|
|
|
23419
23534
|
useExisting: forwardRef(() => PropertiesQuery),
|
|
23420
23535
|
multi: true,
|
|
23421
23536
|
},
|
|
23422
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('selectProperties')\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [filter]=\"true\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [ngModel]=\"query().selectedProperties\"\r\n (ngModelChange)=\"updateSelectedProperties($event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n @if ((query().selectedProperties?.length || 0) > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"propertyOrder\") }}\r\n </span>\r\n @for (\r\n propertyKey of query().selectedProperties;\r\n track propertyKey + $index\r\n ) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"moveSelectedProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"\r\n disabled ||\r\n $index === (query().selectedProperties?.length || 0) - 1\r\n \"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"moveSelectedProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (query().selectedProperties?.length) {\r\n <div class=\"text-sm text-muted-color\">\r\n {{ t(\"selectedCount\") }}: {{ query().selectedProperties?.length }}\r\n </div>\r\n }\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: 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: 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: "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 });
|
|
23537
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <div class=\"w-full\">\r\n <mt-multi-select-field\r\n [label]=\"t('selectProperties')\"\r\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\r\n [group]=\"useGroupedSelect()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n optionGroupLabel=\"label\"\r\n optionGroupChildren=\"items\"\r\n [filter]=\"true\"\r\n [placeholder]=\"t('selectProperties')\"\r\n [ngModel]=\"query().selectedProperties\"\r\n (ngModelChange)=\"updateSelectedProperties($event)\"\r\n [disabled]=\"disabled\"\r\n />\r\n @if ((query().selectedProperties?.length || 0) > 1) {\r\n <div class=\"mt-3 flex flex-col gap-2\">\r\n <span class=\"text-xs font-medium text-muted-color\">\r\n {{ t(\"propertyOrder\") }}\r\n </span>\r\n @for (\r\n propertyKey of query().selectedProperties;\r\n track propertyKey + $index\r\n ) {\r\n <div\r\n class=\"flex items-center justify-between gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2\"\r\n >\r\n <span class=\"min-w-0 truncate text-sm\">\r\n {{ getPropertyLabel(propertyKey) }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <mt-button\r\n icon=\"arrow.arrow-up\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"disabled || $index === 0\"\r\n [pTooltip]=\"t('moveUp')\"\r\n (onClick)=\"moveSelectedProperty($index, -1)\"\r\n />\r\n <mt-button\r\n icon=\"arrow.arrow-down\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n size=\"small\"\r\n [disabled]=\"\r\n disabled ||\r\n $index === (query().selectedProperties?.length || 0) - 1\r\n \"\r\n [pTooltip]=\"t('moveDown')\"\r\n (onClick)=\"moveSelectedProperty($index, 1)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (query().selectedProperties?.length) {\r\n <div class=\"text-sm text-muted-color\">\r\n {{ t(\"selectedCount\") }}: {{ query().selectedProperties?.length }}\r\n </div>\r\n }\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: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["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: "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 });
|
|
23423
23538
|
}
|
|
23424
23539
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesQuery, decorators: [{
|
|
23425
23540
|
type: Component,
|
|
@@ -23514,7 +23629,7 @@ class SnapshotQuery {
|
|
|
23514
23629
|
useExisting: forwardRef(() => SnapshotQuery),
|
|
23515
23630
|
multi: true,
|
|
23516
23631
|
},
|
|
23517
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Level ID -->\n <mt-text-field\n [label]=\"t('levelId')\"\n [placeholder]=\"t('enterLevelId')\"\n [ngModel]=\"query().levelId\"\n (ngModelChange)=\"updateField('levelId', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Time Frame -->\n <mt-select-field\n [label]=\"t('timeFrame')\"\n [options]=\"timeFrameOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectTimeFrame')\"\n [ngModel]=\"query().timeFrame\"\n (ngModelChange)=\"updateField('timeFrame', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Year -->\n <mt-select-field\n [label]=\"t('year')\"\n [options]=\"yearOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectYear')\"\n [ngModel]=\"query().year\"\n (ngModelChange)=\"updateField('year', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Get Average Per Period -->\n <div class=\"flex items-end pb-2\">\n <mt-toggle-field\n [label]=\"t('getAveragePerPeriod')\"\n [ngModel]=\"query().getAveragePerPeriod\"\n (ngModelChange)=\"updateField('getAveragePerPeriod', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n </div>\n\n <!-- Selected Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('selectedProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().selectedProperties\"\n (ngModelChange)=\"updateField('selectedProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23632
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Level ID -->\n <mt-text-field\n [label]=\"t('levelId')\"\n [placeholder]=\"t('enterLevelId')\"\n [ngModel]=\"query().levelId\"\n (ngModelChange)=\"updateField('levelId', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Time Frame -->\n <mt-select-field\n [label]=\"t('timeFrame')\"\n [options]=\"timeFrameOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectTimeFrame')\"\n [ngModel]=\"query().timeFrame\"\n (ngModelChange)=\"updateField('timeFrame', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Year -->\n <mt-select-field\n [label]=\"t('year')\"\n [options]=\"yearOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"t('selectYear')\"\n [ngModel]=\"query().year\"\n (ngModelChange)=\"updateField('year', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Get Average Per Period -->\n <div class=\"flex items-end pb-2\">\n <mt-toggle-field\n [label]=\"t('getAveragePerPeriod')\"\n [ngModel]=\"query().getAveragePerPeriod\"\n (ngModelChange)=\"updateField('getAveragePerPeriod', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n </div>\n\n <!-- Selected Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('selectedProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().selectedProperties\"\n (ngModelChange)=\"updateField('selectedProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23518
23633
|
}
|
|
23519
23634
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: SnapshotQuery, decorators: [{
|
|
23520
23635
|
type: Component,
|
|
@@ -23599,7 +23714,7 @@ class MapQuery {
|
|
|
23599
23714
|
useExisting: forwardRef(() => MapQuery),
|
|
23600
23715
|
multi: true,
|
|
23601
23716
|
},
|
|
23602
|
-
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Location Property -->\n <mt-select-field\n [label]=\"t('locationProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().locationProperty\"\n (ngModelChange)=\"updateField('locationProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Grouping Property -->\n <mt-select-field\n [label]=\"t('groupingProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().groupingProperty\"\n (ngModelChange)=\"updateField('groupingProperty', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n\n <!-- Extra Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().extraProperties\"\n (ngModelChange)=\"updateField('extraProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23717
|
+
], ngImport: i0, template: "<div class=\"flex flex-col gap-4\" *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- Location Property -->\n <mt-select-field\n [label]=\"t('locationProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().locationProperty\"\n (ngModelChange)=\"updateField('locationProperty', $event)\"\n [disabled]=\"disabled\"\n />\n\n <!-- Grouping Property -->\n <mt-select-field\n [label]=\"t('groupingProperty')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperty')\"\n [ngModel]=\"query().groupingProperty\"\n (ngModelChange)=\"updateField('groupingProperty', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n\n <!-- Extra Properties -->\n <div class=\"w-full\">\n <mt-multi-select-field\n [label]=\"t('extraProperties')\"\n [options]=\"useGroupedSelect() ? propertiesGrouped() : propertiesFlat()\"\n [group]=\"useGroupedSelect()\"\n optionLabel=\"name\"\n optionValue=\"key\"\n optionGroupLabel=\"label\"\n optionGroupChildren=\"items\"\n [filter]=\"true\"\n [placeholder]=\"t('selectProperties')\"\n [ngModel]=\"query().extraProperties\"\n (ngModelChange)=\"updateField('extraProperties', $event)\"\n [disabled]=\"disabled\"\n />\n </div>\n</div>\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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display", "required", "maxSelectedLabels", "group", "virtualScroll", "virtualScrollItemSize", "optionGroupLabel", "optionGroupChildren", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
23603
23718
|
}
|
|
23604
23719
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: MapQuery, decorators: [{
|
|
23605
23720
|
type: Component,
|
|
@@ -28974,11 +29089,11 @@ class PropertiesCardComponent {
|
|
|
28974
29089
|
return '';
|
|
28975
29090
|
}
|
|
28976
29091
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
28977
|
-
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'\">\r\n @if (showTabs()) {\r\n <div class=\"mb-3\">\r\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @if (currentTabCards().length === 0) {\r\n <div class=\"py-6 text-center text-sm text-gray-400\">\r\n {{ t(\"noData\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-wrap\">\r\n @for (cardView of currentTabCards(); track cardView.trackId) {\r\n <div\r\n class=\"mb-2 cursor-pointer p-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\
|
|
29092
|
+
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'\">\r\n @if (showTabs()) {\r\n <div class=\"mb-3\">\r\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @if (currentTabCards().length === 0) {\r\n <div class=\"py-6 text-center text-sm text-gray-400\">\r\n {{ t(\"noData\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-wrap\">\r\n @for (cardView of currentTabCards(); track cardView.trackId) {\r\n <div\r\n class=\"mb-2 cursor-pointer p-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\n (click)=\"onCardClick(cardView.card)\"\n >\n <div class=\"rounded-lg bg-white p-3 shadow-sm\">\n @defer (on viewport) {\n <ng-container>\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 </ng-container>\n } @placeholder {\n <div class=\"min-h-24 p-2\">\n <div class=\"flex animate-pulse flex-col gap-3\">\n <div class=\"h-4 w-2/3 rounded bg-surface-200\"></div>\n <div class=\"h-4 w-full rounded bg-surface-100\"></div>\n <div class=\"h-4 w-5/6 rounded bg-surface-100\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\r\n </div>\r\n</ng-container>\r\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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [EntitiesPreview]] });
|
|
28978
29093
|
}
|
|
28979
29094
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesCardComponent, decorators: [{
|
|
28980
29095
|
type: Component,
|
|
28981
|
-
args: [{ selector: 'mt-properties-card, mt-entities-preview-card', standalone: true, imports: [CommonModule, TranslocoDirective, Tabs, EntitiesPreview], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n @if (showTabs()) {\r\n <div class=\"mb-3\">\r\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @if (currentTabCards().length === 0) {\r\n <div class=\"py-6 text-center text-sm text-gray-400\">\r\n {{ t(\"noData\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-wrap\">\r\n @for (cardView of currentTabCards(); track cardView.trackId) {\r\n <div\r\n class=\"mb-2 cursor-pointer p-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\
|
|
29096
|
+
args: [{ selector: 'mt-properties-card, mt-entities-preview-card', standalone: true, imports: [CommonModule, TranslocoDirective, Tabs, EntitiesPreview], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n @if (showTabs()) {\r\n <div class=\"mb-3\">\r\n <mt-tabs [(active)]=\"tabSelected\" [options]=\"tabOptions()\" size=\"small\" />\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"overflow-y-auto overflow-x-hidden\"\r\n [style.max-height]=\"inGroup() ? '500px' : '90%'\"\r\n >\r\n @if (currentTabCards().length === 0) {\r\n <div class=\"py-6 text-center text-sm text-gray-400\">\r\n {{ t(\"noData\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-wrap\">\r\n @for (cardView of currentTabCards(); track cardView.trackId) {\r\n <div\r\n class=\"mb-2 cursor-pointer p-2\"\r\n [class.card-col]=\"!galleryMode()\"\r\n [class.gallery-card-col]=\"galleryMode()\"\r\n [class.w-full]=\"!galleryMode()\"\r\n [class.md:w-1/2]=\"!galleryMode()\"\r\n [class.lg:w-1/3]=\"!galleryMode()\"\n (click)=\"onCardClick(cardView.card)\"\n >\n <div class=\"rounded-lg bg-white p-3 shadow-sm\">\n @defer (on viewport) {\n <ng-container>\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 </ng-container>\n } @placeholder {\n <div class=\"min-h-24 p-2\">\n <div class=\"flex animate-pulse flex-col gap-3\">\n <div class=\"h-4 w-2/3 rounded bg-surface-200\"></div>\n <div class=\"h-4 w-full rounded bg-surface-100\"></div>\n <div class=\"h-4 w-5/6 rounded bg-surface-100\"></div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\r\n </div>\r\n</ng-container>\r\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"] }]
|
|
28982
29097
|
}], ctorParameters: () => [], propDecorators: { dashboardId: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardId", required: true }] }], inGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "inGroup", required: false }] }], onAction: [{ type: i0.Output, args: ["onAction"] }] } });
|
|
28983
29098
|
|
|
28984
29099
|
const VIEW_TYPE_MAP = {
|
|
@@ -30107,7 +30222,7 @@ class ManageItem {
|
|
|
30107
30222
|
this._manageItemService.updateClientConfig(partialConfig);
|
|
30108
30223
|
}
|
|
30109
30224
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
30110
|
-
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'\">\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\n <!-- Main Layout: 60% Config | 40% Preview -->\n <div class=\"flex flex-1\">\n <!-- Left Side: Configuration (60%) -->\n <div
|
|
30225
|
+
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'\">\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\n <!-- Main Layout: 60% Config | 40% Preview -->\n <div class=\"flex flex-1\">\n <!-- Left Side: Configuration (60%) -->\n <div\n class=\"db-sectioned-drawer w-[60%] flex flex-col border-r border-surface-200\"\n >\n <!-- Content -->\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\n <!-- Chart Type Badge -->\n @if (selectedChartType()) {\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\n <span\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\n >\n <mt-icon\n [icon]=\"selectedChartType()?.icon\"\n class=\"text-xl\"\n ></mt-icon>\n </span>\n <div class=\"flex-1\">\n <h3 class=\"text-sm font-semibold text-surface-700\">\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\n </h3>\n <p class=\"text-xs text-muted-color\">\n {{ selectedChartType()?.name }}\n </p>\n </div>\n </div>\n }\n\n <!-- Tabs -->\n <mt-tabs\n [options]=\"tabOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [(active)]=\"activeTab\"\n />\n\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\n <div [hidden]=\"activeTab() !== 'general'\">\n <mt-general-settings\n [config]=\"config()\"\n [isDialog]=\"isDialog()\"\n [hasPreselectedType]=\"hasPreselectedType()\"\n (configChange)=\"onConfigUpdate($event)\"\n (chartTypeChange)=\"onChartTypeChange($event)\"\n />\n </div>\n\n <div [hidden]=\"activeTab() !== 'dataSource'\">\n <mt-data-source-settings\n [config]=\"config()\"\n [chartType]=\"selectedChartType()\"\n [informativeContext]=\"informativeContext()\"\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\n />\n </div>\n\n <div [hidden]=\"activeTab() !== 'actions'\">\n <mt-actions-settings\n [config]=\"config()\"\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Right Side: Chart Preview (40%) -->\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\n </div>\n </div>\n </div>\n <!-- Footer -->\n <div [class]=\"modal.footerClass\">\n <!-- Validation Status -->\n <div class=\"flex items-center gap-2 text-sm flex-1\">\n @if (isValid()) {\n <span class=\"flex items-center gap-1 text-green-600\">\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\n {{ t(\"ready\") }}\n </span>\n } @else {\n <span class=\"flex items-center gap-1 text-amber-600\">\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\n {{ t(\"incomplete\") }}\n </span>\n }\n </div>\n\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"cancel()\" />\n <mt-button\n [label]=\"t('save')\"\n icon=\"general.save-02\"\n [loading]=\"saving()\"\n [disabled]=\"!isValid()\"\n (onClick)=\"save()\"\n />\n </div>\n</ng-container>\n", styles: [".db-sectioned-drawer mt-card{overflow:hidden;border-color:var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);border-radius:.375rem}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1){padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1) h3{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}\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 });
|
|
30111
30226
|
}
|
|
30112
30227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ManageItem, decorators: [{
|
|
30113
30228
|
type: Component,
|
|
@@ -30122,7 +30237,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
30122
30237
|
ActionsSettings,
|
|
30123
30238
|
ChartViewer,
|
|
30124
30239
|
Icon,
|
|
30125
|
-
], providers: [ManageItemService], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\n <!-- Main Layout: 60% Config | 40% Preview -->\n <div class=\"flex flex-1\">\n <!-- Left Side: Configuration (60%) -->\n <div
|
|
30240
|
+
], providers: [ManageItemService], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\n <div class=\"flex flex-col h-full\" [class]=\"modal.contentClass\">\n <!-- Main Layout: 60% Config | 40% Preview -->\n <div class=\"flex flex-1\">\n <!-- Left Side: Configuration (60%) -->\n <div\n class=\"db-sectioned-drawer w-[60%] flex flex-col border-r border-surface-200\"\n >\n <!-- Content -->\n <div class=\"flex-1 flex flex-col gap-4 p-4 overflow-auto\">\n <!-- Chart Type Badge -->\n @if (selectedChartType()) {\n <div class=\"flex items-center gap-2 p-3 bg-surface-50 rounded-lg\">\n <span\n class=\"w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600\"\n >\n <mt-icon\n [icon]=\"selectedChartType()?.icon\"\n class=\"text-xl\"\n ></mt-icon>\n </span>\n <div class=\"flex-1\">\n <h3 class=\"text-sm font-semibold text-surface-700\">\n {{ isNew() ? t(\"newItem\") : t(\"editItem\") }}\n </h3>\n <p class=\"text-xs text-muted-color\">\n {{ selectedChartType()?.name }}\n </p>\n </div>\n </div>\n }\n\n <!-- Tabs -->\n <mt-tabs\n [options]=\"tabOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [(active)]=\"activeTab\"\n />\n\n <!-- Tab Content - All tabs rendered but hidden, prevents re-initialization -->\n <div [hidden]=\"activeTab() !== 'general'\">\n <mt-general-settings\n [config]=\"config()\"\n [isDialog]=\"isDialog()\"\n [hasPreselectedType]=\"hasPreselectedType()\"\n (configChange)=\"onConfigUpdate($event)\"\n (chartTypeChange)=\"onChartTypeChange($event)\"\n />\n </div>\n\n <div [hidden]=\"activeTab() !== 'dataSource'\">\n <mt-data-source-settings\n [config]=\"config()\"\n [chartType]=\"selectedChartType()\"\n [informativeContext]=\"informativeContext()\"\n (serviceConfigChange)=\"onServiceConfigUpdate($event)\"\n />\n </div>\n\n <div [hidden]=\"activeTab() !== 'actions'\">\n <mt-actions-settings\n [config]=\"config()\"\n (clientConfigChange)=\"onClientConfigUpdate($event)\"\n />\n </div>\n </div>\n </div>\n\n <!-- Right Side: Chart Preview (40%) -->\n <div class=\"w-[40%] min-w-[350px] h-[500px]\">\n <mt-chart-viewer [config]=\"config()\" [chartTypeId]=\"chartTypeId()\" />\n </div>\n </div>\n </div>\n <!-- Footer -->\n <div [class]=\"modal.footerClass\">\n <!-- Validation Status -->\n <div class=\"flex items-center gap-2 text-sm flex-1\">\n @if (isValid()) {\n <span class=\"flex items-center gap-1 text-green-600\">\n <mt-icon icon=\"general.check-circle\" class=\"text-base\" />\n {{ t(\"ready\") }}\n </span>\n } @else {\n <span class=\"flex items-center gap-1 text-amber-600\">\n <mt-icon icon=\"general.alert-circle\" class=\"text-base\" />\n {{ t(\"incomplete\") }}\n </span>\n }\n </div>\n\n <mt-button [label]=\"t('cancel')\" variant=\"outlined\" (onClick)=\"cancel()\" />\n <mt-button\n [label]=\"t('save')\"\n icon=\"general.save-02\"\n [loading]=\"saving()\"\n [disabled]=\"!isValid()\"\n (onClick)=\"save()\"\n />\n </div>\n</ng-container>\n", styles: [".db-sectioned-drawer mt-card{overflow:hidden;border-color:var(--p-surface-200, #e5e7eb);background:var(--p-surface-0, #fff);border-radius:.375rem}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1){padding:.75rem 1rem;border-bottom:1px solid var(--p-surface-200, #e5e7eb);background:var(--p-surface-50, #f9fafb)}.db-sectioned-drawer mt-card>div>div:first-child:not(.flex-1) h3{margin:0;font-size:1.125rem;line-height:1.75rem;font-weight:600;color:var(--p-text-color, #111827)}\n"] }]
|
|
30126
30241
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
|
|
30127
30242
|
|
|
30128
30243
|
class TitleEditor {
|
|
@@ -30201,11 +30316,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
30201
30316
|
* Primary entries (always present for chart cards):
|
|
30202
30317
|
* - Configure datasource → opens ManageItem advanced editor
|
|
30203
30318
|
* - Style → opens ChartSettingsDrawer
|
|
30204
|
-
* - Filters → opens ChartFilterDrawer
|
|
30205
30319
|
* - Edit title → focuses inline title input
|
|
30206
30320
|
* - Duplicate → host duplicates the chart
|
|
30207
30321
|
* - Delete → host deletes the chart (severity: danger)
|
|
30208
30322
|
*
|
|
30323
|
+
* The Filters action still routes to ChartFilterDrawer when emitted, but its
|
|
30324
|
+
* menu entry is currently hidden from the chart-card action menu.
|
|
30325
|
+
*
|
|
30209
30326
|
* Optional dialog entries (only when the chart has a linked dialog):
|
|
30210
30327
|
* - Open dialog
|
|
30211
30328
|
* - Edit dialog
|
|
@@ -30213,6 +30330,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
30213
30330
|
*/
|
|
30214
30331
|
class ItemCardMenuComponent {
|
|
30215
30332
|
transloco = inject(TranslocoService);
|
|
30333
|
+
filtersActionVisible = false;
|
|
30216
30334
|
/** Whether to allow duplicate (excluded for layout/group widgets). */
|
|
30217
30335
|
allowDuplicate = input(true, ...(ngDevMode ? [{ debugName: "allowDuplicate" }] : /* istanbul ignore next */ []));
|
|
30218
30336
|
/** Whether the chart has a linked dialog already. */
|
|
@@ -30239,17 +30357,19 @@ class ItemCardMenuComponent {
|
|
|
30239
30357
|
label: t('style'),
|
|
30240
30358
|
icon: 'editor.palette',
|
|
30241
30359
|
},
|
|
30242
|
-
{
|
|
30243
|
-
id: 'filters',
|
|
30244
|
-
label: t('filters'),
|
|
30245
|
-
icon: 'general.filter-funnel-01',
|
|
30246
|
-
},
|
|
30247
30360
|
{
|
|
30248
30361
|
id: 'edit-title',
|
|
30249
30362
|
label: t('editTitle'),
|
|
30250
30363
|
icon: 'general.edit-05',
|
|
30251
30364
|
},
|
|
30252
30365
|
];
|
|
30366
|
+
if (this.filtersActionVisible) {
|
|
30367
|
+
items.splice(2, 0, {
|
|
30368
|
+
id: 'filters',
|
|
30369
|
+
label: t('filters'),
|
|
30370
|
+
icon: 'general.filter-funnel-01',
|
|
30371
|
+
});
|
|
30372
|
+
}
|
|
30253
30373
|
if (this.allowDuplicate()) {
|
|
30254
30374
|
items.push({
|
|
30255
30375
|
id: 'duplicate',
|
|
@@ -34480,6 +34600,10 @@ class DashboardBuilder {
|
|
|
34480
34600
|
}
|
|
34481
34601
|
return true;
|
|
34482
34602
|
}
|
|
34603
|
+
isPropertiesListChart(chart) {
|
|
34604
|
+
const componentName = chart.config?.clientConfig?.componentName;
|
|
34605
|
+
return componentName === 'listOfLevelCards' || componentName === 'entitiesPreview';
|
|
34606
|
+
}
|
|
34483
34607
|
editItem(chart, parentItem, defaultTab) {
|
|
34484
34608
|
this.dashboardService.chartForSelectedDialog.set(parentItem);
|
|
34485
34609
|
this.prefetchModulesTree(this.resolveWorkspaceId(chart.config));
|
|
@@ -34890,12 +35014,11 @@ class DashboardBuilder {
|
|
|
34890
35014
|
openManageFilter() {
|
|
34891
35015
|
const ref = this.modalService.openModal(ManageFilterOnPage, 'drawer', {
|
|
34892
35016
|
header: this.transloco.translate('dashboardBuilder.manageFilter'),
|
|
34893
|
-
styleClass: '!w-
|
|
35017
|
+
styleClass: '!w-[56rem] max-w-[96vw] !absolute',
|
|
34894
35018
|
appendTo: '#page-content',
|
|
34895
35019
|
position: 'end',
|
|
34896
35020
|
inputValues: {
|
|
34897
35021
|
data: this.filtersConfig() || [],
|
|
34898
|
-
chartItems: [...this.charts(), ...this.dialogs()],
|
|
34899
35022
|
},
|
|
34900
35023
|
});
|
|
34901
35024
|
ref.onClose.subscribe((result) => {
|
|
@@ -35528,7 +35651,7 @@ class DashboardBuilder {
|
|
|
35528
35651
|
return current;
|
|
35529
35652
|
}
|
|
35530
35653
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DashboardBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
35531
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DashboardBuilder, isStandalone: true, selector: "mt-dashboard-builder", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, backButton: { classPropertyName: "backButton", publicName: "backButton", isSignal: true, isRequired: false, transformFunction: null }, pageId: { classPropertyName: "pageId", publicName: "pageId", isSignal: true, isRequired: false, transformFunction: null }, standalone: { classPropertyName: "standalone", publicName: "standalone", isSignal: true, isRequired: false, transformFunction: null }, services: { classPropertyName: "services", publicName: "services", isSignal: true, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, informativeContext: { classPropertyName: "informativeContext", publicName: "informativeContext", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardData: "dashboardDataChange", pageChange: "pageChange", chartsChange: "chartsChange", onSave: "onSave", onBack: "onBack", onAddChart: "onAddChart", onEditChart: "onEditChart" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "gridsterContainer", first: true, predicate: ["gridsterContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\r\n [item]=\"chart\"\r\n class=\"db-gridster-item bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden hover:shadow-md hover:border-surface-300\"\r\n [class.ring-2]=\"isSelected(chart)\"\r\n [class.ring-primary]=\"isSelected(chart)\"\r\n [class.ring-offset-2]=\"isSelected(chart)\"\r\n [attr.data-chart-id]=\"chart.config?.serviceConfig?.dashboardId\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!--\r\n Pass 7 \u2014 Single top-end Manage menu per chart card.\r\n Layout widgets (header/topbar/group) keep their dedicated\r\n affordances; chart cards have **only** the kebab.\r\n -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"db-card-actions absolute top-1 end-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Single kebab for chart cards (Pass 7 sole owner). -->\r\n @if (showContextToolbar(chart)) {\r\n <mt-item-card-menu\r\n [allowDuplicate]=\"true\"\r\n [hasLinkedDialog]=\"hasLinkedDialog(chart)\"\r\n [canLinkDialog]=\"canLinkDialog(chart)\"\r\n (action)=\"onItemCardMenuAction(chart, $event)\"\r\n />\r\n }\r\n\r\n <!-- Topbar: breadcrumb editor (layout-specific). -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!--\r\n Header / topbar \u2014 quick style + delete.\r\n These widgets don't have a datasource so they don't\r\n use the chart kebab; the affordances stay minimal.\r\n -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"header\" ||\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('actions.editTitle')\"\r\n (onClick)=\"requestLayoutTitleEdit(chart, $event)\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('actions.style')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('actions.delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"configureChart(chart)\"\r\n (titleEdited)=\"onChartTitleEdited(chart, $event)\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"\r\n editItem(childChart, chart, 'dataSource')\r\n \"\r\n (titleEdited)=\"\r\n onChartTitleEdited(childChart, $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}gridster-item.db-gridster-item{transition:none!important}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}.db-card-actions{pointer-events:auto;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.25rem;max-width:calc(100% - 2.5rem)}@media(max-width:640px){.db-card-actions{top:.25rem;right:.25rem}}.db-card-title-edit{background:transparent;border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.375rem;padding:.25rem .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);text-align:center;width:min(100%,22rem);outline:none}.db-card-title-edit:focus{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff)}.mt-item-config-popover-host .p-dialog-content{padding:0!important;height:clamp(420px,70vh,720px);max-height:80vh}.mt-item-config-popover-host .p-dialog-header{display:none}@media(max-width:768px){.mt-item-config-popover-host{width:100%!important;max-width:100%!important;margin:0!important;inset:auto 0 0!important;border-radius:1rem 1rem 0 0!important;transform:none!important}.mt-item-config-popover-host .p-dialog-content{height:80vh;border-radius:1rem 1rem 0 0}}.db-context-popover{--p-popover-content-padding: .4rem;min-width:200px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: GridsterModule }, { kind: "component", type: i2$2.GridsterComponent, selector: "gridster", inputs: ["options"] }, { kind: "component", type: i2$2.GridsterItemComponent, selector: "gridster-item", inputs: ["item"], outputs: ["itemInit", "itemChange", "itemResize"] }, { 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: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i3$1.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "pageName", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter", "builderMode"], outputs: ["actionTriggered", "configureRequested", "titleEdited"] }, { kind: "component", type: ItemCardMenuComponent, selector: "mt-item-card-menu", inputs: ["allowDuplicate", "hasLinkedDialog", "canLinkDialog"], outputs: ["action"] }, { kind: "pipe", type: FilterByGroupPipe, name: "filterByGroup" }], encapsulation: i0.ViewEncapsulation.None });
|
|
35654
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: DashboardBuilder, isStandalone: true, selector: "mt-dashboard-builder", inputs: { isPage: { classPropertyName: "isPage", publicName: "isPage", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, backButton: { classPropertyName: "backButton", publicName: "backButton", isSignal: true, isRequired: false, transformFunction: null }, pageId: { classPropertyName: "pageId", publicName: "pageId", isSignal: true, isRequired: false, transformFunction: null }, standalone: { classPropertyName: "standalone", publicName: "standalone", isSignal: true, isRequired: false, transformFunction: null }, services: { classPropertyName: "services", publicName: "services", isSignal: true, isRequired: false, transformFunction: null }, dashboardData: { classPropertyName: "dashboardData", publicName: "dashboardData", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, informativeContext: { classPropertyName: "informativeContext", publicName: "informativeContext", isSignal: true, isRequired: false, transformFunction: null }, extraFilters: { classPropertyName: "extraFilters", publicName: "extraFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dashboardData: "dashboardDataChange", pageChange: "pageChange", chartsChange: "chartsChange", onSave: "onSave", onBack: "onBack", onAddChart: "onAddChart", onEditChart: "onEditChart" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true, isSignal: true }, { propertyName: "gridsterContainer", first: true, predicate: ["gridsterContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\n [item]=\"chart\"\n class=\"db-gridster-item bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden hover:shadow-md hover:border-surface-300\"\n [class.db-gridster-item--properties-list]=\"\n isPropertiesListChart(chart)\n \"\n [class.ring-2]=\"isSelected(chart)\"\n [class.ring-primary]=\"isSelected(chart)\"\n [class.ring-offset-2]=\"isSelected(chart)\"\n [attr.data-chart-id]=\"chart.config?.serviceConfig?.dashboardId\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!--\r\n Pass 7 \u2014 Single top-end Manage menu per chart card.\r\n Layout widgets (header/topbar/group) keep their dedicated\r\n affordances; chart cards have **only** the kebab.\r\n -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"db-card-actions absolute top-1 end-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Single kebab for chart cards (Pass 7 sole owner). -->\r\n @if (showContextToolbar(chart)) {\r\n <mt-item-card-menu\r\n [allowDuplicate]=\"true\"\r\n [hasLinkedDialog]=\"hasLinkedDialog(chart)\"\r\n [canLinkDialog]=\"canLinkDialog(chart)\"\r\n (action)=\"onItemCardMenuAction(chart, $event)\"\r\n />\r\n }\r\n\r\n <!-- Topbar: breadcrumb editor (layout-specific). -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!--\r\n Header / topbar \u2014 quick style + delete.\r\n These widgets don't have a datasource so they don't\r\n use the chart kebab; the affordances stay minimal.\r\n -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"header\" ||\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('actions.editTitle')\"\r\n (onClick)=\"requestLayoutTitleEdit(chart, $event)\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('actions.style')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('actions.delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"configureChart(chart)\"\r\n (titleEdited)=\"onChartTitleEdited(chart, $event)\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"\r\n editItem(childChart, chart, 'dataSource')\r\n \"\r\n (titleEdited)=\"\r\n onChartTitleEdited(childChart, $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}gridster-item.db-gridster-item{transition:none!important}gridster-item.db-gridster-item.db-gridster-item--properties-list{background:transparent!important;border-color:transparent!important;border-radius:0!important;box-shadow:none!important;overflow:visible!important}gridster-item.db-gridster-item.db-gridster-item--properties-list:hover{border-color:transparent!important;box-shadow:none!important}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}.db-card-actions{pointer-events:auto;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.25rem;max-width:calc(100% - 2.5rem)}@media(max-width:640px){.db-card-actions{top:.25rem;right:.25rem}}.db-card-title-edit{background:transparent;border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.375rem;padding:.25rem .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);text-align:center;width:min(100%,22rem);outline:none}.db-card-title-edit:focus{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff)}.mt-item-config-popover-host .p-dialog-content{padding:0!important;height:clamp(420px,70vh,720px);max-height:80vh}.mt-item-config-popover-host .p-dialog-header{display:none}@media(max-width:768px){.mt-item-config-popover-host{width:100%!important;max-width:100%!important;margin:0!important;inset:auto 0 0!important;border-radius:1rem 1rem 0 0!important;transform:none!important}.mt-item-config-popover-host .p-dialog-content{height:80vh;border-radius:1rem 1rem 0 0}}.db-context-popover{--p-popover-content-padding: .4rem;min-width:200px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: GridsterModule }, { kind: "component", type: i2$2.GridsterComponent, selector: "gridster", inputs: ["options"] }, { kind: "component", type: i2$2.GridsterItemComponent, selector: "gridster-item", inputs: ["item"], outputs: ["itemInit", "itemChange", "itemResize"] }, { 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: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i3$1.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: DashboardItem, selector: "mt-dashboard-item", inputs: ["config", "chartTypeId", "readonly", "pageName", "inGroup", "isDialog", "queryParams", "extraFilters", "ignoreQueryFilter", "builderMode"], outputs: ["actionTriggered", "configureRequested", "titleEdited"] }, { kind: "component", type: ItemCardMenuComponent, selector: "mt-item-card-menu", inputs: ["allowDuplicate", "hasLinkedDialog", "canLinkDialog"], outputs: ["action"] }, { kind: "pipe", type: FilterByGroupPipe, name: "filterByGroup" }], encapsulation: i0.ViewEncapsulation.None });
|
|
35532
35655
|
}
|
|
35533
35656
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: DashboardBuilder, decorators: [{
|
|
35534
35657
|
type: Component,
|
|
@@ -35543,7 +35666,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
35543
35666
|
FilterByGroupPipe,
|
|
35544
35667
|
DashboardItem,
|
|
35545
35668
|
ItemCardMenuComponent,
|
|
35546
|
-
], encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\r\n [item]=\"chart\"\r\n class=\"db-gridster-item bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden hover:shadow-md hover:border-surface-300\"\r\n [class.ring-2]=\"isSelected(chart)\"\r\n [class.ring-primary]=\"isSelected(chart)\"\r\n [class.ring-offset-2]=\"isSelected(chart)\"\r\n [attr.data-chart-id]=\"chart.config?.serviceConfig?.dashboardId\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!--\r\n Pass 7 \u2014 Single top-end Manage menu per chart card.\r\n Layout widgets (header/topbar/group) keep their dedicated\r\n affordances; chart cards have **only** the kebab.\r\n -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"db-card-actions absolute top-1 end-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Single kebab for chart cards (Pass 7 sole owner). -->\r\n @if (showContextToolbar(chart)) {\r\n <mt-item-card-menu\r\n [allowDuplicate]=\"true\"\r\n [hasLinkedDialog]=\"hasLinkedDialog(chart)\"\r\n [canLinkDialog]=\"canLinkDialog(chart)\"\r\n (action)=\"onItemCardMenuAction(chart, $event)\"\r\n />\r\n }\r\n\r\n <!-- Topbar: breadcrumb editor (layout-specific). -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!--\r\n Header / topbar \u2014 quick style + delete.\r\n These widgets don't have a datasource so they don't\r\n use the chart kebab; the affordances stay minimal.\r\n -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"header\" ||\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('actions.editTitle')\"\r\n (onClick)=\"requestLayoutTitleEdit(chart, $event)\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('actions.style')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('actions.delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"configureChart(chart)\"\r\n (titleEdited)=\"onChartTitleEdited(chart, $event)\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"\r\n editItem(childChart, chart, 'dataSource')\r\n \"\r\n (titleEdited)=\"\r\n onChartTitleEdited(childChart, $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}gridster-item.db-gridster-item{transition:none!important}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}.db-card-actions{pointer-events:auto;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.25rem;max-width:calc(100% - 2.5rem)}@media(max-width:640px){.db-card-actions{top:.25rem;right:.25rem}}.db-card-title-edit{background:transparent;border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.375rem;padding:.25rem .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);text-align:center;width:min(100%,22rem);outline:none}.db-card-title-edit:focus{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff)}.mt-item-config-popover-host .p-dialog-content{padding:0!important;height:clamp(420px,70vh,720px);max-height:80vh}.mt-item-config-popover-host .p-dialog-header{display:none}@media(max-width:768px){.mt-item-config-popover-host{width:100%!important;max-width:100%!important;margin:0!important;inset:auto 0 0!important;border-radius:1rem 1rem 0 0!important;transform:none!important}.mt-item-config-popover-host .p-dialog-content{height:80vh;border-radius:1rem 1rem 0 0}}.db-context-popover{--p-popover-content-padding: .4rem;min-width:200px}\n"] }]
|
|
35669
|
+
], encapsulation: ViewEncapsulation.None, template: "<ng-container *transloco=\"let t; prefix: 'dashboardBuilder'\">\r\n <!-- Shared Actions Template -->\r\n <ng-template #actionsTemplate let-inPage=\"inPage\">\r\n <mt-button\r\n [label]=\"t('addWidget')\"\r\n icon=\"general.plus\"\r\n (onClick)=\"toggleWidgetPalette()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"t('save')\"\r\n icon=\"general.save-02\"\r\n [loading]=\"saving()\"\r\n [disabled]=\"saving()\"\r\n (onClick)=\"saveDash()\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <span [class]=\"'w-px h-5 bg-surface-300'\"></span>\r\n\r\n <mt-button\r\n [icon]=\"stopActionsOnCards() ? 'media.play' : 'media.stop'\"\r\n [tooltip]=\"stopActionsOnCards() ? t('activateActions') : t('stopActions')\"\r\n (onClick)=\"stopAndActiveActions()\"\r\n [severity]=\"'warn'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('pageSettings')\"\r\n (onClick)=\"addOrEditPage(pageConfig()!)\"\r\n [severity]=\"'help'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n\r\n <mt-button\r\n icon=\"general.filter-lines\"\r\n [tooltip]=\"t('manageFilter')\"\r\n (onClick)=\"openManageFilter()\"\r\n [severity]=\"'info'\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [rounded]=\"!inPage\"\r\n />\r\n </ng-template>\r\n\r\n <!-- Page mode -->\r\n @if (isPage()) {\r\n <mt-page\r\n [title]=\"\r\n pageTitle() ||\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n t('builder')\r\n \"\r\n [backButton]=\"backButton()\"\r\n (backButtonClick)=\"onBack.emit()\"\r\n >\r\n <!-- Header actions -->\r\n <ng-template #headerEnd>\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: true }\"\r\n />\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Content -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n </mt-page>\r\n } @else {\r\n <!-- Non-page mode -->\r\n <ng-container *ngTemplateOutlet=\"builderContent\" />\r\n }\r\n\r\n <!-- Reusable builder content template -->\r\n <ng-template #builderContent>\r\n <div class=\"relative h-full min-h-[600px]\">\r\n <!-- Loading State -->\r\n @if (loading()) {\r\n <div class=\"flex items-center justify-center h-64\">\r\n <i class=\"mti mti-spinner-third mti-spin text-4xl text-primary\"></i>\r\n </div>\r\n }\r\n\r\n <!-- Main Content -->\r\n @if (!loading() && pageConfig()) {\r\n <!-- Fixed Actions Bar (only when NOT page mode) -->\r\n @if (!isPage()) {\r\n <div\r\n class=\"fixed bottom-4 left-1/2 -translate-x-1/2 z-50 flex items-center gap-2 bg-surface-0 rounded-full shadow-lg px-4 py-2 border border-surface-200\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"actionsTemplate; context: { inPage: false }\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Gridster Container -->\r\n <gridster\r\n #gridsterContainer\r\n [options]=\"options\"\r\n class=\"h-full min-h-[500px] bg-surface-50!\"\r\n [class.is-page]=\"isPage()\"\r\n [class.pointer-events-none]=\"readonly()\"\r\n (dragover)=\"onGridDragOver($event)\"\r\n (drop)=\"onGridDrop($event)\"\r\n >\r\n @for (chart of charts() | filterByGroup: undefined; track $index) {\r\n <gridster-item\n [item]=\"chart\"\n class=\"db-gridster-item bg-surface-0 rounded-lg shadow-sm border border-surface-200 overflow-hidden hover:shadow-md hover:border-surface-300\"\n [class.db-gridster-item--properties-list]=\"\n isPropertiesListChart(chart)\n \"\n [class.ring-2]=\"isSelected(chart)\"\n [class.ring-primary]=\"isSelected(chart)\"\n [class.ring-offset-2]=\"isSelected(chart)\"\n [attr.data-chart-id]=\"chart.config?.serviceConfig?.dashboardId\"\r\n (click)=\"onSelect(chart, $event)\"\r\n >\r\n <!-- Chart Content -->\r\n <div class=\"h-full w-full relative group\">\r\n <!-- Drag Handle -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"drag-handler absolute top-0 left-0 right-0 h-6 cursor-move bg-gradient-to-b from-black/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center z-10\"\r\n >\r\n <i\r\n class=\"mti mti-grip-horizontal text-white/70 text-sm\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!--\r\n Pass 7 \u2014 Single top-end Manage menu per chart card.\r\n Layout widgets (header/topbar/group) keep their dedicated\r\n affordances; chart cards have **only** the kebab.\r\n -->\r\n @if (!readonly()) {\r\n <div\r\n class=\"db-card-actions absolute top-1 end-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity z-20\"\r\n >\r\n <!-- Single kebab for chart cards (Pass 7 sole owner). -->\r\n @if (showContextToolbar(chart)) {\r\n <mt-item-card-menu\r\n [allowDuplicate]=\"true\"\r\n [hasLinkedDialog]=\"hasLinkedDialog(chart)\"\r\n [canLinkDialog]=\"canLinkDialog(chart)\"\r\n (action)=\"onItemCardMenuAction(chart, $event)\"\r\n />\r\n }\r\n\r\n <!-- Topbar: breadcrumb editor (layout-specific). -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.slash-divider\"\r\n [tooltip]=\"t('manageBreadcrumb')\"\r\n (onClick)=\"openBreadcrumb(chart)\"\r\n severity=\"info\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n <!--\r\n Header / topbar \u2014 quick style + delete.\r\n These widgets don't have a datasource so they don't\r\n use the chart kebab; the affordances stay minimal.\r\n -->\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"header\" ||\r\n chart.config?.clientConfig?.componentName === \"topbar\"\r\n ) {\r\n <mt-button\r\n icon=\"general.edit-05\"\r\n [tooltip]=\"t('actions.editTitle')\"\r\n (onClick)=\"requestLayoutTitleEdit(chart, $event)\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"editor.palette\"\r\n [tooltip]=\"t('actions.style')\"\r\n (onClick)=\"openQuickManage($event, chart)\"\r\n severity=\"primary\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('actions.delete')\"\r\n (onClick)=\"deleteItem(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n\r\n @if (\r\n chart.config?.clientConfig?.componentName === \"Group\"\r\n ) {\r\n <mt-button\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"t('removeGroup')\"\r\n (onClick)=\"removeGroup(chart)\"\r\n severity=\"danger\"\r\n size=\"small\"\r\n [rounded]=\"true\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Chart Rendering -->\r\n @if (!chart.loading) {\r\n <mt-dashboard-item\r\n [config]=\"chart.config\"\r\n [chartTypeId]=\"chart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"configureChart(chart)\"\r\n (titleEdited)=\"onChartTitleEdited(chart, $event)\"\r\n />\r\n } @else {\r\n <div class=\"flex items-center justify-center h-full\">\r\n <i\r\n class=\"mti mti-spinner-third mti-spin text-2xl text-primary\"\r\n ></i>\r\n </div>\r\n }\r\n\r\n <!-- Group Children -->\r\n @if (chart.config?.clientConfig?.componentName === \"Group\") {\r\n <div class=\"h-full flex flex-col p-2\">\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n @if (idx === chart.selectedGroupIndex) {\r\n <div class=\"flex-1 min-h-0\">\r\n <mt-dashboard-item\r\n [config]=\"childChart.config\"\r\n [chartTypeId]=\"childChart.chartTypeId\"\r\n [readonly]=\"readonly()\"\r\n [builderMode]=\"!readonly()\"\r\n [extraFilters]=\"extraFilters()\"\r\n [pageName]=\"\r\n pageConfig()?.name?.[languageCode()] ||\r\n pageConfig()?.name?.['en'] ||\r\n pageConfig()?.name?.['ar'] ||\r\n ''\r\n \"\r\n (configureRequested)=\"\r\n editItem(childChart, chart, 'dataSource')\r\n \"\r\n (titleEdited)=\"\r\n onChartTitleEdited(childChart, $event)\r\n \"\r\n />\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Group Tabs -->\r\n <div\r\n class=\"absolute bottom-0 left-0 right-0 flex gap-1 p-1 bg-surface-100 rounded-b-lg overflow-x-auto\"\r\n >\r\n @for (\r\n childChart of charts()\r\n | filterByGroup\r\n : chart.config?.serviceConfig?.dashboardId;\r\n track childChart.config?.serviceConfig?.dashboardId;\r\n let idx = $index\r\n ) {\r\n <mt-button\r\n [label]=\"\r\n childChart.config?.clientConfig?.title?.[\r\n languageCode()\r\n ] ||\r\n childChart.config?.clientConfig?.title?.['en'] ||\r\n 'Chart ' + (idx + 1)\r\n \"\r\n [severity]=\"\r\n idx === chart.selectedGroupIndex\r\n ? 'primary'\r\n : 'secondary'\r\n \"\r\n [text]=\"idx !== chart.selectedGroupIndex\"\r\n size=\"small\"\r\n (onClick)=\"chart.selectedGroupIndex = idx\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </gridster-item>\r\n }\r\n </gridster>\r\n\r\n <!-- Context Menu -->\r\n <p-contextMenu #contextMenu [model]=\"menuItems()\" appendTo=\"body\" />\r\n }\r\n\r\n <!-- Empty State -->\r\n @if (!loading() && !pageConfig()) {\r\n <div\r\n class=\"flex flex-col items-center justify-center h-64 text-muted-color\"\r\n >\r\n <i class=\"mti mti-layout text-6xl mb-4\"></i>\r\n <p class=\"text-lg\">{{ t(\"noPageSelected\") }}</p>\r\n <p class=\"text-sm\">{{ t(\"selectPageToStart\") }}</p>\r\n </div>\r\n }\r\n </div>\r\n </ng-template>\r\n</ng-container>\r\n", styles: [":host{display:block;height:100%}gridster{min-height:calc(100vh - 120px);height:100%}gridster .gridster-column{border-left:1px solid var(--p-primary-100)!important;border-right:1px solid var(--p-primary-100)!important}gridster .gridster-row{border-top:1px solid var(--p-primary-100)!important;border-bottom:1px solid var(--p-primary-100)!important}gridster.is-page{min-height:calc(100vh - 200px)}gridster-item.db-gridster-item{transition:none!important}gridster-item.db-gridster-item.db-gridster-item--properties-list{background:transparent!important;border-color:transparent!important;border-radius:0!important;box-shadow:none!important;overflow:visible!important}gridster-item.db-gridster-item.db-gridster-item--properties-list:hover{border-color:transparent!important;box-shadow:none!important}.mti-spin{animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.gridster-drop-indicator{position:absolute;background:var(--p-primary-100);border:2px dashed var(--p-primary-400);border-radius:8px;pointer-events:none;z-index:100}.db-card-actions{pointer-events:auto;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:.25rem;max-width:calc(100% - 2.5rem)}@media(max-width:640px){.db-card-actions{top:.25rem;right:.25rem}}.db-card-title-edit{background:transparent;border:1px dashed var(--p-surface-300, #d1d5db);border-radius:.375rem;padding:.25rem .5rem;font-size:.95rem;font-weight:600;color:var(--p-text-color, #1f2937);text-align:center;width:min(100%,22rem);outline:none}.db-card-title-edit:focus{border-color:var(--p-primary-500, #3b82f6);background:var(--p-primary-50, #eff6ff)}.mt-item-config-popover-host .p-dialog-content{padding:0!important;height:clamp(420px,70vh,720px);max-height:80vh}.mt-item-config-popover-host .p-dialog-header{display:none}@media(max-width:768px){.mt-item-config-popover-host{width:100%!important;max-width:100%!important;margin:0!important;inset:auto 0 0!important;border-radius:1rem 1rem 0 0!important;transform:none!important}.mt-item-config-popover-host .p-dialog-content{height:80vh;border-radius:1rem 1rem 0 0}}.db-context-popover{--p-popover-content-padding: .4rem;min-width:200px}\n"] }]
|
|
35547
35670
|
}], ctorParameters: () => [], propDecorators: { isPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPage", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], backButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "backButton", required: false }] }], pageId: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageId", required: false }] }], standalone: [{ type: i0.Input, args: [{ isSignal: true, alias: "standalone", required: false }] }], services: [{ type: i0.Input, args: [{ isSignal: true, alias: "services", required: false }] }], dashboardData: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardData", required: false }] }, { type: i0.Output, args: ["dashboardDataChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], informativeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "informativeContext", required: false }] }], extraFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraFilters", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], chartsChange: [{ type: i0.Output, args: ["chartsChange"] }], onSave: [{ type: i0.Output, args: ["onSave"] }], onBack: [{ type: i0.Output, args: ["onBack"] }], onAddChart: [{ type: i0.Output, args: ["onAddChart"] }], onEditChart: [{ type: i0.Output, args: ["onEditChart"] }], contextMenu: [{ type: i0.ViewChild, args: ['contextMenu', { isSignal: true }] }], gridsterContainer: [{ type: i0.ViewChild, args: ['gridsterContainer', { isSignal: true }] }], onKeyDown: [{
|
|
35548
35671
|
type: HostListener,
|
|
35549
35672
|
args: ['window:keydown', ['$event']]
|