@masterteam/dashboard-builder 0.0.41 → 0.0.42
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 = [
|
|
@@ -3785,71 +3576,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
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", "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
|
|
@@ -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
|
|
@@ -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']]
|