@adminforth/dashboard 1.1.0 → 1.3.0
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 +43 -52
- package/custom/composables/useElementSize.ts +17 -2
- package/custom/model/dashboard.types.ts +385 -98
- package/custom/runtime/DashboardRuntime.vue +2 -1
- package/custom/runtime/WidgetRenderer.vue +2 -1
- package/custom/skills/adminforth-dashboard/SKILL.md +8 -4
- package/custom/widgets/chart/ChartWidget.vue +36 -35
- package/custom/widgets/chart/bar/BarChart.vue +20 -12
- package/custom/widgets/chart/chart.types.ts +42 -8
- package/custom/widgets/chart/chart.utils.ts +11 -0
- package/custom/widgets/chart/funnel/FunnelChart.vue +6 -4
- package/custom/widgets/chart/line/LineChart.vue +23 -15
- package/custom/widgets/chart/stacked-bar/StackedBarChart.vue +28 -43
- package/custom/widgets/gauge-card/GaugeCardWidget.vue +7 -43
- package/custom/widgets/kpi-card/KpiCardWidget.vue +6 -10
- package/custom/widgets/pivot-table/PivotTableWidget.vue +10 -11
- package/custom/widgets/table/TableWidget.vue +9 -4
- package/dist/custom/composables/useElementSize.js +14 -2
- package/dist/custom/composables/useElementSize.ts +17 -2
- package/dist/custom/model/dashboard.types.d.ts +179 -38
- package/dist/custom/model/dashboard.types.js +108 -42
- package/dist/custom/model/dashboard.types.ts +385 -98
- package/dist/custom/queries/useDashboardConfig.d.ts +832 -68
- package/dist/custom/queries/useWidgetData.d.ts +828 -64
- package/dist/custom/runtime/DashboardRuntime.vue +2 -1
- package/dist/custom/runtime/WidgetRenderer.vue +2 -1
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +8 -4
- package/dist/custom/widgets/chart/ChartWidget.vue +36 -35
- package/dist/custom/widgets/chart/bar/BarChart.vue +20 -12
- package/dist/custom/widgets/chart/chart.types.d.ts +14 -8
- package/dist/custom/widgets/chart/chart.types.js +23 -0
- package/dist/custom/widgets/chart/chart.types.ts +42 -8
- package/dist/custom/widgets/chart/chart.utils.d.ts +1 -0
- package/dist/custom/widgets/chart/chart.utils.js +7 -0
- package/dist/custom/widgets/chart/chart.utils.ts +11 -0
- package/dist/custom/widgets/chart/funnel/FunnelChart.vue +6 -4
- package/dist/custom/widgets/chart/line/LineChart.vue +23 -15
- package/dist/custom/widgets/chart/stacked-bar/StackedBarChart.vue +28 -43
- package/dist/custom/widgets/gauge-card/GaugeCardWidget.vue +7 -43
- package/dist/custom/widgets/kpi-card/KpiCardWidget.vue +6 -10
- package/dist/custom/widgets/pivot-table/PivotTableWidget.vue +10 -11
- package/dist/custom/widgets/table/TableWidget.vue +9 -4
- package/dist/endpoint/widgets.js +23 -3
- package/dist/schema/api.d.ts +2637 -933
- package/dist/schema/widget.d.ts +1562 -582
- package/dist/schema/widget.js +207 -127
- package/dist/services/widgetConfigValidator.js +16 -80
- package/dist/services/widgetDataService.d.ts +0 -9
- package/dist/services/widgetDataService.js +356 -97
- package/endpoint/dashboard.ts +1 -1
- package/endpoint/widgets.ts +29 -3
- package/package.json +1 -1
- package/schema/widget.ts +221 -121
- package/services/widgetConfigValidator.ts +29 -100
- package/services/widgetDataService.ts +478 -129
|
@@ -113,10 +113,11 @@
|
|
|
113
113
|
<script setup lang="ts">
|
|
114
114
|
import { computed, ref, watch } from 'vue'
|
|
115
115
|
import { useWidgetData } from '../../queries/useWidgetData.js'
|
|
116
|
-
import
|
|
116
|
+
import { getFieldRefField } from '../../model/dashboard.types.js'
|
|
117
|
+
import type { DashboardWidgetConfig, DashboardWidgetTableData, FieldRef } from '../../model/dashboard.types.js'
|
|
117
118
|
|
|
118
119
|
type TableWidgetConfig = {
|
|
119
|
-
columns?:
|
|
120
|
+
columns?: FieldRef[]
|
|
120
121
|
pagination?: boolean
|
|
121
122
|
pageSize?: number
|
|
122
123
|
}
|
|
@@ -132,7 +133,7 @@ const currentPage = ref(1)
|
|
|
132
133
|
const currentPageInput = ref(1)
|
|
133
134
|
const tableConfig = computed(() => props.widget.table as TableWidgetConfig | undefined)
|
|
134
135
|
const isPaginationEnabled = computed(() => tableConfig.value?.pagination !== false)
|
|
135
|
-
const pageSize = computed(() => tableConfig.value?.pageSize ??
|
|
136
|
+
const pageSize = computed(() => tableConfig.value?.pageSize ?? DEFAULT_PAGE_SIZE)
|
|
136
137
|
const dashboardSlugRef = computed(() => props.dashboardSlug)
|
|
137
138
|
const widgetIdRef = computed(() => props.widget.id)
|
|
138
139
|
const widgetDataRequest = computed(() => (
|
|
@@ -168,7 +169,11 @@ const tableData = computed(() => {
|
|
|
168
169
|
|
|
169
170
|
const columns = computed(() => {
|
|
170
171
|
const configuredColumns = tableConfig.value?.columns
|
|
171
|
-
|
|
172
|
+
if (configuredColumns) {
|
|
173
|
+
return configuredColumns.map((column) => getFieldRefField(column)).filter(Boolean) as string[]
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return tableData.value?.columns ?? []
|
|
172
177
|
})
|
|
173
178
|
|
|
174
179
|
const pagination = computed(() => tableData.value?.pagination)
|
|
@@ -7,19 +7,31 @@ function useElementSize() {
|
|
|
7
7
|
const width = (0, vue_1.ref)(0);
|
|
8
8
|
const height = (0, vue_1.ref)(0);
|
|
9
9
|
let observer;
|
|
10
|
+
let frameId;
|
|
10
11
|
(0, vue_1.onMounted)(() => {
|
|
11
12
|
observer = new ResizeObserver(([entry]) => {
|
|
12
13
|
if (!entry) {
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
const nextWidth = Math.floor(entry.contentRect.width);
|
|
17
|
+
const nextHeight = Math.floor(entry.contentRect.height);
|
|
18
|
+
if (frameId !== undefined) {
|
|
19
|
+
cancelAnimationFrame(frameId);
|
|
20
|
+
}
|
|
21
|
+
frameId = requestAnimationFrame(() => {
|
|
22
|
+
frameId = undefined;
|
|
23
|
+
width.value = nextWidth;
|
|
24
|
+
height.value = nextHeight;
|
|
25
|
+
});
|
|
17
26
|
});
|
|
18
27
|
if (el.value) {
|
|
19
28
|
observer.observe(el.value);
|
|
20
29
|
}
|
|
21
30
|
});
|
|
22
31
|
(0, vue_1.onBeforeUnmount)(() => {
|
|
32
|
+
if (frameId !== undefined) {
|
|
33
|
+
cancelAnimationFrame(frameId);
|
|
34
|
+
}
|
|
23
35
|
observer === null || observer === void 0 ? void 0 : observer.disconnect();
|
|
24
36
|
});
|
|
25
37
|
return {
|
|
@@ -13,6 +13,7 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
13
13
|
const height = ref(0)
|
|
14
14
|
|
|
15
15
|
let observer: ResizeObserver | undefined
|
|
16
|
+
let frameId: number | undefined
|
|
16
17
|
|
|
17
18
|
onMounted(() => {
|
|
18
19
|
observer = new ResizeObserver(([entry]) => {
|
|
@@ -20,8 +21,18 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
20
21
|
return
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const nextWidth = Math.floor(entry.contentRect.width)
|
|
25
|
+
const nextHeight = Math.floor(entry.contentRect.height)
|
|
26
|
+
|
|
27
|
+
if (frameId !== undefined) {
|
|
28
|
+
cancelAnimationFrame(frameId)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
frameId = requestAnimationFrame(() => {
|
|
32
|
+
frameId = undefined
|
|
33
|
+
width.value = nextWidth
|
|
34
|
+
height.value = nextHeight
|
|
35
|
+
})
|
|
25
36
|
})
|
|
26
37
|
|
|
27
38
|
if (el.value) {
|
|
@@ -30,6 +41,10 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
30
41
|
})
|
|
31
42
|
|
|
32
43
|
onBeforeUnmount(() => {
|
|
44
|
+
if (frameId !== undefined) {
|
|
45
|
+
cancelAnimationFrame(frameId)
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
observer?.disconnect()
|
|
34
49
|
})
|
|
35
50
|
|
|
@@ -1,33 +1,4 @@
|
|
|
1
1
|
import type { ChartWidgetConfig } from '../widgets/chart/chart.types.js';
|
|
2
|
-
export type AggregationOperation = 'sum' | 'count' | 'avg' | 'min' | 'max' | 'median';
|
|
3
|
-
export type AggregationRule = {
|
|
4
|
-
operation: AggregationOperation;
|
|
5
|
-
field?: string;
|
|
6
|
-
};
|
|
7
|
-
export type GroupByRule = {
|
|
8
|
-
type: 'field';
|
|
9
|
-
field: string;
|
|
10
|
-
} | {
|
|
11
|
-
type: 'date_trunc';
|
|
12
|
-
field: string;
|
|
13
|
-
truncation: 'day' | 'week' | 'month' | 'year';
|
|
14
|
-
timezone?: string;
|
|
15
|
-
};
|
|
16
|
-
export type ResourceWidgetDataSource = {
|
|
17
|
-
type: 'resource';
|
|
18
|
-
resourceId: string;
|
|
19
|
-
columns?: string[];
|
|
20
|
-
sort?: unknown;
|
|
21
|
-
filters?: unknown;
|
|
22
|
-
};
|
|
23
|
-
export type AggregateWidgetDataSource = {
|
|
24
|
-
type: 'aggregate';
|
|
25
|
-
resourceId: string;
|
|
26
|
-
aggregations: Record<string, AggregationRule>;
|
|
27
|
-
groupBy?: GroupByRule;
|
|
28
|
-
filters?: unknown;
|
|
29
|
-
};
|
|
30
|
-
export type WidgetDataSource = ResourceWidgetDataSource | AggregateWidgetDataSource;
|
|
31
2
|
export type DashboardConfig = {
|
|
32
3
|
version: number;
|
|
33
4
|
groups: DashboardGroupConfig[];
|
|
@@ -42,6 +13,9 @@ export type DashboardGroupMoveDirection = 'up' | 'down';
|
|
|
42
13
|
export type DashboardWidgetMoveDirection = 'up' | 'down';
|
|
43
14
|
export type DashboardWidgetTarget = 'empty' | 'table' | 'chart' | 'kpi_card' | 'pivot_table' | 'gauge_card';
|
|
44
15
|
export type DashboardWidgetSize = 'small' | 'medium' | 'large' | 'wide' | 'full';
|
|
16
|
+
export type QueryAggregateOperation = 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median';
|
|
17
|
+
export type TimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
|
|
18
|
+
export type ValueFormat = 'number' | 'compact_number' | 'currency' | 'percent' | 'percent_delta' | 'number_delta' | 'currency_delta';
|
|
45
19
|
export type WidgetLayout = {
|
|
46
20
|
size?: DashboardWidgetSize;
|
|
47
21
|
width?: number;
|
|
@@ -49,7 +23,7 @@ export type WidgetLayout = {
|
|
|
49
23
|
maxWidth?: number | null;
|
|
50
24
|
height?: number;
|
|
51
25
|
};
|
|
52
|
-
export type
|
|
26
|
+
export type WidgetBaseConfig = {
|
|
53
27
|
id: string;
|
|
54
28
|
group_id: string;
|
|
55
29
|
label?: string;
|
|
@@ -59,15 +33,173 @@ export type DashboardWidgetConfig = {
|
|
|
59
33
|
minWidth?: number;
|
|
60
34
|
maxWidth?: number | null;
|
|
61
35
|
order: number;
|
|
62
|
-
target: DashboardWidgetTarget;
|
|
63
|
-
dataSource?: WidgetDataSource;
|
|
64
|
-
chart?: ChartWidgetConfig;
|
|
65
|
-
table?: unknown;
|
|
66
|
-
kpi_card?: unknown;
|
|
67
|
-
pivot_table?: unknown;
|
|
68
|
-
gauge_card?: unknown;
|
|
69
|
-
query?: unknown;
|
|
70
36
|
};
|
|
37
|
+
export type FilterExpression = {
|
|
38
|
+
and: FilterExpression[];
|
|
39
|
+
} | {
|
|
40
|
+
or: FilterExpression[];
|
|
41
|
+
} | Array<FilterExpression> | {
|
|
42
|
+
field: string;
|
|
43
|
+
eq?: unknown;
|
|
44
|
+
neq?: unknown;
|
|
45
|
+
gt?: unknown;
|
|
46
|
+
gte?: unknown;
|
|
47
|
+
lt?: unknown;
|
|
48
|
+
lte?: unknown;
|
|
49
|
+
in?: unknown[];
|
|
50
|
+
not_in?: unknown[];
|
|
51
|
+
like?: unknown;
|
|
52
|
+
ilike?: unknown;
|
|
53
|
+
};
|
|
54
|
+
export type QueryFieldSelectItem = {
|
|
55
|
+
field: string;
|
|
56
|
+
as?: string;
|
|
57
|
+
grain?: TimeGrain;
|
|
58
|
+
};
|
|
59
|
+
export type QueryAggregateSelectItem = {
|
|
60
|
+
agg: QueryAggregateOperation;
|
|
61
|
+
field?: string;
|
|
62
|
+
as: string;
|
|
63
|
+
filters?: FilterExpression;
|
|
64
|
+
};
|
|
65
|
+
export type QueryCalcSelectItem = {
|
|
66
|
+
calc: string;
|
|
67
|
+
as: string;
|
|
68
|
+
};
|
|
69
|
+
export type QuerySelectItem = QueryFieldSelectItem | QueryAggregateSelectItem | QueryCalcSelectItem;
|
|
70
|
+
export type QueryGroupByItem = string | {
|
|
71
|
+
field: string;
|
|
72
|
+
as?: string;
|
|
73
|
+
grain?: TimeGrain;
|
|
74
|
+
timezone?: string;
|
|
75
|
+
};
|
|
76
|
+
export type QueryOrderByItem = {
|
|
77
|
+
field: string;
|
|
78
|
+
direction?: 'asc' | 'desc';
|
|
79
|
+
};
|
|
80
|
+
export type QueryConfig = {
|
|
81
|
+
resource: string;
|
|
82
|
+
select?: QuerySelectItem[];
|
|
83
|
+
filters?: FilterExpression;
|
|
84
|
+
groupBy?: QueryGroupByItem[];
|
|
85
|
+
orderBy?: QueryOrderByItem[];
|
|
86
|
+
limit?: number;
|
|
87
|
+
offset?: number;
|
|
88
|
+
timeSeries?: {
|
|
89
|
+
field: string;
|
|
90
|
+
grain: TimeGrain;
|
|
91
|
+
timezone?: string;
|
|
92
|
+
};
|
|
93
|
+
period?: {
|
|
94
|
+
field: string;
|
|
95
|
+
gte?: unknown;
|
|
96
|
+
lt?: unknown;
|
|
97
|
+
};
|
|
98
|
+
bucket?: {
|
|
99
|
+
field: string;
|
|
100
|
+
buckets: Array<{
|
|
101
|
+
label: string;
|
|
102
|
+
min?: number;
|
|
103
|
+
max?: number;
|
|
104
|
+
}>;
|
|
105
|
+
};
|
|
106
|
+
calcs?: QueryCalcSelectItem[];
|
|
107
|
+
formatting?: Record<string, unknown>;
|
|
108
|
+
};
|
|
109
|
+
export type FunnelQueryConfig = {
|
|
110
|
+
steps: FunnelQueryStep[];
|
|
111
|
+
};
|
|
112
|
+
export type FunnelQueryStep = {
|
|
113
|
+
name: string;
|
|
114
|
+
resource: string;
|
|
115
|
+
metric: QueryAggregateSelectItem;
|
|
116
|
+
filters?: FilterExpression;
|
|
117
|
+
};
|
|
118
|
+
export type FieldRef = string | {
|
|
119
|
+
field: string;
|
|
120
|
+
label?: string;
|
|
121
|
+
format?: ValueFormat;
|
|
122
|
+
};
|
|
123
|
+
export type TableViewConfig = {
|
|
124
|
+
columns?: FieldRef[];
|
|
125
|
+
pagination?: boolean;
|
|
126
|
+
pageSize?: number;
|
|
127
|
+
};
|
|
128
|
+
export type KpiCardViewConfig = {
|
|
129
|
+
title?: string;
|
|
130
|
+
value: {
|
|
131
|
+
field: string;
|
|
132
|
+
format?: ValueFormat;
|
|
133
|
+
prefix?: string;
|
|
134
|
+
suffix?: string;
|
|
135
|
+
};
|
|
136
|
+
subtitle?: {
|
|
137
|
+
text?: string;
|
|
138
|
+
field?: string;
|
|
139
|
+
};
|
|
140
|
+
comparison?: unknown;
|
|
141
|
+
sparkline?: unknown;
|
|
142
|
+
};
|
|
143
|
+
export type GaugeCardViewConfig = {
|
|
144
|
+
title?: string;
|
|
145
|
+
value: {
|
|
146
|
+
field: string;
|
|
147
|
+
format?: ValueFormat;
|
|
148
|
+
prefix?: string;
|
|
149
|
+
suffix?: string;
|
|
150
|
+
};
|
|
151
|
+
target?: {
|
|
152
|
+
value?: number;
|
|
153
|
+
field?: string;
|
|
154
|
+
label?: string;
|
|
155
|
+
};
|
|
156
|
+
progress?: {
|
|
157
|
+
valueField: string;
|
|
158
|
+
targetValue?: number;
|
|
159
|
+
targetField?: string;
|
|
160
|
+
format?: ValueFormat;
|
|
161
|
+
};
|
|
162
|
+
color?: string;
|
|
163
|
+
};
|
|
164
|
+
export type PivotTableViewConfig = {
|
|
165
|
+
rows: FieldRef[];
|
|
166
|
+
columns?: FieldRef[];
|
|
167
|
+
values: Array<{
|
|
168
|
+
field: string;
|
|
169
|
+
label?: string;
|
|
170
|
+
format?: ValueFormat;
|
|
171
|
+
aggregation?: 'sum' | 'count' | 'avg' | 'min' | 'max';
|
|
172
|
+
}>;
|
|
173
|
+
};
|
|
174
|
+
export type EmptyWidgetConfig = WidgetBaseConfig & {
|
|
175
|
+
target: 'empty';
|
|
176
|
+
};
|
|
177
|
+
export type TableWidgetConfig = WidgetBaseConfig & {
|
|
178
|
+
target: 'table';
|
|
179
|
+
table?: TableViewConfig;
|
|
180
|
+
query: QueryConfig;
|
|
181
|
+
};
|
|
182
|
+
export type ChartDashboardWidgetConfig = WidgetBaseConfig & {
|
|
183
|
+
target: 'chart';
|
|
184
|
+
chart: ChartWidgetConfig;
|
|
185
|
+
query: QueryConfig | FunnelQueryConfig;
|
|
186
|
+
};
|
|
187
|
+
export type KpiCardWidgetConfig = WidgetBaseConfig & {
|
|
188
|
+
target: 'kpi_card';
|
|
189
|
+
card: KpiCardViewConfig;
|
|
190
|
+
query: QueryConfig;
|
|
191
|
+
};
|
|
192
|
+
export type GaugeCardWidgetConfig = WidgetBaseConfig & {
|
|
193
|
+
target: 'gauge_card';
|
|
194
|
+
card: GaugeCardViewConfig;
|
|
195
|
+
query: QueryConfig;
|
|
196
|
+
};
|
|
197
|
+
export type PivotTableWidgetConfig = WidgetBaseConfig & {
|
|
198
|
+
target: 'pivot_table';
|
|
199
|
+
pivot: PivotTableViewConfig;
|
|
200
|
+
query: QueryConfig;
|
|
201
|
+
};
|
|
202
|
+
export type DashboardWidgetConfig = EmptyWidgetConfig | TableWidgetConfig | ChartDashboardWidgetConfig | KpiCardWidgetConfig | GaugeCardWidgetConfig | PivotTableWidgetConfig;
|
|
71
203
|
export type DashboardWidgetTableData = {
|
|
72
204
|
kind?: 'table';
|
|
73
205
|
columns: string[];
|
|
@@ -84,7 +216,16 @@ export type DashboardWidgetAggregateData = {
|
|
|
84
216
|
columns: string[];
|
|
85
217
|
rows: Record<string, unknown>[];
|
|
86
218
|
values?: Record<string, unknown>;
|
|
219
|
+
pagination?: {
|
|
220
|
+
page: number;
|
|
221
|
+
pageSize: number;
|
|
222
|
+
total: number;
|
|
223
|
+
totalPages: number;
|
|
224
|
+
};
|
|
87
225
|
};
|
|
88
226
|
export type DashboardWidgetData = DashboardWidgetTableData | DashboardWidgetAggregateData;
|
|
89
227
|
export declare function normalizeDashboardConfig(config: unknown): DashboardConfig;
|
|
90
228
|
export declare function normalizeDashboardWidgetConfig(config: unknown): unknown;
|
|
229
|
+
export declare function serializeDashboardWidgetConfigForEditor(widget: DashboardWidgetConfig): Record<string, unknown>;
|
|
230
|
+
export declare function getFieldRefField(value: FieldRef | undefined): string | undefined;
|
|
231
|
+
export declare function getFieldRefLabel(value: FieldRef | undefined): string | undefined;
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeDashboardConfig = normalizeDashboardConfig;
|
|
4
4
|
exports.normalizeDashboardWidgetConfig = normalizeDashboardWidgetConfig;
|
|
5
|
+
exports.serializeDashboardWidgetConfigForEditor = serializeDashboardWidgetConfigForEditor;
|
|
6
|
+
exports.getFieldRefField = getFieldRefField;
|
|
7
|
+
exports.getFieldRefLabel = getFieldRefLabel;
|
|
5
8
|
function normalizeDashboardConfig(config) {
|
|
6
9
|
const value = isRecord(config) ? config : {};
|
|
7
10
|
return {
|
|
@@ -13,29 +16,59 @@ function normalizeDashboardConfig(config) {
|
|
|
13
16
|
};
|
|
14
17
|
}
|
|
15
18
|
function normalizeDashboardWidgetConfig(config) {
|
|
16
|
-
var _a;
|
|
17
19
|
if (!isRecord(config)) {
|
|
18
20
|
return config;
|
|
19
21
|
}
|
|
20
22
|
const normalized = Object.assign({}, config);
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
normalized.
|
|
23
|
+
normalizeWidgetLayoutConfig(normalized);
|
|
24
|
+
if (normalized.query !== undefined) {
|
|
25
|
+
normalized.query = normalizeQueryConfig(normalized.query);
|
|
26
|
+
}
|
|
27
|
+
if (normalized.table !== undefined) {
|
|
28
|
+
normalized.table = normalizeTableConfig(normalized.table);
|
|
29
|
+
}
|
|
30
|
+
if (normalized.card !== undefined) {
|
|
31
|
+
normalized.card = normalizeCardConfig(normalized.card);
|
|
24
32
|
}
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
if (kpiCardConfig !== undefined) {
|
|
28
|
-
normalized.kpi_card = kpiCardConfig;
|
|
29
|
-
}
|
|
33
|
+
if (normalized.pivot !== undefined) {
|
|
34
|
+
normalized.pivot = normalizePivotConfig(normalized.pivot);
|
|
30
35
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
normalized.gauge_card = gaugeCardConfig;
|
|
35
|
-
}
|
|
36
|
+
const target = normalizeDashboardWidgetTarget(normalized.target);
|
|
37
|
+
if (target !== undefined) {
|
|
38
|
+
normalized.target = target;
|
|
36
39
|
}
|
|
37
40
|
return normalized;
|
|
38
41
|
}
|
|
42
|
+
function serializeDashboardWidgetConfigForEditor(widget) {
|
|
43
|
+
const serialized = Object.assign({}, widget);
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(serialized, 'minWidth')) {
|
|
45
|
+
serialized.min_width = widget.minWidth;
|
|
46
|
+
delete serialized.minWidth;
|
|
47
|
+
}
|
|
48
|
+
if (Object.prototype.hasOwnProperty.call(serialized, 'maxWidth')) {
|
|
49
|
+
serialized.max_width = widget.maxWidth;
|
|
50
|
+
delete serialized.maxWidth;
|
|
51
|
+
}
|
|
52
|
+
if ('query' in widget) {
|
|
53
|
+
serialized.query = serializeQueryConfigForEditor(widget.query);
|
|
54
|
+
}
|
|
55
|
+
if ('table' in widget && widget.table !== undefined) {
|
|
56
|
+
serialized.table = serializeTableConfigForEditor(widget.table);
|
|
57
|
+
}
|
|
58
|
+
if ('card' in widget && widget.card !== undefined) {
|
|
59
|
+
serialized.card = serializeCardConfigForEditor(widget.card);
|
|
60
|
+
}
|
|
61
|
+
if ('pivot' in widget && widget.pivot !== undefined) {
|
|
62
|
+
serialized.pivot = serializePivotConfigForEditor(widget.pivot);
|
|
63
|
+
}
|
|
64
|
+
return serialized;
|
|
65
|
+
}
|
|
66
|
+
function getFieldRefField(value) {
|
|
67
|
+
return typeof value === 'string' ? value : value === null || value === void 0 ? void 0 : value.field;
|
|
68
|
+
}
|
|
69
|
+
function getFieldRefLabel(value) {
|
|
70
|
+
return typeof value === 'string' ? value : value === null || value === void 0 ? void 0 : value.label;
|
|
71
|
+
}
|
|
39
72
|
function normalizeDashboardWidgetTarget(value) {
|
|
40
73
|
switch (value) {
|
|
41
74
|
case 'empty':
|
|
@@ -49,46 +82,79 @@ function normalizeDashboardWidgetTarget(value) {
|
|
|
49
82
|
return undefined;
|
|
50
83
|
}
|
|
51
84
|
}
|
|
52
|
-
function
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
85
|
+
function normalizeWidgetLayoutConfig(value) {
|
|
86
|
+
if (value.min_width !== undefined) {
|
|
87
|
+
value.minWidth = value.min_width;
|
|
88
|
+
}
|
|
89
|
+
if (value.max_width !== undefined) {
|
|
90
|
+
value.maxWidth = value.max_width;
|
|
56
91
|
}
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
}
|
|
93
|
+
function normalizeQueryConfig(value) {
|
|
94
|
+
if (!isRecord(value)) {
|
|
95
|
+
return value;
|
|
59
96
|
}
|
|
60
|
-
if (
|
|
61
|
-
|
|
97
|
+
if (Array.isArray(value.steps)) {
|
|
98
|
+
return {
|
|
99
|
+
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
100
|
+
};
|
|
62
101
|
}
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({}, value), (Array.isArray(value.group_by) ? { groupBy: value.group_by } : {})), (Array.isArray(value.order_by) ? { orderBy: value.order_by } : {})), (value.time_series !== undefined ? { timeSeries: value.time_series } : {}));
|
|
103
|
+
}
|
|
104
|
+
function normalizeFunnelQueryStep(value) {
|
|
105
|
+
if (!isRecord(value)) {
|
|
106
|
+
return value;
|
|
65
107
|
}
|
|
66
|
-
return Object.
|
|
108
|
+
return Object.assign(Object.assign({}, value), (typeof value.resource_id === 'string' ? { resource: value.resource_id } : {}));
|
|
67
109
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
config.value_field = value.valueField;
|
|
110
|
+
function normalizeTableConfig(value) {
|
|
111
|
+
if (!isRecord(value)) {
|
|
112
|
+
return value;
|
|
72
113
|
}
|
|
73
|
-
|
|
74
|
-
|
|
114
|
+
return Object.assign(Object.assign({}, value), (value.page_size !== undefined ? { pageSize: value.page_size } : {}));
|
|
115
|
+
}
|
|
116
|
+
function normalizeCardConfig(value) {
|
|
117
|
+
if (!isRecord(value)) {
|
|
118
|
+
return value;
|
|
75
119
|
}
|
|
76
|
-
|
|
77
|
-
|
|
120
|
+
const normalized = Object.assign({}, value);
|
|
121
|
+
if (isRecord(normalized.progress)) {
|
|
122
|
+
normalized.progress = Object.assign(Object.assign(Object.assign(Object.assign({}, normalized.progress), (normalized.progress.value_field !== undefined ? { valueField: normalized.progress.value_field } : {})), (normalized.progress.target_value !== undefined ? { targetValue: normalized.progress.target_value } : {})), (normalized.progress.target_field !== undefined ? { targetField: normalized.progress.target_field } : {}));
|
|
78
123
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
124
|
+
if (isRecord(normalized.comparison)) {
|
|
125
|
+
normalized.comparison = Object.assign(Object.assign({}, normalized.comparison), (normalized.comparison.positive_is_good !== undefined ? { positiveIsGood: normalized.comparison.positive_is_good } : {}));
|
|
81
126
|
}
|
|
82
|
-
|
|
83
|
-
|
|
127
|
+
return normalized;
|
|
128
|
+
}
|
|
129
|
+
function normalizePivotConfig(value) {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
function serializeQueryConfigForEditor(value) {
|
|
133
|
+
if ('steps' in value) {
|
|
134
|
+
return {
|
|
135
|
+
steps: value.steps.map((step) => (Object.assign(Object.assign({}, step), { resource_id: step.resource, resource: undefined }))).map((step) => removeUndefinedFields(step)),
|
|
136
|
+
};
|
|
84
137
|
}
|
|
85
|
-
|
|
86
|
-
|
|
138
|
+
return removeUndefinedFields(Object.assign(Object.assign({}, value), { group_by: value.groupBy, groupBy: undefined, order_by: value.orderBy, orderBy: undefined, time_series: value.timeSeries, timeSeries: undefined }));
|
|
139
|
+
}
|
|
140
|
+
function serializeTableConfigForEditor(value) {
|
|
141
|
+
return removeUndefinedFields(Object.assign(Object.assign({}, value), { page_size: value.pageSize, pageSize: undefined }));
|
|
142
|
+
}
|
|
143
|
+
function serializeCardConfigForEditor(value) {
|
|
144
|
+
const serialized = Object.assign({}, value);
|
|
145
|
+
if (isRecord(serialized.progress)) {
|
|
146
|
+
serialized.progress = removeUndefinedFields(Object.assign(Object.assign({}, serialized.progress), { value_field: serialized.progress.valueField, valueField: undefined, target_value: serialized.progress.targetValue, targetValue: undefined, target_field: serialized.progress.targetField, targetField: undefined }));
|
|
87
147
|
}
|
|
88
|
-
if (
|
|
89
|
-
|
|
148
|
+
if (isRecord(serialized.comparison)) {
|
|
149
|
+
serialized.comparison = removeUndefinedFields(Object.assign(Object.assign({}, serialized.comparison), { positive_is_good: serialized.comparison.positiveIsGood, positiveIsGood: undefined }));
|
|
90
150
|
}
|
|
91
|
-
return
|
|
151
|
+
return removeUndefinedFields(serialized);
|
|
152
|
+
}
|
|
153
|
+
function serializePivotConfigForEditor(value) {
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
function removeUndefinedFields(value) {
|
|
157
|
+
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
92
158
|
}
|
|
93
159
|
function isRecord(value) {
|
|
94
160
|
return typeof value === 'object' && value !== null;
|