@oneteme/jquery-organizer 0.0.1 → 0.0.2
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.
- package/README.md +159 -60
- package/esm2022/lib/models/organizer-chart-adapter.mjs +37 -3
- package/esm2022/lib/models/organizer-config.interface.mjs +1 -1
- package/esm2022/lib/models/organizer-utils.mjs +127 -1
- package/esm2022/lib/organizer-button/organizer-button.component.mjs +38 -18
- package/esm2022/lib/organizer-button/template-manager.utility.mjs +7 -0
- package/esm2022/public-api.mjs +2 -2
- package/fesm2022/oneteme-jquery-organizer.mjs +229 -45
- package/fesm2022/oneteme-jquery-organizer.mjs.map +1 -1
- package/lib/models/organizer-chart-adapter.d.ts +10 -0
- package/lib/models/organizer-config.interface.d.ts +1 -0
- package/lib/models/organizer-utils.d.ts +4 -1
- package/lib/organizer-button/organizer-button.component.d.ts +1 -0
- package/lib/organizer-button/template-manager.utility.d.ts +4 -0
- package/package.json +1 -1
- package/public-api.d.ts +1 -1
|
@@ -12,6 +12,164 @@ import { MatDividerModule } from '@angular/material/divider';
|
|
|
12
12
|
import { Subject, isObservable, take, takeUntil as takeUntil$1 } from 'rxjs';
|
|
13
13
|
import { takeUntil } from 'rxjs/operators';
|
|
14
14
|
|
|
15
|
+
function buildYFields(indicators) {
|
|
16
|
+
const ordered = [];
|
|
17
|
+
const map = new Map();
|
|
18
|
+
for (const indicator of indicators) {
|
|
19
|
+
const groupKey = indicator.group;
|
|
20
|
+
if (groupKey) {
|
|
21
|
+
if (!map.has(groupKey)) {
|
|
22
|
+
ordered.push(groupKey);
|
|
23
|
+
map.set(groupKey, { id: groupKey, label: groupKey, aggregates: [] });
|
|
24
|
+
}
|
|
25
|
+
const parent = map.get(groupKey);
|
|
26
|
+
if (parent?.aggregates) {
|
|
27
|
+
parent.aggregates.push({ id: indicator.id, label: indicator.label });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
ordered.push(indicator.id);
|
|
32
|
+
map.set(indicator.id, { id: indicator.id, label: indicator.label });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return ordered.map(k => map.get(k)).filter((f) => !!f);
|
|
36
|
+
}
|
|
37
|
+
function resolveYKey(selectedY, selectedYAggregate) {
|
|
38
|
+
return selectedYAggregate ?? selectedY;
|
|
39
|
+
}
|
|
40
|
+
function normalizeOrganizerState(state, config) {
|
|
41
|
+
const base = state || {};
|
|
42
|
+
const normalizedY = normalizeYSelection(base.selectedY, base.selectedYAggregate, config.yFields);
|
|
43
|
+
const selectedX = hasOption(config.xFields, base.selectedX) ? base.selectedX : undefined;
|
|
44
|
+
const selectedGroupBy = hasOption(config.groups, base.selectedGroupBy) ? base.selectedGroupBy : undefined;
|
|
45
|
+
const selectedSlices = (base.selectedSlices || []).filter(sliceId => hasOption(config.slices, sliceId));
|
|
46
|
+
const normalized = {
|
|
47
|
+
...base,
|
|
48
|
+
selectedX,
|
|
49
|
+
selectedY: normalizedY.selectedY,
|
|
50
|
+
selectedYAggregate: normalizedY.selectedYAggregate,
|
|
51
|
+
selectedGroupBy,
|
|
52
|
+
selectedSlices,
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
...normalized,
|
|
56
|
+
selectedTemplate: resolveMatchingTemplateId(config.templates, normalized, config)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function normalizeTemplateToState(template, currentState, config) {
|
|
60
|
+
const base = normalizeOrganizerState(currentState, config);
|
|
61
|
+
const normalizedY = normalizeYSelection(template.yField, template.yAggregate, config.yFields, base);
|
|
62
|
+
const nextState = {
|
|
63
|
+
viewMode: base.viewMode,
|
|
64
|
+
visibleFields: base.visibleFields,
|
|
65
|
+
selectedX: hasOption(config.xFields, template.xField) ? template.xField : base.selectedX,
|
|
66
|
+
selectedY: normalizedY.selectedY,
|
|
67
|
+
selectedYAggregate: normalizedY.selectedYAggregate,
|
|
68
|
+
selectedGroupBy: hasOption(config.groups, template.groupBy) ? template.groupBy : base.selectedGroupBy,
|
|
69
|
+
selectedSlices: (template.selectedSlices || []).filter(sliceId => hasOption(config.slices, sliceId)),
|
|
70
|
+
};
|
|
71
|
+
const resolvedTemplateId = resolveMatchingTemplateId(config.templates, nextState, config);
|
|
72
|
+
return {
|
|
73
|
+
...nextState,
|
|
74
|
+
selectedTemplate: resolvedTemplateId ?? template.id
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function resolveMatchingTemplateId(templates, state, config) {
|
|
78
|
+
if (!templates?.length)
|
|
79
|
+
return undefined;
|
|
80
|
+
const normalizedState = normalizeStateWithoutTemplate(state, config);
|
|
81
|
+
return templates.find(template => {
|
|
82
|
+
const templateState = normalizeStateWithoutTemplate(normalizeTemplateToComparableState(template, normalizedState, config), config);
|
|
83
|
+
return sameOrganizerState(templateState, normalizedState);
|
|
84
|
+
})?.id;
|
|
85
|
+
}
|
|
86
|
+
function normalizeTemplateToComparableState(template, baseState, config) {
|
|
87
|
+
const normalizedY = normalizeYSelection(template.yField, template.yAggregate, config.yFields, baseState);
|
|
88
|
+
return {
|
|
89
|
+
...baseState,
|
|
90
|
+
selectedX: hasOption(config.xFields, template.xField) ? template.xField : baseState.selectedX,
|
|
91
|
+
selectedY: normalizedY.selectedY,
|
|
92
|
+
selectedYAggregate: normalizedY.selectedYAggregate,
|
|
93
|
+
selectedGroupBy: hasOption(config.groups, template.groupBy) ? template.groupBy : baseState.selectedGroupBy,
|
|
94
|
+
selectedSlices: template.selectedSlices
|
|
95
|
+
? template.selectedSlices.filter(sliceId => hasOption(config.slices, sliceId))
|
|
96
|
+
: (baseState.selectedSlices || []),
|
|
97
|
+
selectedTemplate: undefined,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function normalizeStateWithoutTemplate(state, config) {
|
|
101
|
+
const base = state || {};
|
|
102
|
+
const normalizedY = normalizeYSelection(base.selectedY, base.selectedYAggregate, config.yFields);
|
|
103
|
+
return {
|
|
104
|
+
...base,
|
|
105
|
+
selectedX: hasOption(config.xFields, base.selectedX) ? base.selectedX : undefined,
|
|
106
|
+
selectedY: normalizedY.selectedY,
|
|
107
|
+
selectedYAggregate: normalizedY.selectedYAggregate,
|
|
108
|
+
selectedGroupBy: hasOption(config.groups, base.selectedGroupBy) ? base.selectedGroupBy : undefined,
|
|
109
|
+
selectedSlices: (base.selectedSlices || []).filter(sliceId => hasOption(config.slices, sliceId)),
|
|
110
|
+
selectedTemplate: undefined,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function normalizeYSelection(selectedY, selectedYAggregate, yFields, fallbackState) {
|
|
114
|
+
if (!selectedY) {
|
|
115
|
+
return {
|
|
116
|
+
selectedY: fallbackState?.selectedY,
|
|
117
|
+
selectedYAggregate: fallbackState?.selectedYAggregate,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const directField = yFields?.find(field => field.id === selectedY);
|
|
121
|
+
if (directField) {
|
|
122
|
+
if (!directField.aggregates?.length) {
|
|
123
|
+
return { selectedY: directField.id, selectedYAggregate: undefined };
|
|
124
|
+
}
|
|
125
|
+
const matchedAggregate = selectedYAggregate
|
|
126
|
+
? directField.aggregates.find(aggregate => aggregate.id === selectedYAggregate)
|
|
127
|
+
: undefined;
|
|
128
|
+
const fallbackAggregate = fallbackState?.selectedY === directField.id
|
|
129
|
+
? directField.aggregates.find(aggregate => aggregate.id === fallbackState.selectedYAggregate)
|
|
130
|
+
: undefined;
|
|
131
|
+
const resolvedAggregate = matchedAggregate ?? fallbackAggregate ?? directField.aggregates[0];
|
|
132
|
+
return {
|
|
133
|
+
selectedY: directField.id,
|
|
134
|
+
selectedYAggregate: resolvedAggregate?.id,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const aggregateParent = yFields?.find(field => field.aggregates?.some(aggregate => aggregate.id === selectedY));
|
|
138
|
+
if (aggregateParent) {
|
|
139
|
+
return {
|
|
140
|
+
selectedY: aggregateParent.id,
|
|
141
|
+
selectedYAggregate: selectedY,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
selectedY: fallbackState?.selectedY,
|
|
146
|
+
selectedYAggregate: fallbackState?.selectedYAggregate,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function sameOrganizerState(left, right) {
|
|
150
|
+
return left.selectedX === right.selectedX
|
|
151
|
+
&& left.selectedY === right.selectedY
|
|
152
|
+
&& left.selectedYAggregate === right.selectedYAggregate
|
|
153
|
+
&& left.selectedGroupBy === right.selectedGroupBy
|
|
154
|
+
&& sameSlices(left.selectedSlices || [], right.selectedSlices || []);
|
|
155
|
+
}
|
|
156
|
+
function sameSlices(left, right) {
|
|
157
|
+
if (left.length !== right.length)
|
|
158
|
+
return false;
|
|
159
|
+
const sortedLeft = [...left].sort((a, b) => a.localeCompare(b));
|
|
160
|
+
const sortedRight = [...right].sort((a, b) => a.localeCompare(b));
|
|
161
|
+
return sortedLeft.every((value, index) => value === sortedRight[index]);
|
|
162
|
+
}
|
|
163
|
+
function hasOption(items, id) {
|
|
164
|
+
return !!id && !!items?.some(item => item.id === id);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
class TemplateManager {
|
|
168
|
+
static applyTemplate(template, currentState, config) {
|
|
169
|
+
return normalizeTemplateToState(template, currentState, config);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
15
173
|
class OrganizerButtonComponent {
|
|
16
174
|
constructor(cdr) {
|
|
17
175
|
this.cdr = cdr;
|
|
@@ -65,16 +223,14 @@ class OrganizerButtonComponent {
|
|
|
65
223
|
this.emitChange('groupBySelected', { selectedGroupBy: current === groupId ? undefined : groupId });
|
|
66
224
|
}
|
|
67
225
|
onTemplateSelect(templateId) {
|
|
68
|
-
|
|
69
|
-
if (!t)
|
|
226
|
+
if (!this.config.templates?.length)
|
|
70
227
|
return;
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
});
|
|
228
|
+
const template = this.config.templates?.find(t => t.id === templateId);
|
|
229
|
+
if (!template)
|
|
230
|
+
return;
|
|
231
|
+
const newState = TemplateManager.applyTemplate(template, this.state, this.config);
|
|
232
|
+
this.emitChange('templateSelected', newState);
|
|
233
|
+
this.syncSliceState(newState.selectedSlices);
|
|
78
234
|
}
|
|
79
235
|
onSliceClick(sliceId) {
|
|
80
236
|
if (this.config.onSliceClick) {
|
|
@@ -89,20 +245,34 @@ class OrganizerButtonComponent {
|
|
|
89
245
|
updated = selectedSlices;
|
|
90
246
|
}
|
|
91
247
|
if (updated.length === 0 || !sliceId || !this.config.onFetchSliceData) {
|
|
92
|
-
|
|
93
|
-
this.sliceStateChange.emit(null);
|
|
94
|
-
}
|
|
248
|
+
this.sliceStateChange.emit(null);
|
|
95
249
|
this.emitChange('sliceSelected', { selectedSlices: updated });
|
|
96
250
|
return;
|
|
97
251
|
}
|
|
252
|
+
this.syncSliceState(updated, () => {
|
|
253
|
+
this.emitChange('sliceSelected', { selectedSlices: updated });
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
syncSliceState(selectedSlices, onLoaded) {
|
|
257
|
+
const sliceId = selectedSlices?.[0];
|
|
258
|
+
if (!sliceId || !this.config.onFetchSliceData) {
|
|
259
|
+
this.sliceStateChange.emit(null);
|
|
260
|
+
onLoaded?.();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
98
263
|
const slice = this.config.slices?.find(s => s.id === sliceId);
|
|
264
|
+
if (!slice) {
|
|
265
|
+
this.sliceStateChange.emit(null);
|
|
266
|
+
onLoaded?.();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
99
269
|
const result = this.config.onFetchSliceData(sliceId);
|
|
100
270
|
const handleData = (tasks) => {
|
|
101
271
|
this.sliceStateChange.emit({
|
|
102
|
-
sliceConfigs: [{ title: slice
|
|
272
|
+
sliceConfigs: [{ title: slice.label ?? sliceId, columnKey: sliceId }],
|
|
103
273
|
tasks
|
|
104
274
|
});
|
|
105
|
-
|
|
275
|
+
onLoaded?.();
|
|
106
276
|
};
|
|
107
277
|
if (isObservable(result)) {
|
|
108
278
|
result.pipe(takeUntil(this.destroy$)).subscribe({ next: handleData });
|
|
@@ -237,19 +407,25 @@ class OrganizerButtonComponent {
|
|
|
237
407
|
return this.state?.selectedY === yFieldId && this.state?.selectedYAggregate === aggregateId;
|
|
238
408
|
}
|
|
239
409
|
emitChange(type, stateUpdate) {
|
|
410
|
+
const isFullState = 'selectedX' in stateUpdate && 'selectedTemplate' in stateUpdate;
|
|
411
|
+
const rawState = isFullState ? stateUpdate : { ...this.state, ...stateUpdate };
|
|
412
|
+
const normalizedState = normalizeOrganizerState(rawState, this.config);
|
|
240
413
|
const event = {
|
|
241
414
|
type,
|
|
242
|
-
state: {
|
|
415
|
+
state: {
|
|
416
|
+
...normalizedState,
|
|
417
|
+
selectedTemplate: resolveMatchingTemplateId(this.config.templates, normalizedState, this.config)
|
|
418
|
+
},
|
|
243
419
|
source: 'user'
|
|
244
420
|
};
|
|
245
421
|
this.viewChange.emit(event);
|
|
246
422
|
}
|
|
247
423
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OrganizerButtonComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
248
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: OrganizerButtonComponent, isStandalone: true, selector: "organizer-button", inputs: { config: "config", state: "state", hideMenuValues: "hideMenuValues" }, outputs: { viewChange: "viewChange", sliceStateChange: "sliceStateChange" }, viewQueries: [{ propertyName: "mainMenuTrigger", first: true, predicate: ["mainMenuTrigger"], descendants: true }], ngImport: i0, template: "<button type=\"button\" class=\"organizer-btn\" [matMenuTriggerFor]=\"viewMenu\" #mainMenuTrigger=\"matMenuTrigger\" [attr.aria-label]=\"'View'\">\n <mat-icon class=\"organizer-btn-icon\">{{ config.buttonIcon || 'settings' }}</mat-icon>\n</button>\n\n<mat-menu #viewMenu=\"matMenu\" panelClass=\"organizer-menu-panel\">\n\n <!-- Champs : mode chart (X + Y) -->\n <button *ngIf=\"hasChartFields()\" mat-menu-item [matMenuTriggerFor]=\"champsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && (activeXLabel() || activeYLabel())\">\n {{ activeXLabel() }}<ng-container *ngIf=\"activeXLabel() && activeYLabel()\"> / </ng-container>{{ activeYLabel() }}\n </span>\n </button>\n\n <!-- Champs : mode table (toggle colonnes) -->\n <button *ngIf=\"hasTableFields()\" mat-menu-item [matMenuTriggerFor]=\"fieldsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues\">{{ fieldsSummary() }}</span>\n </button>\n\n <!-- Grouper par -->\n <button *ngIf=\"config.groups?.length\" mat-menu-item [matMenuTriggerFor]=\"groupsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Grouper par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeGroupByLabel()\">{{ activeGroupByLabel() }}</span>\n </button>\n\n <!-- Filtrer par -->\n <button *ngIf=\"config.slices?.length\" mat-menu-item [matMenuTriggerFor]=\"slicesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Filtrer par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeSlicesLabel()\">{{ activeSlicesLabel() }}</span>\n </button>\n\n <!-- Template -->\n <button *ngIf=\"config.templates?.length\" mat-menu-item [matMenuTriggerFor]=\"templateSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Template</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeTemplateLabel()\">{{ activeTemplateLabel() }}</span>\n </button>\n\n <!-- Export direct (mode table) -->\n <mat-divider *ngIf=\"config.showExport\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showExport && !hasExportSubMenu()\" mat-menu-item type=\"button\" class=\"organizer-menu-export\" (click)=\"onExport()\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Export graphique (mode chart) \u2014 ouvre un sous-menu -->\n <button *ngIf=\"config.showExport && hasExportSubMenu()\" mat-menu-item [matMenuTriggerFor]=\"exportSubMenu\" class=\"organizer-menu-trigger organizer-menu-export\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Pr\u00E9f\u00E9rences -->\n <mat-divider *ngIf=\"config.showPreferences\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showPreferences\" mat-menu-item [matMenuTriggerFor]=\"preferencesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Pr\u00E9f\u00E9rences</span>\n </button>\n\n <!-- Switch chart / table -->\n <mat-divider *ngIf=\"hasSwitchView()\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"hasSwitchView()\" mat-menu-item type=\"button\" class=\"organizer-menu-trigger\" (click)=\"onSwitchView()\">\n <mat-icon class=\"organizer-menu-export-icon\">{{ config.switchView?.currentView === 'chart' ? 'table_chart' : 'bar_chart' }}</mat-icon>\n <span class=\"organizer-menu-label\">{{ config.switchView?.currentView === 'chart' ? 'Tableau' : 'Graphique' }}</span>\n </button>\n\n</mat-menu>\n\n<!-- Sous-menu : Export graphique -->\n<mat-menu #exportSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button *ngIf=\"config.onExportVisual\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportVisual()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">image</mat-icon>\n Visuel\n </button>\n <button *ngIf=\"config.onExportData\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportData()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">table_chart</mat-icon>\n Donn\u00E9es\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Champs chart (X + Y) -->\n<mat-menu #champsSubMenu=\"matMenu\" panelClass=\"organizer-champs-panel\">\n <div class=\"organizer-champs-wrapper\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n\n <!-- Bloc X -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.xFields?.length\">\n <span class=\"organizer-champs-block-title\">X \u2014 Axe horizontal</span>\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let xField of config.xFields\"\n [class.active]=\"state?.selectedX === xField.id\"\n [disabled]=\"xField.disabled\"\n (mousedown)=\"onXFieldSelect(xField.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedX === xField.id ? '\u2713' : '' }}</span>\n {{ xField.label }}\n </button>\n </div>\n\n <mat-divider *ngIf=\"config.xFields?.length && config.yFields?.length\" class=\"organizer-champs-divider\"></mat-divider>\n\n <!-- Bloc Y -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.yFields?.length\">\n <span class=\"organizer-champs-block-title\">Y \u2014 Axe vertical</span>\n <ng-container *ngFor=\"let yField of config.yFields\">\n\n <!-- Y simple (Count sans agr\u00E9gat ni stack) -->\n <!-- Y simple (Count ou m\u00E9trique directe) -->\n <button *ngIf=\"!yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n (mousedown)=\"onYFieldSelect(yField.id)\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n </button>\n\n <!-- Y avec agr\u00E9gats \u2192 sous-menu -->\n <button *ngIf=\"yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item organizer-submenu-item--has-children\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n [matMenuTriggerFor]=\"yAggSubMenu\"\n [matMenuTriggerData]=\"{ yField: yField }\"\n (mousedown)=\"$event.stopPropagation()\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n <mat-icon class=\"organizer-submenu-arrow\">chevron_right</mat-icon>\n </button>\n\n </ng-container>\n </div>\n\n </div>\n</mat-menu>\n\n<!-- Sous-menu dynamique : agr\u00E9gats d'un champ Y -->\n<mat-menu #yAggSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <ng-template matMenuContent let-yField=\"yField\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let agg of yField.aggregates\"\n [class.active]=\"isYAggregateActive(yField.id, agg.id)\"\n (mousedown)=\"onYAggregateSelect(yField.id, agg.id)\">\n <span class=\"organizer-submenu-check\">{{ isYAggregateActive(yField.id, agg.id) ? '\u2713' : '' }}</span>\n {{ agg.label }}\n </button>\n </div>\n </ng-template>\n</mat-menu>\n\n<!-- Sous-menu : Champs table (toggle colonnes) -->\n<mat-menu #fieldsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let field of config.fields\"\n [class.active]=\"isFieldVisible(field.id)\"\n (mousedown)=\"onFieldToggle(field.id, !isFieldVisible(field.id))\">\n <span class=\"organizer-submenu-check\">{{ isFieldVisible(field.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"field.icon\" class=\"organizer-submenu-icon\">{{ field.icon }}</mat-icon> {{ field.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Grouper par -->\n<mat-menu #groupsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let group of config.groups\"\n [class.active]=\"state?.selectedGroupBy === group.id\"\n (mousedown)=\"onGroupBySelect(group.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedGroupBy === group.id ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"group.icon\" class=\"organizer-submenu-icon\">{{ group.icon }}</mat-icon> {{ group.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Filtrer par -->\n<mat-menu #slicesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let slice of config.slices\"\n [class.active]=\"state?.selectedSlices?.includes(slice.id)\"\n (mousedown)=\"onSliceClick(slice.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedSlices?.includes(slice.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"slice.icon\" class=\"organizer-submenu-icon\">{{ slice.icon }}</mat-icon> {{ slice.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Template -->\n<mat-menu #templateSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let tmpl of config.templates\"\n [class.active]=\"state?.selectedTemplate === tmpl.id\"\n (mousedown)=\"onTemplateSelect(tmpl.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedTemplate === tmpl.id ? '\u2713' : '' }}</span>\n <mat-icon *ngIf=\"tmpl.icon\" class=\"organizer-submenu-icon\">{{ tmpl.icon }}</mat-icon>\n {{ tmpl.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Pr\u00E9f\u00E9rences -->\n<mat-menu #preferencesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesEdit()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">edit</mat-icon>\u00C9diter\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesSave()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">save</mat-icon>Sauvegarder\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" [disabled]=\"!config.hasSavedPreferences\" (mousedown)=\"onPreferencesClear()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">delete_outline</mat-icon>R\u00E9initialiser\n </button>\n </div>\n</mat-menu>\n\n", styles: [".organizer-btn{display:inline-flex;align-items:center;height:34px;border:1px solid #e0e0e0;border-radius:8px;background:#fff;padding:0 10px;cursor:pointer;box-sizing:border-box}.organizer-btn:hover{border-color:#9e9e9e}.organizer-btn-icon{font-size:16px;width:16px;height:16px;line-height:1;color:#000}.mat-mdc-menu-panel:has(.organizer-menu-label){min-width:170px!important;max-width:320px!important;overflow:visible!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .mat-mdc-menu-content{padding:4px 0!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item{min-height:42px;padding:0 14px;display:flex;align-items:center;box-sizing:border-box}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item .mdc-list-item__primary-text{display:flex;align-items:center;width:100%;overflow:hidden}.organizer-menu-label{font-size:13px;font-weight:500;color:#212121;flex:0 0 auto;white-space:nowrap;padding-right:8px}.organizer-menu-value{font-size:12px;color:#757575;flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}.organizer-submenu{padding:4px 6px;min-width:180px;box-sizing:border-box}.organizer-submenu .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-submenu .organizer-submenu-item:hover{background:#f5f5f5}.organizer-submenu .organizer-submenu-item.active{font-weight:600}.organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-submenu-icon{font-size:14px!important;width:14px!important;height:14px!important;color:#212121;margin-right:4px}.organizer-menu-export.mat-mdc-menu-item{min-height:42px;padding:0 14px}.organizer-menu-export-icon{font-size:16px!important;width:16px!important;height:16px!important;color:#424242;margin-right:8px}.organizer-divider{margin:4px 0!important}.organizer-champs-wrapper{padding:4px 6px;min-width:200px;box-sizing:border-box;display:flex;flex-direction:column}.organizer-champs-block{display:flex;flex-direction:column}.organizer-champs-block-title{font-size:10px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:#9e9e9e;padding:6px 2px 2px}.organizer-champs-divider{margin:4px 0!important}.organizer-champs-wrapper .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;font-family:inherit;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-champs-wrapper .organizer-submenu-item:hover:not([disabled]){background:#f5f5f5}.organizer-champs-wrapper .organizer-submenu-item.active{font-weight:600}.organizer-champs-wrapper .organizer-submenu-item[disabled]{opacity:.38;cursor:default}.organizer-champs-wrapper .organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-champs-wrapper .organizer-submenu-item--has-children{padding-right:8px}.organizer-champs-wrapper .organizer-submenu-arrow{font-size:18px!important;width:18px!important;height:18px!important;color:#00000061;margin-left:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i4.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
424
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: OrganizerButtonComponent, isStandalone: true, selector: "organizer-button", inputs: { config: "config", state: "state", hideMenuValues: "hideMenuValues" }, outputs: { viewChange: "viewChange", sliceStateChange: "sliceStateChange" }, viewQueries: [{ propertyName: "mainMenuTrigger", first: true, predicate: ["mainMenuTrigger"], descendants: true }], ngImport: i0, template: "<button type=\"button\" class=\"organizer-btn\" [matMenuTriggerFor]=\"viewMenu\" #mainMenuTrigger=\"matMenuTrigger\" [attr.aria-label]=\"'View'\">\n <mat-icon class=\"organizer-btn-icon\">{{ config.buttonIcon || 'settings' }}</mat-icon>\n</button>\n\n<mat-menu #viewMenu=\"matMenu\" panelClass=\"organizer-menu-panel\">\n\n <!-- Champs : mode chart (X + Y) -->\n <button *ngIf=\"hasChartFields()\" mat-menu-item [matMenuTriggerFor]=\"champsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && (activeXLabel() || activeYLabel())\">\n {{ activeXLabel() }}<ng-container *ngIf=\"activeXLabel() && activeYLabel()\"> / </ng-container>{{ activeYLabel() }}\n </span>\n </button>\n\n <!-- Champs : mode table (toggle colonnes) -->\n <button *ngIf=\"hasTableFields()\" mat-menu-item [matMenuTriggerFor]=\"fieldsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues\">{{ fieldsSummary() }}</span>\n </button>\n\n <!-- Grouper par -->\n <button *ngIf=\"config.groups?.length\" mat-menu-item [matMenuTriggerFor]=\"groupsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Grouper par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeGroupByLabel()\">{{ activeGroupByLabel() }}</span>\n </button>\n\n <!-- Filtrer par -->\n <button *ngIf=\"config.slices?.length\" mat-menu-item [matMenuTriggerFor]=\"slicesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Filtrer par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeSlicesLabel()\">{{ activeSlicesLabel() }}</span>\n </button>\n\n <!-- Template -->\n <button *ngIf=\"config.templates?.length\" mat-menu-item [matMenuTriggerFor]=\"templateSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Template</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeTemplateLabel()\">{{ activeTemplateLabel() }}</span>\n </button>\n\n <!-- Export direct (mode table) -->\n <mat-divider *ngIf=\"config.showExport\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showExport && !hasExportSubMenu()\" mat-menu-item type=\"button\" class=\"organizer-menu-export\" (click)=\"onExport()\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Export graphique (mode chart) \u2014 ouvre un sous-menu -->\n <button *ngIf=\"config.showExport && hasExportSubMenu()\" mat-menu-item [matMenuTriggerFor]=\"exportSubMenu\" class=\"organizer-menu-trigger organizer-menu-export\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Pr\u00E9f\u00E9rences -->\n <mat-divider *ngIf=\"config.showPreferences\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showPreferences\" mat-menu-item [matMenuTriggerFor]=\"preferencesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Pr\u00E9f\u00E9rences</span>\n </button>\n\n <!-- Switch chart / table -->\n <mat-divider *ngIf=\"hasSwitchView()\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"hasSwitchView()\" mat-menu-item type=\"button\" class=\"organizer-menu-trigger\" (click)=\"onSwitchView()\">\n <mat-icon class=\"organizer-menu-export-icon\">{{ config.switchView?.currentView === 'chart' ? 'table_chart' : 'bar_chart' }}</mat-icon>\n <span class=\"organizer-menu-label\">{{ config.switchView?.currentView === 'chart' ? 'Tableau' : 'Graphique' }}</span>\n </button>\n\n</mat-menu>\n\n<!-- Sous-menu : Export graphique -->\n<mat-menu #exportSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button *ngIf=\"config.onExportVisual\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportVisual()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">image</mat-icon>\n Visuel\n </button>\n <button *ngIf=\"config.onExportData\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportData()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">table_chart</mat-icon>\n Donn\u00E9es\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Champs chart (X + Y) -->\n<mat-menu #champsSubMenu=\"matMenu\" panelClass=\"organizer-champs-panel\">\n <div class=\"organizer-champs-wrapper\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n\n <!-- Bloc X -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.xFields?.length\">\n <span class=\"organizer-champs-block-title\">Axe horizontal \u2014 X</span>\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let xField of config.xFields\"\n [class.active]=\"state?.selectedX === xField.id\"\n [disabled]=\"xField.disabled\"\n (mousedown)=\"onXFieldSelect(xField.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedX === xField.id ? '\u2713' : '' }}</span>\n {{ xField.label }}\n </button>\n </div>\n\n <mat-divider *ngIf=\"config.xFields?.length && config.yFields?.length\" class=\"organizer-champs-divider\"></mat-divider>\n\n <!-- Bloc Y -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.yFields?.length\">\n <span class=\"organizer-champs-block-title\">Axe vertical \u2014 Y</span>\n <ng-container *ngFor=\"let yField of config.yFields\">\n\n <!-- Y simple (Count sans agr\u00E9gat ni stack) -->\n <!-- Y simple (Count ou m\u00E9trique directe) -->\n <button *ngIf=\"!yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n (mousedown)=\"onYFieldSelect(yField.id)\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n </button>\n\n <!-- Y avec agr\u00E9gats \u2192 sous-menu -->\n <button *ngIf=\"yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item organizer-submenu-item--has-children\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n [matMenuTriggerFor]=\"yAggSubMenu\"\n [matMenuTriggerData]=\"{ yField: yField }\"\n (mousedown)=\"$event.stopPropagation()\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n <mat-icon class=\"organizer-submenu-arrow\">chevron_right</mat-icon>\n </button>\n\n </ng-container>\n </div>\n\n </div>\n</mat-menu>\n\n<!-- Sous-menu dynamique : agr\u00E9gats d'un champ Y -->\n<mat-menu #yAggSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <ng-template matMenuContent let-yField=\"yField\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let agg of yField.aggregates\"\n [class.active]=\"isYAggregateActive(yField.id, agg.id)\"\n (mousedown)=\"onYAggregateSelect(yField.id, agg.id)\">\n <span class=\"organizer-submenu-check\">{{ isYAggregateActive(yField.id, agg.id) ? '\u2713' : '' }}</span>\n {{ agg.label }}\n </button>\n </div>\n </ng-template>\n</mat-menu>\n\n<!-- Sous-menu : Champs table (toggle colonnes) -->\n<mat-menu #fieldsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let field of config.fields\"\n [class.active]=\"isFieldVisible(field.id)\"\n (mousedown)=\"onFieldToggle(field.id, !isFieldVisible(field.id))\">\n <span class=\"organizer-submenu-check\">{{ isFieldVisible(field.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"field.icon\" class=\"organizer-submenu-icon\">{{ field.icon }}</mat-icon> {{ field.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Grouper par -->\n<mat-menu #groupsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let group of config.groups\"\n [class.active]=\"state?.selectedGroupBy === group.id\"\n (mousedown)=\"onGroupBySelect(group.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedGroupBy === group.id ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"group.icon\" class=\"organizer-submenu-icon\">{{ group.icon }}</mat-icon> {{ group.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Filtrer par -->\n<mat-menu #slicesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let slice of config.slices\"\n [class.active]=\"state?.selectedSlices?.includes(slice.id)\"\n (mousedown)=\"onSliceClick(slice.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedSlices?.includes(slice.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"slice.icon\" class=\"organizer-submenu-icon\">{{ slice.icon }}</mat-icon> {{ slice.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Template -->\n<mat-menu #templateSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let tmpl of config.templates\"\n [class.active]=\"state?.selectedTemplate === tmpl.id\"\n [title]=\"tmpl.description || ''\"\n (mousedown)=\"onTemplateSelect(tmpl.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedTemplate === tmpl.id ? '\u2713' : '' }}</span>\n <mat-icon *ngIf=\"tmpl.icon\" class=\"organizer-submenu-icon\">{{ tmpl.icon }}</mat-icon>\n {{ tmpl.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Pr\u00E9f\u00E9rences -->\n<mat-menu #preferencesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesEdit()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">edit</mat-icon>\u00C9diter\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesSave()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">save</mat-icon>Sauvegarder\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" [disabled]=\"!config.hasSavedPreferences\" (mousedown)=\"onPreferencesClear()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">delete_outline</mat-icon>R\u00E9initialiser\n </button>\n </div>\n</mat-menu>\n\n", styles: [".organizer-btn{display:inline-flex;align-items:center;height:34px;border:1px solid #e0e0e0;border-radius:8px;background:#fff;padding:0 10px;cursor:pointer;box-sizing:border-box}.organizer-btn:hover{border-color:#9e9e9e}.organizer-btn-icon{font-size:16px;width:16px;height:16px;line-height:1;color:#000}.mat-mdc-menu-panel:has(.organizer-menu-label){min-width:170px!important;max-width:320px!important;overflow:visible!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .mat-mdc-menu-content{padding:4px 0!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item{min-height:42px;padding:0 14px;display:flex;align-items:center;box-sizing:border-box}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item .mdc-list-item__primary-text{display:flex;align-items:center;width:100%;overflow:hidden}.organizer-menu-label{font-size:13px;font-weight:500;color:#212121;flex:0 0 auto;white-space:nowrap;padding-right:8px}.organizer-menu-value{font-size:12px;color:#757575;flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}.organizer-submenu{padding:4px 6px;min-width:180px;box-sizing:border-box}.organizer-submenu .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-submenu .organizer-submenu-item:hover{background:#f5f5f5}.organizer-submenu .organizer-submenu-item.active{font-weight:600}.organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-submenu-icon{font-size:14px!important;width:14px!important;height:14px!important;color:#212121;margin-right:4px}.organizer-menu-export.mat-mdc-menu-item{min-height:42px;padding:0 14px}.organizer-menu-export-icon{font-size:16px!important;width:16px!important;height:16px!important;color:#424242;margin-right:8px}.organizer-divider{margin:4px 0!important}.organizer-champs-wrapper{padding:4px 6px;min-width:200px;box-sizing:border-box;display:flex;flex-direction:column}.organizer-champs-block{display:flex;flex-direction:column}.organizer-champs-block-title{font-size:10px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:#9e9e9e;padding:6px 2px 2px}.organizer-champs-divider{margin:4px 0!important}.organizer-champs-wrapper .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;font-family:inherit;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-champs-wrapper .organizer-submenu-item:hover:not([disabled]){background:#f5f5f5}.organizer-champs-wrapper .organizer-submenu-item.active{font-weight:600}.organizer-champs-wrapper .organizer-submenu-item[disabled]{opacity:.38;cursor:default}.organizer-champs-wrapper .organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-champs-wrapper .organizer-submenu-item--has-children{padding-right:8px}.organizer-champs-wrapper .organizer-submenu-arrow{font-size:18px!important;width:18px!important;height:18px!important;color:#00000061;margin-left:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i4.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
249
425
|
}
|
|
250
426
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OrganizerButtonComponent, decorators: [{
|
|
251
427
|
type: Component,
|
|
252
|
-
args: [{ standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatDividerModule], selector: 'organizer-button', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"organizer-btn\" [matMenuTriggerFor]=\"viewMenu\" #mainMenuTrigger=\"matMenuTrigger\" [attr.aria-label]=\"'View'\">\n <mat-icon class=\"organizer-btn-icon\">{{ config.buttonIcon || 'settings' }}</mat-icon>\n</button>\n\n<mat-menu #viewMenu=\"matMenu\" panelClass=\"organizer-menu-panel\">\n\n <!-- Champs : mode chart (X + Y) -->\n <button *ngIf=\"hasChartFields()\" mat-menu-item [matMenuTriggerFor]=\"champsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && (activeXLabel() || activeYLabel())\">\n {{ activeXLabel() }}<ng-container *ngIf=\"activeXLabel() && activeYLabel()\"> / </ng-container>{{ activeYLabel() }}\n </span>\n </button>\n\n <!-- Champs : mode table (toggle colonnes) -->\n <button *ngIf=\"hasTableFields()\" mat-menu-item [matMenuTriggerFor]=\"fieldsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues\">{{ fieldsSummary() }}</span>\n </button>\n\n <!-- Grouper par -->\n <button *ngIf=\"config.groups?.length\" mat-menu-item [matMenuTriggerFor]=\"groupsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Grouper par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeGroupByLabel()\">{{ activeGroupByLabel() }}</span>\n </button>\n\n <!-- Filtrer par -->\n <button *ngIf=\"config.slices?.length\" mat-menu-item [matMenuTriggerFor]=\"slicesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Filtrer par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeSlicesLabel()\">{{ activeSlicesLabel() }}</span>\n </button>\n\n <!-- Template -->\n <button *ngIf=\"config.templates?.length\" mat-menu-item [matMenuTriggerFor]=\"templateSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Template</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeTemplateLabel()\">{{ activeTemplateLabel() }}</span>\n </button>\n\n <!-- Export direct (mode table) -->\n <mat-divider *ngIf=\"config.showExport\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showExport && !hasExportSubMenu()\" mat-menu-item type=\"button\" class=\"organizer-menu-export\" (click)=\"onExport()\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Export graphique (mode chart) \u2014 ouvre un sous-menu -->\n <button *ngIf=\"config.showExport && hasExportSubMenu()\" mat-menu-item [matMenuTriggerFor]=\"exportSubMenu\" class=\"organizer-menu-trigger organizer-menu-export\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Pr\u00E9f\u00E9rences -->\n <mat-divider *ngIf=\"config.showPreferences\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showPreferences\" mat-menu-item [matMenuTriggerFor]=\"preferencesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Pr\u00E9f\u00E9rences</span>\n </button>\n\n <!-- Switch chart / table -->\n <mat-divider *ngIf=\"hasSwitchView()\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"hasSwitchView()\" mat-menu-item type=\"button\" class=\"organizer-menu-trigger\" (click)=\"onSwitchView()\">\n <mat-icon class=\"organizer-menu-export-icon\">{{ config.switchView?.currentView === 'chart' ? 'table_chart' : 'bar_chart' }}</mat-icon>\n <span class=\"organizer-menu-label\">{{ config.switchView?.currentView === 'chart' ? 'Tableau' : 'Graphique' }}</span>\n </button>\n\n</mat-menu>\n\n<!-- Sous-menu : Export graphique -->\n<mat-menu #exportSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button *ngIf=\"config.onExportVisual\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportVisual()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">image</mat-icon>\n Visuel\n </button>\n <button *ngIf=\"config.onExportData\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportData()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">table_chart</mat-icon>\n Donn\u00E9es\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Champs chart (X + Y) -->\n<mat-menu #champsSubMenu=\"matMenu\" panelClass=\"organizer-champs-panel\">\n <div class=\"organizer-champs-wrapper\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n\n <!-- Bloc X -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.xFields?.length\">\n <span class=\"organizer-champs-block-title\">X \u2014 Axe horizontal</span>\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let xField of config.xFields\"\n [class.active]=\"state?.selectedX === xField.id\"\n [disabled]=\"xField.disabled\"\n (mousedown)=\"onXFieldSelect(xField.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedX === xField.id ? '\u2713' : '' }}</span>\n {{ xField.label }}\n </button>\n </div>\n\n <mat-divider *ngIf=\"config.xFields?.length && config.yFields?.length\" class=\"organizer-champs-divider\"></mat-divider>\n\n <!-- Bloc Y -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.yFields?.length\">\n <span class=\"organizer-champs-block-title\">Y \u2014 Axe vertical</span>\n <ng-container *ngFor=\"let yField of config.yFields\">\n\n <!-- Y simple (Count sans agr\u00E9gat ni stack) -->\n <!-- Y simple (Count ou m\u00E9trique directe) -->\n <button *ngIf=\"!yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n (mousedown)=\"onYFieldSelect(yField.id)\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n </button>\n\n <!-- Y avec agr\u00E9gats \u2192 sous-menu -->\n <button *ngIf=\"yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item organizer-submenu-item--has-children\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n [matMenuTriggerFor]=\"yAggSubMenu\"\n [matMenuTriggerData]=\"{ yField: yField }\"\n (mousedown)=\"$event.stopPropagation()\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n <mat-icon class=\"organizer-submenu-arrow\">chevron_right</mat-icon>\n </button>\n\n </ng-container>\n </div>\n\n </div>\n</mat-menu>\n\n<!-- Sous-menu dynamique : agr\u00E9gats d'un champ Y -->\n<mat-menu #yAggSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <ng-template matMenuContent let-yField=\"yField\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let agg of yField.aggregates\"\n [class.active]=\"isYAggregateActive(yField.id, agg.id)\"\n (mousedown)=\"onYAggregateSelect(yField.id, agg.id)\">\n <span class=\"organizer-submenu-check\">{{ isYAggregateActive(yField.id, agg.id) ? '\u2713' : '' }}</span>\n {{ agg.label }}\n </button>\n </div>\n </ng-template>\n</mat-menu>\n\n<!-- Sous-menu : Champs table (toggle colonnes) -->\n<mat-menu #fieldsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let field of config.fields\"\n [class.active]=\"isFieldVisible(field.id)\"\n (mousedown)=\"onFieldToggle(field.id, !isFieldVisible(field.id))\">\n <span class=\"organizer-submenu-check\">{{ isFieldVisible(field.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"field.icon\" class=\"organizer-submenu-icon\">{{ field.icon }}</mat-icon> {{ field.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Grouper par -->\n<mat-menu #groupsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let group of config.groups\"\n [class.active]=\"state?.selectedGroupBy === group.id\"\n (mousedown)=\"onGroupBySelect(group.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedGroupBy === group.id ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"group.icon\" class=\"organizer-submenu-icon\">{{ group.icon }}</mat-icon> {{ group.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Filtrer par -->\n<mat-menu #slicesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let slice of config.slices\"\n [class.active]=\"state?.selectedSlices?.includes(slice.id)\"\n (mousedown)=\"onSliceClick(slice.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedSlices?.includes(slice.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"slice.icon\" class=\"organizer-submenu-icon\">{{ slice.icon }}</mat-icon> {{ slice.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Template -->\n<mat-menu #templateSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let tmpl of config.templates\"\n [class.active]=\"state?.selectedTemplate === tmpl.id\"\n (mousedown)=\"onTemplateSelect(tmpl.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedTemplate === tmpl.id ? '\u2713' : '' }}</span>\n <mat-icon *ngIf=\"tmpl.icon\" class=\"organizer-submenu-icon\">{{ tmpl.icon }}</mat-icon>\n {{ tmpl.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Pr\u00E9f\u00E9rences -->\n<mat-menu #preferencesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesEdit()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">edit</mat-icon>\u00C9diter\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesSave()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">save</mat-icon>Sauvegarder\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" [disabled]=\"!config.hasSavedPreferences\" (mousedown)=\"onPreferencesClear()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">delete_outline</mat-icon>R\u00E9initialiser\n </button>\n </div>\n</mat-menu>\n\n", styles: [".organizer-btn{display:inline-flex;align-items:center;height:34px;border:1px solid #e0e0e0;border-radius:8px;background:#fff;padding:0 10px;cursor:pointer;box-sizing:border-box}.organizer-btn:hover{border-color:#9e9e9e}.organizer-btn-icon{font-size:16px;width:16px;height:16px;line-height:1;color:#000}.mat-mdc-menu-panel:has(.organizer-menu-label){min-width:170px!important;max-width:320px!important;overflow:visible!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .mat-mdc-menu-content{padding:4px 0!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item{min-height:42px;padding:0 14px;display:flex;align-items:center;box-sizing:border-box}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item .mdc-list-item__primary-text{display:flex;align-items:center;width:100%;overflow:hidden}.organizer-menu-label{font-size:13px;font-weight:500;color:#212121;flex:0 0 auto;white-space:nowrap;padding-right:8px}.organizer-menu-value{font-size:12px;color:#757575;flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}.organizer-submenu{padding:4px 6px;min-width:180px;box-sizing:border-box}.organizer-submenu .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-submenu .organizer-submenu-item:hover{background:#f5f5f5}.organizer-submenu .organizer-submenu-item.active{font-weight:600}.organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-submenu-icon{font-size:14px!important;width:14px!important;height:14px!important;color:#212121;margin-right:4px}.organizer-menu-export.mat-mdc-menu-item{min-height:42px;padding:0 14px}.organizer-menu-export-icon{font-size:16px!important;width:16px!important;height:16px!important;color:#424242;margin-right:8px}.organizer-divider{margin:4px 0!important}.organizer-champs-wrapper{padding:4px 6px;min-width:200px;box-sizing:border-box;display:flex;flex-direction:column}.organizer-champs-block{display:flex;flex-direction:column}.organizer-champs-block-title{font-size:10px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:#9e9e9e;padding:6px 2px 2px}.organizer-champs-divider{margin:4px 0!important}.organizer-champs-wrapper .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;font-family:inherit;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-champs-wrapper .organizer-submenu-item:hover:not([disabled]){background:#f5f5f5}.organizer-champs-wrapper .organizer-submenu-item.active{font-weight:600}.organizer-champs-wrapper .organizer-submenu-item[disabled]{opacity:.38;cursor:default}.organizer-champs-wrapper .organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-champs-wrapper .organizer-submenu-item--has-children{padding-right:8px}.organizer-champs-wrapper .organizer-submenu-arrow{font-size:18px!important;width:18px!important;height:18px!important;color:#00000061;margin-left:auto}\n"] }]
|
|
428
|
+
args: [{ standalone: true, imports: [CommonModule, MatButtonModule, MatIconModule, MatMenuModule, MatDividerModule], selector: 'organizer-button', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"organizer-btn\" [matMenuTriggerFor]=\"viewMenu\" #mainMenuTrigger=\"matMenuTrigger\" [attr.aria-label]=\"'View'\">\n <mat-icon class=\"organizer-btn-icon\">{{ config.buttonIcon || 'settings' }}</mat-icon>\n</button>\n\n<mat-menu #viewMenu=\"matMenu\" panelClass=\"organizer-menu-panel\">\n\n <!-- Champs : mode chart (X + Y) -->\n <button *ngIf=\"hasChartFields()\" mat-menu-item [matMenuTriggerFor]=\"champsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && (activeXLabel() || activeYLabel())\">\n {{ activeXLabel() }}<ng-container *ngIf=\"activeXLabel() && activeYLabel()\"> / </ng-container>{{ activeYLabel() }}\n </span>\n </button>\n\n <!-- Champs : mode table (toggle colonnes) -->\n <button *ngIf=\"hasTableFields()\" mat-menu-item [matMenuTriggerFor]=\"fieldsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Champs</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues\">{{ fieldsSummary() }}</span>\n </button>\n\n <!-- Grouper par -->\n <button *ngIf=\"config.groups?.length\" mat-menu-item [matMenuTriggerFor]=\"groupsSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Grouper par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeGroupByLabel()\">{{ activeGroupByLabel() }}</span>\n </button>\n\n <!-- Filtrer par -->\n <button *ngIf=\"config.slices?.length\" mat-menu-item [matMenuTriggerFor]=\"slicesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Filtrer par</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeSlicesLabel()\">{{ activeSlicesLabel() }}</span>\n </button>\n\n <!-- Template -->\n <button *ngIf=\"config.templates?.length\" mat-menu-item [matMenuTriggerFor]=\"templateSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Template</span>\n <span class=\"organizer-menu-value\" *ngIf=\"!hideMenuValues && activeTemplateLabel()\">{{ activeTemplateLabel() }}</span>\n </button>\n\n <!-- Export direct (mode table) -->\n <mat-divider *ngIf=\"config.showExport\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showExport && !hasExportSubMenu()\" mat-menu-item type=\"button\" class=\"organizer-menu-export\" (click)=\"onExport()\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Export graphique (mode chart) \u2014 ouvre un sous-menu -->\n <button *ngIf=\"config.showExport && hasExportSubMenu()\" mat-menu-item [matMenuTriggerFor]=\"exportSubMenu\" class=\"organizer-menu-trigger organizer-menu-export\">\n <mat-icon class=\"organizer-menu-export-icon\">download</mat-icon>\n <span class=\"organizer-menu-label\">Exporter</span>\n </button>\n\n <!-- Pr\u00E9f\u00E9rences -->\n <mat-divider *ngIf=\"config.showPreferences\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"config.showPreferences\" mat-menu-item [matMenuTriggerFor]=\"preferencesSubMenu\" class=\"organizer-menu-trigger\">\n <span class=\"organizer-menu-label\">Pr\u00E9f\u00E9rences</span>\n </button>\n\n <!-- Switch chart / table -->\n <mat-divider *ngIf=\"hasSwitchView()\" class=\"organizer-divider\"></mat-divider>\n <button *ngIf=\"hasSwitchView()\" mat-menu-item type=\"button\" class=\"organizer-menu-trigger\" (click)=\"onSwitchView()\">\n <mat-icon class=\"organizer-menu-export-icon\">{{ config.switchView?.currentView === 'chart' ? 'table_chart' : 'bar_chart' }}</mat-icon>\n <span class=\"organizer-menu-label\">{{ config.switchView?.currentView === 'chart' ? 'Tableau' : 'Graphique' }}</span>\n </button>\n\n</mat-menu>\n\n<!-- Sous-menu : Export graphique -->\n<mat-menu #exportSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button *ngIf=\"config.onExportVisual\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportVisual()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">image</mat-icon>\n Visuel\n </button>\n <button *ngIf=\"config.onExportData\" type=\"button\" class=\"organizer-submenu-item\"\n (mousedown)=\"onExportData()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">table_chart</mat-icon>\n Donn\u00E9es\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Champs chart (X + Y) -->\n<mat-menu #champsSubMenu=\"matMenu\" panelClass=\"organizer-champs-panel\">\n <div class=\"organizer-champs-wrapper\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n\n <!-- Bloc X -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.xFields?.length\">\n <span class=\"organizer-champs-block-title\">Axe horizontal \u2014 X</span>\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let xField of config.xFields\"\n [class.active]=\"state?.selectedX === xField.id\"\n [disabled]=\"xField.disabled\"\n (mousedown)=\"onXFieldSelect(xField.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedX === xField.id ? '\u2713' : '' }}</span>\n {{ xField.label }}\n </button>\n </div>\n\n <mat-divider *ngIf=\"config.xFields?.length && config.yFields?.length\" class=\"organizer-champs-divider\"></mat-divider>\n\n <!-- Bloc Y -->\n <div class=\"organizer-champs-block\" *ngIf=\"config.yFields?.length\">\n <span class=\"organizer-champs-block-title\">Axe vertical \u2014 Y</span>\n <ng-container *ngFor=\"let yField of config.yFields\">\n\n <!-- Y simple (Count sans agr\u00E9gat ni stack) -->\n <!-- Y simple (Count ou m\u00E9trique directe) -->\n <button *ngIf=\"!yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n (mousedown)=\"onYFieldSelect(yField.id)\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n </button>\n\n <!-- Y avec agr\u00E9gats \u2192 sous-menu -->\n <button *ngIf=\"yField.aggregates?.length\"\n type=\"button\" class=\"organizer-submenu-item organizer-submenu-item--has-children\"\n [class.active]=\"isYActive(yField.id)\"\n [disabled]=\"yField.disabled\"\n [matMenuTriggerFor]=\"yAggSubMenu\"\n [matMenuTriggerData]=\"{ yField: yField }\"\n (mousedown)=\"$event.stopPropagation()\">\n <span class=\"organizer-submenu-check\">{{ isYActive(yField.id) ? '\u2713' : '' }}</span>\n {{ yField.label }}\n <mat-icon class=\"organizer-submenu-arrow\">chevron_right</mat-icon>\n </button>\n\n </ng-container>\n </div>\n\n </div>\n</mat-menu>\n\n<!-- Sous-menu dynamique : agr\u00E9gats d'un champ Y -->\n<mat-menu #yAggSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <ng-template matMenuContent let-yField=\"yField\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let agg of yField.aggregates\"\n [class.active]=\"isYAggregateActive(yField.id, agg.id)\"\n (mousedown)=\"onYAggregateSelect(yField.id, agg.id)\">\n <span class=\"organizer-submenu-check\">{{ isYAggregateActive(yField.id, agg.id) ? '\u2713' : '' }}</span>\n {{ agg.label }}\n </button>\n </div>\n </ng-template>\n</mat-menu>\n\n<!-- Sous-menu : Champs table (toggle colonnes) -->\n<mat-menu #fieldsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let field of config.fields\"\n [class.active]=\"isFieldVisible(field.id)\"\n (mousedown)=\"onFieldToggle(field.id, !isFieldVisible(field.id))\">\n <span class=\"organizer-submenu-check\">{{ isFieldVisible(field.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"field.icon\" class=\"organizer-submenu-icon\">{{ field.icon }}</mat-icon> {{ field.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Grouper par -->\n<mat-menu #groupsSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let group of config.groups\"\n [class.active]=\"state?.selectedGroupBy === group.id\"\n (mousedown)=\"onGroupBySelect(group.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedGroupBy === group.id ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"group.icon\" class=\"organizer-submenu-icon\">{{ group.icon }}</mat-icon> {{ group.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Filtrer par -->\n<mat-menu #slicesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let slice of config.slices\"\n [class.active]=\"state?.selectedSlices?.includes(slice.id)\"\n (mousedown)=\"onSliceClick(slice.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedSlices?.includes(slice.id) ? '\u2713' : '' }}</span> <mat-icon *ngIf=\"slice.icon\" class=\"organizer-submenu-icon\">{{ slice.icon }}</mat-icon> {{ slice.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Template -->\n<mat-menu #templateSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\"\n *ngFor=\"let tmpl of config.templates\"\n [class.active]=\"state?.selectedTemplate === tmpl.id\"\n [title]=\"tmpl.description || ''\"\n (mousedown)=\"onTemplateSelect(tmpl.id)\">\n <span class=\"organizer-submenu-check\">{{ state?.selectedTemplate === tmpl.id ? '\u2713' : '' }}</span>\n <mat-icon *ngIf=\"tmpl.icon\" class=\"organizer-submenu-icon\">{{ tmpl.icon }}</mat-icon>\n {{ tmpl.label }}\n </button>\n </div>\n</mat-menu>\n\n<!-- Sous-menu : Pr\u00E9f\u00E9rences -->\n<mat-menu #preferencesSubMenu=\"matMenu\" panelClass=\"organizer-submenu-panel\">\n <div class=\"organizer-submenu\"\n (mousedown)=\"$event.stopPropagation()\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesEdit()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">edit</mat-icon>\u00C9diter\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" (mousedown)=\"onPreferencesSave()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">save</mat-icon>Sauvegarder\n </button>\n <button type=\"button\" class=\"organizer-submenu-item\" [disabled]=\"!config.hasSavedPreferences\" (mousedown)=\"onPreferencesClear()\">\n <span class=\"organizer-submenu-check\"></span>\n <mat-icon class=\"organizer-submenu-icon\">delete_outline</mat-icon>R\u00E9initialiser\n </button>\n </div>\n</mat-menu>\n\n", styles: [".organizer-btn{display:inline-flex;align-items:center;height:34px;border:1px solid #e0e0e0;border-radius:8px;background:#fff;padding:0 10px;cursor:pointer;box-sizing:border-box}.organizer-btn:hover{border-color:#9e9e9e}.organizer-btn-icon{font-size:16px;width:16px;height:16px;line-height:1;color:#000}.mat-mdc-menu-panel:has(.organizer-menu-label){min-width:170px!important;max-width:320px!important;overflow:visible!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .mat-mdc-menu-content{padding:4px 0!important}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item{min-height:42px;padding:0 14px;display:flex;align-items:center;box-sizing:border-box}.mat-mdc-menu-panel:has(.organizer-menu-label) .organizer-menu-trigger.mat-mdc-menu-item .mdc-list-item__primary-text{display:flex;align-items:center;width:100%;overflow:hidden}.organizer-menu-label{font-size:13px;font-weight:500;color:#212121;flex:0 0 auto;white-space:nowrap;padding-right:8px}.organizer-menu-value{font-size:12px;color:#757575;flex:1 1 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:right}.organizer-submenu{padding:4px 6px;min-width:180px;box-sizing:border-box}.organizer-submenu .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-submenu .organizer-submenu-item:hover{background:#f5f5f5}.organizer-submenu .organizer-submenu-item.active{font-weight:600}.organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-submenu-icon{font-size:14px!important;width:14px!important;height:14px!important;color:#212121;margin-right:4px}.organizer-menu-export.mat-mdc-menu-item{min-height:42px;padding:0 14px}.organizer-menu-export-icon{font-size:16px!important;width:16px!important;height:16px!important;color:#424242;margin-right:8px}.organizer-divider{margin:4px 0!important}.organizer-champs-wrapper{padding:4px 6px;min-width:200px;box-sizing:border-box;display:flex;flex-direction:column}.organizer-champs-block{display:flex;flex-direction:column}.organizer-champs-block-title{font-size:10px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:#9e9e9e;padding:6px 2px 2px}.organizer-champs-divider{margin:4px 0!important}.organizer-champs-wrapper .organizer-submenu-item{display:flex;align-items:center;gap:6px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:6px;font-size:13px;font-family:inherit;color:#212121;cursor:pointer;text-align:left;box-sizing:border-box;white-space:nowrap}.organizer-champs-wrapper .organizer-submenu-item:hover:not([disabled]){background:#f5f5f5}.organizer-champs-wrapper .organizer-submenu-item.active{font-weight:600}.organizer-champs-wrapper .organizer-submenu-item[disabled]{opacity:.38;cursor:default}.organizer-champs-wrapper .organizer-submenu-check{flex-shrink:0;width:16px;text-align:center;font-size:12px;color:#212121}.organizer-champs-wrapper .organizer-submenu-item--has-children{padding-right:8px}.organizer-champs-wrapper .organizer-submenu-arrow{font-size:18px!important;width:18px!important;height:18px!important;color:#00000061;margin-left:auto}\n"] }]
|
|
253
429
|
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { config: [{
|
|
254
430
|
type: Input
|
|
255
431
|
}], state: [{
|
|
@@ -741,32 +917,6 @@ const DEFAULT_MENU_ICONS = {
|
|
|
741
917
|
'custom': 'settings'
|
|
742
918
|
};
|
|
743
919
|
|
|
744
|
-
function buildYFields(indicators) {
|
|
745
|
-
const ordered = [];
|
|
746
|
-
const map = new Map();
|
|
747
|
-
for (const indicator of indicators) {
|
|
748
|
-
const groupKey = indicator.group;
|
|
749
|
-
if (groupKey) {
|
|
750
|
-
if (!map.has(groupKey)) {
|
|
751
|
-
ordered.push(groupKey);
|
|
752
|
-
map.set(groupKey, { id: groupKey, label: groupKey, aggregates: [] });
|
|
753
|
-
}
|
|
754
|
-
const parent = map.get(groupKey);
|
|
755
|
-
if (parent?.aggregates) {
|
|
756
|
-
parent.aggregates.push({ id: indicator.id, label: indicator.label });
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
else {
|
|
760
|
-
ordered.push(indicator.id);
|
|
761
|
-
map.set(indicator.id, { id: indicator.id, label: indicator.label });
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
return ordered.map(k => map.get(k)).filter((f) => !!f);
|
|
765
|
-
}
|
|
766
|
-
function resolveYKey(selectedY, selectedYAggregate) {
|
|
767
|
-
return selectedYAggregate ?? selectedY;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
920
|
function chartConfigToOrganizer(chartConfig, options = {}) {
|
|
771
921
|
if (!chartConfig)
|
|
772
922
|
return {};
|
|
@@ -791,6 +941,7 @@ function chartConfigToOrganizer(chartConfig, options = {}) {
|
|
|
791
941
|
yFields,
|
|
792
942
|
groups: mergedGroupFields,
|
|
793
943
|
slices: (chartConfig.filters?.items || []).map(f => ({ id: f.key, label: f.menu.label || f.key })),
|
|
944
|
+
templates: chartConfig.templates,
|
|
794
945
|
showReset: false,
|
|
795
946
|
onFetchSliceData,
|
|
796
947
|
showExport: !!(onExportVisual || onExportData),
|
|
@@ -807,13 +958,21 @@ function chartConfigToState(chartConfig) {
|
|
|
807
958
|
const activeGroup = chartConfig.groups?.items?.find(g => g.selected);
|
|
808
959
|
const activeSlices = (chartConfig.filters?.items || []).filter(f => f.selected);
|
|
809
960
|
const indicatorGroup = activeIndicator?.group;
|
|
810
|
-
|
|
961
|
+
const state = {
|
|
811
962
|
selectedX: activeGroup?.key,
|
|
812
963
|
selectedY: indicatorGroup ?? activeIndicator?.key,
|
|
813
964
|
selectedYAggregate: indicatorGroup ? activeIndicator?.key : undefined,
|
|
814
965
|
selectedGroupBy: activeStack?.key,
|
|
815
966
|
selectedSlices: activeSlices.map(f => f.key),
|
|
816
967
|
};
|
|
968
|
+
const organizerConfig = chartConfigToOrganizer(chartConfig);
|
|
969
|
+
return normalizeOrganizerState(state, organizerConfig);
|
|
970
|
+
}
|
|
971
|
+
function buildOrganizerChartBinding(chartConfig, options = {}) {
|
|
972
|
+
return {
|
|
973
|
+
config: chartConfigToOrganizer(chartConfig, options),
|
|
974
|
+
state: chartConfigToState(chartConfig)
|
|
975
|
+
};
|
|
817
976
|
}
|
|
818
977
|
function chartConfigToUnifiedState(chartConfig, viewMode = 'chart') {
|
|
819
978
|
const state = chartConfigToState(chartConfig);
|
|
@@ -841,6 +1000,31 @@ function applyOrganizerEventToChart(event, chartConfig) {
|
|
|
841
1000
|
_applySliceSelection(state.selectedSlices, chartConfig);
|
|
842
1001
|
event.resolvedYUnit = resolveYUnit(chartConfig, event.state.selectedY, event.state.selectedYAggregate);
|
|
843
1002
|
}
|
|
1003
|
+
function handleOrganizerChartEvent(event, chartConfig, currentBinding, options = {}) {
|
|
1004
|
+
if (event.type === 'viewSwitched') {
|
|
1005
|
+
return {
|
|
1006
|
+
binding: {
|
|
1007
|
+
config: chartConfigToOrganizer(chartConfig, options),
|
|
1008
|
+
state: { ...event.state }
|
|
1009
|
+
},
|
|
1010
|
+
shouldRefetch: false
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
applyOrganizerEventToChart(event, chartConfig);
|
|
1014
|
+
if (event.type === 'ySelected' || event.type === 'templateSelected') {
|
|
1015
|
+
return {
|
|
1016
|
+
binding: buildOrganizerChartBinding(chartConfig, options),
|
|
1017
|
+
shouldRefetch: true
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
return {
|
|
1021
|
+
binding: {
|
|
1022
|
+
config: currentBinding?.config ?? chartConfigToOrganizer(chartConfig, options),
|
|
1023
|
+
state: event.state
|
|
1024
|
+
},
|
|
1025
|
+
shouldRefetch: event.type !== 'sliceSelected'
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
844
1028
|
function resolveYUnit(chartConfig, selectedY, selectedYAggregate) {
|
|
845
1029
|
if (!chartConfig || !selectedY)
|
|
846
1030
|
return undefined;
|
|
@@ -1365,5 +1549,5 @@ class LazyFieldManager {
|
|
|
1365
1549
|
* Generated bundle index. Do not edit.
|
|
1366
1550
|
*/
|
|
1367
1551
|
|
|
1368
|
-
export { DEFAULT_MENU_ICONS, DEFAULT_MENU_LABELS, GroupByManager, LAZY_FIELD_ERROR_VALUE, LAZY_FIELD_LOADING_VALUE, LazyFieldManager, OrganizerButtonComponent, OrganizerButtonModule, OrganizerFacade, SlicePanelComponent, applyOrganizerEventToChart, buildYFields, chartConfigToOrganizer, chartConfigToState, chartConfigToUnifiedState, humanizeKey, resolveYKey, resolveYUnit };
|
|
1552
|
+
export { DEFAULT_MENU_ICONS, DEFAULT_MENU_LABELS, GroupByManager, LAZY_FIELD_ERROR_VALUE, LAZY_FIELD_LOADING_VALUE, LazyFieldManager, OrganizerButtonComponent, OrganizerButtonModule, OrganizerFacade, SlicePanelComponent, applyOrganizerEventToChart, buildOrganizerChartBinding, buildYFields, chartConfigToOrganizer, chartConfigToState, chartConfigToUnifiedState, handleOrganizerChartEvent, humanizeKey, resolveYKey, resolveYUnit };
|
|
1369
1553
|
//# sourceMappingURL=oneteme-jquery-organizer.mjs.map
|