@devtable/dashboard 0.4.0 → 1.2.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/dist/api-caller/index.d.ts +9 -2
- package/dist/contexts/definition-context.d.ts +2 -1
- package/dist/contexts/panel-context.d.ts +2 -2
- package/dist/dashboard.es.js +1212 -500
- package/dist/dashboard.umd.js +17 -6
- package/dist/definition-editor/data-source-editor/context-and-snippets.d.ts +5 -0
- package/dist/definition-editor/data-source-editor/data-preview.d.ts +4 -0
- package/dist/definition-editor/data-source-editor/editor.d.ts +6 -0
- package/dist/definition-editor/data-source-editor/form.d.ts +8 -0
- package/dist/definition-editor/data-source-editor/index.d.ts +7 -0
- package/dist/definition-editor/data-source-editor/select-or-add-data-source.d.ts +7 -0
- package/dist/definition-editor/index.d.ts +2 -0
- package/dist/{panel/settings/context-info/index.d.ts → definition-editor/sql-snippet-editor/context-info.d.ts} +0 -0
- package/dist/definition-editor/sql-snippet-editor/editor.d.ts +5 -0
- package/dist/definition-editor/sql-snippet-editor/index.d.ts +7 -0
- package/dist/layout/index.d.ts +1 -2
- package/dist/main/main.d.ts +3 -1
- package/dist/main/read-only.d.ts +3 -1
- package/dist/panel/index.d.ts +1 -1
- package/dist/panel/panel-description.d.ts +7 -0
- package/dist/panel/settings/{viz-config → panel-config}/description.d.ts +0 -0
- package/dist/panel/settings/panel-config/index.d.ts +5 -0
- package/dist/panel/settings/panel-config/preview-panel.d.ts +2 -0
- package/dist/panel/settings/{viz-config → panel-config}/title.d.ts +0 -0
- package/dist/panel/settings/pick-data-source/index.d.ts +5 -0
- package/dist/panel/settings/viz-config/preview-viz.d.ts +5 -0
- package/dist/style.css +1 -1
- package/dist/types/dashboard.d.ts +8 -1
- package/package.json +4 -2
- package/dist/panel/settings/query-editor/index.d.ts +0 -2
- package/dist/panel/settings/query-editor/sql-query-editor/index.d.ts +0 -5
- package/dist/panel/settings/query-result/index.d.ts +0 -5
- package/dist/panel/settings/sql-snippets/form.d.ts +0 -9
- package/dist/panel/settings/sql-snippets/index.d.ts +0 -5
package/dist/dashboard.es.js
CHANGED
|
@@ -32,11 +32,12 @@ var __objRest = (source, exclude) => {
|
|
|
32
32
|
import React from "react";
|
|
33
33
|
import _ from "lodash";
|
|
34
34
|
import { WidthProvider, Responsive } from "react-grid-layout";
|
|
35
|
-
import {
|
|
35
|
+
import { Popover, Tooltip, Group, Text, ActionIcon, TextInput, Box, LoadingOverlay, Table, Select, Button, useMantineTheme, ColorSwatch, Switch, Slider, JsonInput, Modal, AppShell, Tabs, Menu, Divider, Container, SegmentedControl, Textarea } from "@mantine/core";
|
|
36
36
|
import { useRequest } from "ahooks";
|
|
37
37
|
import axios from "axios";
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
38
|
+
import { InfoCircle, DeviceFloppy, Trash, Refresh, Settings, Paint, PlayerPlay, PlaylistAdd, ClipboardText, Database, Recycle, Share } from "tabler-icons-react";
|
|
39
|
+
import RichTextEditor, { RichTextEditor as RichTextEditor$1 } from "@mantine/rte";
|
|
40
|
+
import { useInputState, useElementSize, randomId } from "@mantine/hooks";
|
|
40
41
|
import ReactEChartsCore from "echarts-for-react/lib/core";
|
|
41
42
|
import * as echarts from "echarts/core";
|
|
42
43
|
import { SunburstChart, BarChart, LineChart } from "echarts/charts";
|
|
@@ -44,9 +45,9 @@ import { CanvasRenderer } from "echarts/renderers";
|
|
|
44
45
|
import { GridComponent, LegendComponent, TooltipComponent, VisualMapComponent } from "echarts/components";
|
|
45
46
|
import numbro from "numbro";
|
|
46
47
|
import "echarts-gl";
|
|
48
|
+
import { useForm, Controller } from "react-hook-form";
|
|
49
|
+
import { formList, useForm as useForm$1 } from "@mantine/form";
|
|
47
50
|
import { Prism } from "@mantine/prism";
|
|
48
|
-
import { formList, useForm } from "@mantine/form";
|
|
49
|
-
import { useForm as useForm$1, Controller } from "react-hook-form";
|
|
50
51
|
var DashboardMode = /* @__PURE__ */ ((DashboardMode2) => {
|
|
51
52
|
DashboardMode2["Use"] = "use";
|
|
52
53
|
DashboardMode2["Edit"] = "edit";
|
|
@@ -87,7 +88,14 @@ const post = getRequest("POST");
|
|
|
87
88
|
function formatSQL(sql, params) {
|
|
88
89
|
const names = Object.keys(params);
|
|
89
90
|
const vals = Object.values(params);
|
|
90
|
-
|
|
91
|
+
try {
|
|
92
|
+
return new Function(...names, `return \`${sql}\`;`)(...vals);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (names.length === 0 && sql.includes("$")) {
|
|
95
|
+
throw new Error("[formatSQL] insufficient params");
|
|
96
|
+
}
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
91
99
|
}
|
|
92
100
|
function getSQLParams(context, definitions) {
|
|
93
101
|
const sqlSnippetRecord = definitions.sqlSnippets.reduce((ret, curr) => {
|
|
@@ -96,24 +104,26 @@ function getSQLParams(context, definitions) {
|
|
|
96
104
|
}, {});
|
|
97
105
|
return _.merge({}, sqlSnippetRecord, context);
|
|
98
106
|
}
|
|
99
|
-
const queryBySQL = (
|
|
100
|
-
if (!sql) {
|
|
107
|
+
const queryBySQL = ({ context, definitions, title, dataSource }) => async () => {
|
|
108
|
+
if (!dataSource || !dataSource.sql) {
|
|
101
109
|
return [];
|
|
102
110
|
}
|
|
111
|
+
const { type, key, sql } = dataSource;
|
|
103
112
|
const needParams = sql.includes("$");
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
113
|
+
try {
|
|
114
|
+
const params = getSQLParams(context, definitions);
|
|
115
|
+
const formattedSQL = formatSQL(sql, params);
|
|
116
|
+
if (needParams) {
|
|
117
|
+
console.groupCollapsed(`Final SQL for: ${title}`);
|
|
118
|
+
console.log(formattedSQL);
|
|
119
|
+
console.groupEnd();
|
|
120
|
+
}
|
|
121
|
+
const res = await post("/query", { type, key, sql: formattedSQL });
|
|
122
|
+
return res;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error(error);
|
|
107
125
|
return [];
|
|
108
126
|
}
|
|
109
|
-
const formattedSQL = formatSQL(sql, params);
|
|
110
|
-
if (needParams) {
|
|
111
|
-
console.groupCollapsed(`Final SQL for: ${title}`);
|
|
112
|
-
console.log(formattedSQL);
|
|
113
|
-
console.groupEnd();
|
|
114
|
-
}
|
|
115
|
-
const res = await post("/query", { sql: formattedSQL });
|
|
116
|
-
return res;
|
|
117
127
|
};
|
|
118
128
|
const initialContext$2 = {};
|
|
119
129
|
const initialContextInfoContext = initialContext$2;
|
|
@@ -127,8 +137,8 @@ const initialContext$1 = {
|
|
|
127
137
|
description: "",
|
|
128
138
|
setDescription: () => {
|
|
129
139
|
},
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
dataSourceID: "",
|
|
141
|
+
setDataSourceID: () => {
|
|
132
142
|
},
|
|
133
143
|
viz: {
|
|
134
144
|
type: "",
|
|
@@ -140,6 +150,15 @@ const initialContext$1 = {
|
|
|
140
150
|
}
|
|
141
151
|
};
|
|
142
152
|
const PanelContext = React.createContext(initialContext$1);
|
|
153
|
+
const initialContext = {
|
|
154
|
+
sqlSnippets: [],
|
|
155
|
+
setSQLSnippets: () => {
|
|
156
|
+
},
|
|
157
|
+
dataSources: [],
|
|
158
|
+
setDataSources: () => {
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const DefinitionContext = React.createContext(initialContext);
|
|
143
162
|
var jsxRuntime = { exports: {} };
|
|
144
163
|
var reactJsxRuntime_production_min = {};
|
|
145
164
|
/**
|
|
@@ -173,6 +192,105 @@ reactJsxRuntime_production_min.jsxs = q;
|
|
|
173
192
|
const jsx = jsxRuntime.exports.jsx;
|
|
174
193
|
const jsxs = jsxRuntime.exports.jsxs;
|
|
175
194
|
const Fragment = jsxRuntime.exports.Fragment;
|
|
195
|
+
function DescriptionPopover({
|
|
196
|
+
position,
|
|
197
|
+
trigger = "click"
|
|
198
|
+
}) {
|
|
199
|
+
const {
|
|
200
|
+
freezeLayout
|
|
201
|
+
} = React.useContext(LayoutStateContext);
|
|
202
|
+
const [opened, setOpened] = React.useState(false);
|
|
203
|
+
const {
|
|
204
|
+
description
|
|
205
|
+
} = React.useContext(PanelContext);
|
|
206
|
+
React.useEffect(() => {
|
|
207
|
+
freezeLayout(opened);
|
|
208
|
+
}, [opened]);
|
|
209
|
+
if (!description) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
const target = trigger === "click" ? /* @__PURE__ */ jsx(Tooltip, {
|
|
213
|
+
label: "Click to see description",
|
|
214
|
+
openDelay: 500,
|
|
215
|
+
children: /* @__PURE__ */ jsx(InfoCircle, {
|
|
216
|
+
size: 20,
|
|
217
|
+
onClick: () => setOpened((v) => !v),
|
|
218
|
+
style: {
|
|
219
|
+
verticalAlign: "baseline",
|
|
220
|
+
cursor: "pointer"
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
}) : /* @__PURE__ */ jsx(InfoCircle, {
|
|
224
|
+
size: 20,
|
|
225
|
+
onMouseEnter: () => setOpened(true),
|
|
226
|
+
onMouseLeave: () => setOpened(false),
|
|
227
|
+
style: {
|
|
228
|
+
verticalAlign: "baseline",
|
|
229
|
+
cursor: "pointer"
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
return /* @__PURE__ */ jsx(Popover, {
|
|
233
|
+
opened,
|
|
234
|
+
onClose: () => setOpened(false),
|
|
235
|
+
withCloseButton: true,
|
|
236
|
+
withArrow: true,
|
|
237
|
+
trapFocus: true,
|
|
238
|
+
closeOnEscape: false,
|
|
239
|
+
placement: "center",
|
|
240
|
+
position,
|
|
241
|
+
target,
|
|
242
|
+
children: /* @__PURE__ */ jsx(RichTextEditor, {
|
|
243
|
+
readOnly: true,
|
|
244
|
+
value: description,
|
|
245
|
+
onChange: _.noop,
|
|
246
|
+
sx: {
|
|
247
|
+
border: "none"
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function EditDescription() {
|
|
253
|
+
const {
|
|
254
|
+
description,
|
|
255
|
+
setDescription
|
|
256
|
+
} = React.useContext(PanelContext);
|
|
257
|
+
const [value, onChange] = React.useState(description);
|
|
258
|
+
const changed = description !== value;
|
|
259
|
+
const submit = React.useCallback(() => {
|
|
260
|
+
if (!changed) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
setDescription(value);
|
|
264
|
+
}, [changed, value]);
|
|
265
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
266
|
+
direction: "column",
|
|
267
|
+
sx: {
|
|
268
|
+
flexGrow: 1
|
|
269
|
+
},
|
|
270
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
271
|
+
align: "end",
|
|
272
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
273
|
+
children: "Description"
|
|
274
|
+
}), /* @__PURE__ */ jsx(ActionIcon, {
|
|
275
|
+
variant: "hover",
|
|
276
|
+
color: "blue",
|
|
277
|
+
disabled: !changed,
|
|
278
|
+
onClick: submit,
|
|
279
|
+
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
280
|
+
size: 20
|
|
281
|
+
})
|
|
282
|
+
})]
|
|
283
|
+
}), /* @__PURE__ */ jsx(RichTextEditor$1, {
|
|
284
|
+
value,
|
|
285
|
+
onChange,
|
|
286
|
+
sx: {
|
|
287
|
+
flexGrow: 1
|
|
288
|
+
},
|
|
289
|
+
sticky: true,
|
|
290
|
+
p: "0"
|
|
291
|
+
})]
|
|
292
|
+
});
|
|
293
|
+
}
|
|
176
294
|
class ErrorBoundary extends React.Component {
|
|
177
295
|
constructor(props) {
|
|
178
296
|
super(props);
|
|
@@ -194,6 +312,240 @@ class ErrorBoundary extends React.Component {
|
|
|
194
312
|
return this.props.children;
|
|
195
313
|
}
|
|
196
314
|
}
|
|
315
|
+
function PreviewPanel() {
|
|
316
|
+
const {
|
|
317
|
+
title
|
|
318
|
+
} = React.useContext(PanelContext);
|
|
319
|
+
return /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
320
|
+
children: /* @__PURE__ */ jsxs(Group, {
|
|
321
|
+
direction: "column",
|
|
322
|
+
grow: true,
|
|
323
|
+
noWrap: true,
|
|
324
|
+
mx: "auto",
|
|
325
|
+
mt: "xl",
|
|
326
|
+
p: "5px",
|
|
327
|
+
spacing: "xs",
|
|
328
|
+
sx: {
|
|
329
|
+
width: "600px",
|
|
330
|
+
height: "450px",
|
|
331
|
+
background: "transparent",
|
|
332
|
+
borderRadius: "5px",
|
|
333
|
+
boxShadow: "0px 0px 10px 0px rgba(0,0,0,.2)"
|
|
334
|
+
},
|
|
335
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
336
|
+
position: "apart",
|
|
337
|
+
noWrap: true,
|
|
338
|
+
sx: {
|
|
339
|
+
borderBottom: "1px solid #eee",
|
|
340
|
+
paddingBottom: "5px",
|
|
341
|
+
flexGrow: 0,
|
|
342
|
+
flexShrink: 0
|
|
343
|
+
},
|
|
344
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
345
|
+
children: /* @__PURE__ */ jsx(DescriptionPopover, {
|
|
346
|
+
position: "bottom",
|
|
347
|
+
trigger: "hover"
|
|
348
|
+
})
|
|
349
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
350
|
+
grow: true,
|
|
351
|
+
position: "center",
|
|
352
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
353
|
+
lineClamp: 1,
|
|
354
|
+
weight: "bold",
|
|
355
|
+
children: title
|
|
356
|
+
})
|
|
357
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
358
|
+
position: "right",
|
|
359
|
+
spacing: 0,
|
|
360
|
+
sx: {
|
|
361
|
+
height: "28px"
|
|
362
|
+
}
|
|
363
|
+
})]
|
|
364
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
365
|
+
sx: {
|
|
366
|
+
background: "#eee",
|
|
367
|
+
flexGrow: 1
|
|
368
|
+
}
|
|
369
|
+
})]
|
|
370
|
+
})
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
function EditTitle() {
|
|
374
|
+
const {
|
|
375
|
+
title,
|
|
376
|
+
setTitle
|
|
377
|
+
} = React.useContext(PanelContext);
|
|
378
|
+
const [localTitle, setLocalTitle] = useInputState(title);
|
|
379
|
+
const changed = title !== localTitle;
|
|
380
|
+
const submit = React.useCallback(() => {
|
|
381
|
+
if (!changed) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
setTitle(localTitle);
|
|
385
|
+
}, [changed, localTitle]);
|
|
386
|
+
return /* @__PURE__ */ jsx(TextInput, {
|
|
387
|
+
value: localTitle,
|
|
388
|
+
onChange: setLocalTitle,
|
|
389
|
+
label: /* @__PURE__ */ jsxs(Group, {
|
|
390
|
+
align: "end",
|
|
391
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
392
|
+
children: "Panel Title"
|
|
393
|
+
}), /* @__PURE__ */ jsx(ActionIcon, {
|
|
394
|
+
variant: "hover",
|
|
395
|
+
color: "blue",
|
|
396
|
+
disabled: !changed,
|
|
397
|
+
onClick: submit,
|
|
398
|
+
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
399
|
+
size: 20
|
|
400
|
+
})
|
|
401
|
+
})]
|
|
402
|
+
})
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
function PanelConfig({}) {
|
|
406
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
407
|
+
direction: "row",
|
|
408
|
+
grow: true,
|
|
409
|
+
noWrap: true,
|
|
410
|
+
align: "stretch",
|
|
411
|
+
sx: {
|
|
412
|
+
height: "100%"
|
|
413
|
+
},
|
|
414
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
415
|
+
grow: true,
|
|
416
|
+
direction: "column",
|
|
417
|
+
sx: {
|
|
418
|
+
width: "40%",
|
|
419
|
+
flexShrink: 0,
|
|
420
|
+
flexGrow: 0,
|
|
421
|
+
height: "100%"
|
|
422
|
+
},
|
|
423
|
+
children: [/* @__PURE__ */ jsx(EditTitle, {}), /* @__PURE__ */ jsx(EditDescription, {})]
|
|
424
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
425
|
+
sx: {
|
|
426
|
+
height: "100%",
|
|
427
|
+
flexGrow: 1,
|
|
428
|
+
maxWidth: "60%"
|
|
429
|
+
},
|
|
430
|
+
children: /* @__PURE__ */ jsx(PreviewPanel, {})
|
|
431
|
+
})]
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
function DataPreview({
|
|
435
|
+
id
|
|
436
|
+
}) {
|
|
437
|
+
const definitions = React.useContext(DefinitionContext);
|
|
438
|
+
const contextInfo = React.useContext(ContextInfoContext);
|
|
439
|
+
const dataSource = React.useMemo(() => {
|
|
440
|
+
return definitions.dataSources.find((d) => d.id === id);
|
|
441
|
+
}, [definitions.dataSources, id]);
|
|
442
|
+
const {
|
|
443
|
+
data = [],
|
|
444
|
+
loading
|
|
445
|
+
} = useRequest(queryBySQL({
|
|
446
|
+
context: contextInfo,
|
|
447
|
+
definitions,
|
|
448
|
+
title: id,
|
|
449
|
+
dataSource
|
|
450
|
+
}), {
|
|
451
|
+
refreshDeps: [contextInfo, definitions, dataSource]
|
|
452
|
+
});
|
|
453
|
+
if (loading) {
|
|
454
|
+
return /* @__PURE__ */ jsx(LoadingOverlay, {
|
|
455
|
+
visible: loading
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
if (data.length === 0) {
|
|
459
|
+
return /* @__PURE__ */ jsx(Table, {});
|
|
460
|
+
}
|
|
461
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
462
|
+
my: "xl",
|
|
463
|
+
direction: "column",
|
|
464
|
+
grow: true,
|
|
465
|
+
sx: {
|
|
466
|
+
border: "1px solid #eee"
|
|
467
|
+
},
|
|
468
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
469
|
+
position: "left",
|
|
470
|
+
py: "md",
|
|
471
|
+
pl: "md",
|
|
472
|
+
sx: {
|
|
473
|
+
borderBottom: "1px solid #eee",
|
|
474
|
+
background: "#efefef"
|
|
475
|
+
},
|
|
476
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
477
|
+
weight: 500,
|
|
478
|
+
children: "Preview Data"
|
|
479
|
+
})
|
|
480
|
+
}), /* @__PURE__ */ jsxs(Table, {
|
|
481
|
+
children: [/* @__PURE__ */ jsx("thead", {
|
|
482
|
+
children: /* @__PURE__ */ jsx("tr", {
|
|
483
|
+
children: Object.keys(data == null ? void 0 : data[0]).map((label) => /* @__PURE__ */ jsx("th", {
|
|
484
|
+
children: label
|
|
485
|
+
}, label))
|
|
486
|
+
})
|
|
487
|
+
}), /* @__PURE__ */ jsx("tbody", {
|
|
488
|
+
children: data.map((row, index2) => /* @__PURE__ */ jsx("tr", {
|
|
489
|
+
children: Object.values(row).map((v, i) => /* @__PURE__ */ jsx("td", {
|
|
490
|
+
children: /* @__PURE__ */ jsx(Group, {
|
|
491
|
+
sx: {
|
|
492
|
+
"&, .mantine-Text-root": {
|
|
493
|
+
fontFamily: "monospace"
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
497
|
+
children: v
|
|
498
|
+
})
|
|
499
|
+
})
|
|
500
|
+
}, `${v}--${i}`))
|
|
501
|
+
}, `row-${index2}`))
|
|
502
|
+
})]
|
|
503
|
+
})]
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
function PickDataSource({}) {
|
|
507
|
+
const {
|
|
508
|
+
dataSources
|
|
509
|
+
} = React.useContext(DefinitionContext);
|
|
510
|
+
const {
|
|
511
|
+
dataSourceID,
|
|
512
|
+
setDataSourceID,
|
|
513
|
+
data,
|
|
514
|
+
loading
|
|
515
|
+
} = React.useContext(PanelContext);
|
|
516
|
+
const options = React.useMemo(() => {
|
|
517
|
+
return dataSources.map((d) => ({
|
|
518
|
+
value: d.id,
|
|
519
|
+
label: d.id
|
|
520
|
+
}));
|
|
521
|
+
}, [dataSources]);
|
|
522
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
523
|
+
direction: "column",
|
|
524
|
+
grow: true,
|
|
525
|
+
noWrap: true,
|
|
526
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
527
|
+
position: "left",
|
|
528
|
+
sx: {
|
|
529
|
+
maxWidth: "600px",
|
|
530
|
+
alignItems: "baseline"
|
|
531
|
+
},
|
|
532
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
533
|
+
children: "Select a Data Source"
|
|
534
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
535
|
+
data: options,
|
|
536
|
+
value: dataSourceID,
|
|
537
|
+
onChange: setDataSourceID,
|
|
538
|
+
allowDeselect: false,
|
|
539
|
+
clearable: false,
|
|
540
|
+
sx: {
|
|
541
|
+
flexGrow: 1
|
|
542
|
+
}
|
|
543
|
+
})]
|
|
544
|
+
}), /* @__PURE__ */ jsx(DataPreview, {
|
|
545
|
+
id: dataSourceID
|
|
546
|
+
})]
|
|
547
|
+
});
|
|
548
|
+
}
|
|
197
549
|
echarts.use([SunburstChart, CanvasRenderer]);
|
|
198
550
|
const defaultOption$1 = {
|
|
199
551
|
tooltip: {
|
|
@@ -244,8 +596,8 @@ function Sunbrust({
|
|
|
244
596
|
}
|
|
245
597
|
}
|
|
246
598
|
}
|
|
247
|
-
}), []);
|
|
248
|
-
const option = _.merge(defaultOption$1, labelOption, restConf, {
|
|
599
|
+
}), [max]);
|
|
600
|
+
const option = _.merge({}, defaultOption$1, labelOption, restConf, {
|
|
249
601
|
series: {
|
|
250
602
|
data: chartData
|
|
251
603
|
}
|
|
@@ -560,7 +912,7 @@ function VizBar3D({
|
|
|
560
912
|
}
|
|
561
913
|
});
|
|
562
914
|
}
|
|
563
|
-
var index$
|
|
915
|
+
var index$2 = "";
|
|
564
916
|
function renderViz(width, height, data, viz) {
|
|
565
917
|
const props = {
|
|
566
918
|
width,
|
|
@@ -613,287 +965,23 @@ function Viz({
|
|
|
613
965
|
}), !empty && renderViz(width, height, data, viz)]
|
|
614
966
|
});
|
|
615
967
|
}
|
|
616
|
-
function
|
|
617
|
-
const contextInfo = React.useContext(ContextInfoContext);
|
|
618
|
-
const sampleSQL = `SELECT *
|
|
619
|
-
FROM commit
|
|
620
|
-
WHERE author_time BETWEEN '\${timeRange?.[0].toISOString()}' AND '\${timeRange?.[1].toISOString()}'`;
|
|
621
|
-
return /* @__PURE__ */ jsxs(Group, {
|
|
622
|
-
direction: "column",
|
|
623
|
-
children: [/* @__PURE__ */ jsx(Prism, {
|
|
624
|
-
language: "sql",
|
|
625
|
-
sx: {
|
|
626
|
-
width: "100%"
|
|
627
|
-
},
|
|
628
|
-
noCopy: true,
|
|
629
|
-
colorScheme: "dark",
|
|
630
|
-
children: `-- You may refer context data *by name*
|
|
631
|
-
-- in SQL or VizConfig.
|
|
632
|
-
|
|
633
|
-
${sampleSQL}`
|
|
634
|
-
}), /* @__PURE__ */ jsx(Text, {
|
|
635
|
-
weight: 700,
|
|
636
|
-
children: "Avaiable context entries"
|
|
637
|
-
}), /* @__PURE__ */ jsx(Prism, {
|
|
638
|
-
language: "json",
|
|
639
|
-
sx: {
|
|
640
|
-
width: "100%"
|
|
641
|
-
},
|
|
642
|
-
noCopy: true,
|
|
643
|
-
colorScheme: "dark",
|
|
644
|
-
children: JSON.stringify(contextInfo, null, 2)
|
|
645
|
-
})]
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
var index$2 = "";
|
|
649
|
-
function SQLQueryEditor({}) {
|
|
650
|
-
const {
|
|
651
|
-
sql,
|
|
652
|
-
setSQL
|
|
653
|
-
} = React.useContext(PanelContext);
|
|
654
|
-
const [showPreview, setShowPreview] = React.useState(true);
|
|
655
|
-
const handleChange = (e) => {
|
|
656
|
-
setSQL(e.target.value);
|
|
657
|
-
};
|
|
658
|
-
const togglePreview = React.useCallback(() => {
|
|
659
|
-
setShowPreview((v) => !v);
|
|
660
|
-
}, []);
|
|
661
|
-
const format = React.useCallback(() => {
|
|
662
|
-
setSQL((sql2) => sql2.trim());
|
|
663
|
-
}, [setSQL]);
|
|
664
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
665
|
-
className: "sql-query-editor-root",
|
|
666
|
-
sx: {
|
|
667
|
-
height: "100%"
|
|
668
|
-
},
|
|
669
|
-
children: [/* @__PURE__ */ jsx(Textarea, {
|
|
670
|
-
value: sql,
|
|
671
|
-
onChange: handleChange,
|
|
672
|
-
minRows: 20,
|
|
673
|
-
maxRows: 20
|
|
674
|
-
}), /* @__PURE__ */ jsxs(Group, {
|
|
675
|
-
m: "md",
|
|
676
|
-
position: "right",
|
|
677
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
678
|
-
color: "blue",
|
|
679
|
-
onClick: format,
|
|
680
|
-
children: "Format"
|
|
681
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
682
|
-
variant: "default",
|
|
683
|
-
onClick: togglePreview,
|
|
684
|
-
children: "Toggle Preview"
|
|
685
|
-
})]
|
|
686
|
-
}), showPreview && /* @__PURE__ */ jsx(Prism, {
|
|
687
|
-
language: "sql",
|
|
688
|
-
withLineNumbers: true,
|
|
689
|
-
noCopy: true,
|
|
690
|
-
colorScheme: "dark",
|
|
691
|
-
children: sql
|
|
692
|
-
})]
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
|
-
const QueryEditor = SQLQueryEditor;
|
|
696
|
-
function QueryResult({}) {
|
|
968
|
+
function PreviewViz({}) {
|
|
697
969
|
const {
|
|
698
|
-
data
|
|
970
|
+
data,
|
|
971
|
+
loading,
|
|
972
|
+
viz
|
|
699
973
|
} = React.useContext(PanelContext);
|
|
700
|
-
return /* @__PURE__ */
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
children: "Data Length: "
|
|
707
|
-
}), data.length]
|
|
708
|
-
}), /* @__PURE__ */ jsx(Prism, {
|
|
709
|
-
language: "json",
|
|
710
|
-
colorScheme: "dark",
|
|
711
|
-
children: JSON.stringify(data, null, 2)
|
|
712
|
-
})]
|
|
974
|
+
return /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
975
|
+
children: /* @__PURE__ */ jsx(Viz, {
|
|
976
|
+
viz,
|
|
977
|
+
data,
|
|
978
|
+
loading
|
|
979
|
+
})
|
|
713
980
|
});
|
|
714
981
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
const DefinitionContext = React.createContext(initialContext);
|
|
721
|
-
function SQLSnippetsForm({
|
|
722
|
-
sqlSnippets,
|
|
723
|
-
setSQLSnippets
|
|
724
|
-
}) {
|
|
725
|
-
const initialValues = React.useMemo(() => ({
|
|
726
|
-
snippets: formList(sqlSnippets != null ? sqlSnippets : [])
|
|
727
|
-
}), [sqlSnippets]);
|
|
728
|
-
const form = useForm({
|
|
729
|
-
initialValues
|
|
730
|
-
});
|
|
731
|
-
const addSnippet = () => form.addListItem("snippets", {
|
|
732
|
-
key: randomId(),
|
|
733
|
-
value: ""
|
|
734
|
-
});
|
|
735
|
-
const changed = React.useMemo(() => !_.isEqual(form.values, initialValues), [form.values, initialValues]);
|
|
736
|
-
const submit = ({
|
|
737
|
-
snippets
|
|
738
|
-
}) => {
|
|
739
|
-
setSQLSnippets(snippets);
|
|
740
|
-
};
|
|
741
|
-
return /* @__PURE__ */ jsx(Group, {
|
|
742
|
-
direction: "column",
|
|
743
|
-
sx: {
|
|
744
|
-
width: "100%",
|
|
745
|
-
position: "relative"
|
|
746
|
-
},
|
|
747
|
-
grow: true,
|
|
748
|
-
children: /* @__PURE__ */ jsxs("form", {
|
|
749
|
-
onSubmit: form.onSubmit(submit),
|
|
750
|
-
children: [form.values.snippets.map((_item, index2) => /* @__PURE__ */ jsxs(Group, {
|
|
751
|
-
direction: "column",
|
|
752
|
-
grow: true,
|
|
753
|
-
my: 0,
|
|
754
|
-
p: "md",
|
|
755
|
-
pr: 40,
|
|
756
|
-
sx: {
|
|
757
|
-
border: "1px solid #eee",
|
|
758
|
-
position: "relative"
|
|
759
|
-
},
|
|
760
|
-
children: [/* @__PURE__ */ jsx(TextInput, __spreadValues({
|
|
761
|
-
label: "Key",
|
|
762
|
-
required: true
|
|
763
|
-
}, form.getListInputProps("snippets", index2, "key"))), /* @__PURE__ */ jsx(Textarea, __spreadValues({
|
|
764
|
-
minRows: 3,
|
|
765
|
-
label: "Value",
|
|
766
|
-
required: true
|
|
767
|
-
}, form.getListInputProps("snippets", index2, "value"))), /* @__PURE__ */ jsx(ActionIcon, {
|
|
768
|
-
color: "red",
|
|
769
|
-
variant: "hover",
|
|
770
|
-
onClick: () => form.removeListItem("snippets", index2),
|
|
771
|
-
sx: {
|
|
772
|
-
position: "absolute",
|
|
773
|
-
top: 15,
|
|
774
|
-
right: 5
|
|
775
|
-
},
|
|
776
|
-
children: /* @__PURE__ */ jsx(Trash, {
|
|
777
|
-
size: 16
|
|
778
|
-
})
|
|
779
|
-
})]
|
|
780
|
-
}, index2)), /* @__PURE__ */ jsxs(Group, {
|
|
781
|
-
position: "center",
|
|
782
|
-
mt: "xl",
|
|
783
|
-
grow: true,
|
|
784
|
-
sx: {
|
|
785
|
-
width: "80%"
|
|
786
|
-
},
|
|
787
|
-
mx: "auto",
|
|
788
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
789
|
-
variant: "default",
|
|
790
|
-
onClick: addSnippet,
|
|
791
|
-
children: "Add a snippet"
|
|
792
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
793
|
-
color: "blue",
|
|
794
|
-
type: "submit",
|
|
795
|
-
disabled: !changed,
|
|
796
|
-
children: "Submit"
|
|
797
|
-
})]
|
|
798
|
-
})]
|
|
799
|
-
})
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
function SQLSnippetsTab({}) {
|
|
803
|
-
const {
|
|
804
|
-
sqlSnippets,
|
|
805
|
-
setSQLSnippets
|
|
806
|
-
} = React.useContext(DefinitionContext);
|
|
807
|
-
const sampleSQL = `SELECT *
|
|
808
|
-
FROM commit
|
|
809
|
-
WHERE \${author_time_condition}`;
|
|
810
|
-
return /* @__PURE__ */ jsxs(Group, {
|
|
811
|
-
direction: "column",
|
|
812
|
-
children: [/* @__PURE__ */ jsx(Prism, {
|
|
813
|
-
language: "sql",
|
|
814
|
-
sx: {
|
|
815
|
-
width: "100%"
|
|
816
|
-
},
|
|
817
|
-
noCopy: true,
|
|
818
|
-
trim: false,
|
|
819
|
-
colorScheme: "dark",
|
|
820
|
-
children: `-- You may refer context data *by name*
|
|
821
|
-
-- in SQL or VizConfig.
|
|
822
|
-
|
|
823
|
-
${sampleSQL}
|
|
824
|
-
|
|
825
|
-
-- where author_time_condition is:
|
|
826
|
-
author_time BETWEEN '\${timeRange?.[0].toISOString()}' AND '\${timeRange?.[1].toISOString()}'
|
|
827
|
-
`
|
|
828
|
-
}), /* @__PURE__ */ jsx(Text, {
|
|
829
|
-
weight: 700,
|
|
830
|
-
children: "SQL Snippets"
|
|
831
|
-
}), /* @__PURE__ */ jsx(SQLSnippetsForm, {
|
|
832
|
-
sqlSnippets,
|
|
833
|
-
setSQLSnippets
|
|
834
|
-
})]
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
function EditDescription() {
|
|
838
|
-
const {
|
|
839
|
-
description,
|
|
840
|
-
setDescription
|
|
841
|
-
} = React.useContext(PanelContext);
|
|
842
|
-
const [localDesc, setLocalDesc] = useInputState(description);
|
|
843
|
-
const changed = description !== localDesc;
|
|
844
|
-
const submit = React.useCallback(() => {
|
|
845
|
-
if (!changed) {
|
|
846
|
-
return;
|
|
847
|
-
}
|
|
848
|
-
setDescription(localDesc);
|
|
849
|
-
}, [changed, localDesc]);
|
|
850
|
-
return /* @__PURE__ */ jsx(Textarea, {
|
|
851
|
-
label: "Panel Description",
|
|
852
|
-
value: localDesc,
|
|
853
|
-
onChange: setLocalDesc,
|
|
854
|
-
minRows: 2,
|
|
855
|
-
rightSection: /* @__PURE__ */ jsx(ActionIcon, {
|
|
856
|
-
disabled: !changed,
|
|
857
|
-
onClick: submit,
|
|
858
|
-
sx: {
|
|
859
|
-
alignSelf: "flex-start",
|
|
860
|
-
marginTop: "4px"
|
|
861
|
-
},
|
|
862
|
-
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
863
|
-
size: 20
|
|
864
|
-
})
|
|
865
|
-
})
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
function EditTitle() {
|
|
869
|
-
const {
|
|
870
|
-
title,
|
|
871
|
-
setTitle
|
|
872
|
-
} = React.useContext(PanelContext);
|
|
873
|
-
const [localTitle, setLocalTitle] = useInputState(title);
|
|
874
|
-
const changed = title !== localTitle;
|
|
875
|
-
const submit = React.useCallback(() => {
|
|
876
|
-
if (!changed) {
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
setTitle(localTitle);
|
|
880
|
-
}, [changed, localTitle]);
|
|
881
|
-
return /* @__PURE__ */ jsx(TextInput, {
|
|
882
|
-
label: "Panel Title",
|
|
883
|
-
value: localTitle,
|
|
884
|
-
onChange: setLocalTitle,
|
|
885
|
-
rightSection: /* @__PURE__ */ jsx(ActionIcon, {
|
|
886
|
-
disabled: !changed,
|
|
887
|
-
onClick: submit,
|
|
888
|
-
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
889
|
-
size: 20
|
|
890
|
-
})
|
|
891
|
-
})
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
function VizBar3DPanel({
|
|
895
|
-
conf,
|
|
896
|
-
setConf
|
|
982
|
+
function VizBar3DPanel({
|
|
983
|
+
conf,
|
|
984
|
+
setConf
|
|
897
985
|
}) {
|
|
898
986
|
const defaultValues = _.assign({}, {
|
|
899
987
|
"x_axis_data_key": "x",
|
|
@@ -916,7 +1004,7 @@ function VizBar3DPanel({
|
|
|
916
1004
|
control,
|
|
917
1005
|
handleSubmit,
|
|
918
1006
|
formState
|
|
919
|
-
} = useForm
|
|
1007
|
+
} = useForm({
|
|
920
1008
|
defaultValues
|
|
921
1009
|
});
|
|
922
1010
|
return /* @__PURE__ */ jsx(Group, {
|
|
@@ -1119,7 +1207,7 @@ function VizLineBarChartPanel({
|
|
|
1119
1207
|
const initialValues = React.useMemo(() => __spreadValues({
|
|
1120
1208
|
series: formList(series != null ? series : [])
|
|
1121
1209
|
}, restConf), [series, restConf]);
|
|
1122
|
-
const form = useForm({
|
|
1210
|
+
const form = useForm$1({
|
|
1123
1211
|
initialValues
|
|
1124
1212
|
});
|
|
1125
1213
|
const addSeries = () => form.addListItem("series", {
|
|
@@ -1231,7 +1319,7 @@ function SunburstPanel({
|
|
|
1231
1319
|
},
|
|
1232
1320
|
setConf
|
|
1233
1321
|
}) {
|
|
1234
|
-
const form = useForm({
|
|
1322
|
+
const form = useForm$1({
|
|
1235
1323
|
initialValues: {
|
|
1236
1324
|
label_field,
|
|
1237
1325
|
value_field
|
|
@@ -1318,7 +1406,7 @@ function VizTablePanel(_a) {
|
|
|
1318
1406
|
]), {
|
|
1319
1407
|
setConf
|
|
1320
1408
|
} = _b;
|
|
1321
|
-
const form = useForm({
|
|
1409
|
+
const form = useForm$1({
|
|
1322
1410
|
initialValues: __spreadValues({
|
|
1323
1411
|
id_field: "id",
|
|
1324
1412
|
use_raw_columns: true,
|
|
@@ -1593,7 +1681,7 @@ function VizTextPanel({
|
|
|
1593
1681
|
setConf
|
|
1594
1682
|
}) {
|
|
1595
1683
|
var _a;
|
|
1596
|
-
const form = useForm({
|
|
1684
|
+
const form = useForm$1({
|
|
1597
1685
|
initialValues: {
|
|
1598
1686
|
paragraphs: formList((_a = conf.paragraphs) != null ? _a : sampleParagraphs)
|
|
1599
1687
|
}
|
|
@@ -1788,9 +1876,31 @@ function EditVizConf() {
|
|
|
1788
1876
|
}
|
|
1789
1877
|
function VizConfig({}) {
|
|
1790
1878
|
return /* @__PURE__ */ jsxs(Group, {
|
|
1879
|
+
direction: "row",
|
|
1791
1880
|
grow: true,
|
|
1792
|
-
|
|
1793
|
-
|
|
1881
|
+
noWrap: true,
|
|
1882
|
+
align: "stretch",
|
|
1883
|
+
sx: {
|
|
1884
|
+
height: "100%"
|
|
1885
|
+
},
|
|
1886
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
1887
|
+
grow: true,
|
|
1888
|
+
direction: "column",
|
|
1889
|
+
noWrap: true,
|
|
1890
|
+
sx: {
|
|
1891
|
+
width: "40%",
|
|
1892
|
+
flexShrink: 0,
|
|
1893
|
+
flexGrow: 0
|
|
1894
|
+
},
|
|
1895
|
+
children: /* @__PURE__ */ jsx(EditVizConf, {})
|
|
1896
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
1897
|
+
sx: {
|
|
1898
|
+
height: "100%",
|
|
1899
|
+
flexGrow: 1,
|
|
1900
|
+
maxWidth: "60%"
|
|
1901
|
+
},
|
|
1902
|
+
children: /* @__PURE__ */ jsx(PreviewViz, {})
|
|
1903
|
+
})]
|
|
1794
1904
|
});
|
|
1795
1905
|
}
|
|
1796
1906
|
function PanelSettingsModal({
|
|
@@ -1832,40 +1942,20 @@ function PanelSettingsModal({
|
|
|
1832
1942
|
}
|
|
1833
1943
|
},
|
|
1834
1944
|
padding: "md",
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
}), /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
1850
|
-
label: "SQL",
|
|
1851
|
-
children: /* @__PURE__ */ jsx(QueryEditor, {})
|
|
1852
|
-
}), /* @__PURE__ */ jsxs(Tabs.Tab, {
|
|
1853
|
-
label: "Data",
|
|
1854
|
-
children: [/* @__PURE__ */ jsx(LoadingOverlay, {
|
|
1855
|
-
visible: loading
|
|
1856
|
-
}), /* @__PURE__ */ jsx(QueryResult, {})]
|
|
1857
|
-
}), /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
1858
|
-
label: "Viz Config",
|
|
1859
|
-
children: /* @__PURE__ */ jsx(VizConfig, {})
|
|
1860
|
-
})]
|
|
1861
|
-
})
|
|
1862
|
-
}),
|
|
1863
|
-
children: /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
1864
|
-
children: /* @__PURE__ */ jsx(Viz, {
|
|
1865
|
-
viz,
|
|
1866
|
-
data,
|
|
1867
|
-
loading
|
|
1868
|
-
})
|
|
1945
|
+
children: /* @__PURE__ */ jsxs(Tabs, {
|
|
1946
|
+
initialTab: 2,
|
|
1947
|
+
children: [/* @__PURE__ */ jsxs(Tabs.Tab, {
|
|
1948
|
+
label: "Data Source",
|
|
1949
|
+
children: [/* @__PURE__ */ jsx(LoadingOverlay, {
|
|
1950
|
+
visible: loading
|
|
1951
|
+
}), /* @__PURE__ */ jsx(PickDataSource, {})]
|
|
1952
|
+
}), /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
1953
|
+
label: "Panel",
|
|
1954
|
+
children: /* @__PURE__ */ jsx(PanelConfig, {})
|
|
1955
|
+
}), /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
1956
|
+
label: "Visualization",
|
|
1957
|
+
children: /* @__PURE__ */ jsx(VizConfig, {})
|
|
1958
|
+
})]
|
|
1869
1959
|
})
|
|
1870
1960
|
})
|
|
1871
1961
|
});
|
|
@@ -1876,8 +1966,6 @@ function PanelTitleBar({}) {
|
|
|
1876
1966
|
const close = () => setOpened(false);
|
|
1877
1967
|
const {
|
|
1878
1968
|
title,
|
|
1879
|
-
description,
|
|
1880
|
-
loading,
|
|
1881
1969
|
refreshData
|
|
1882
1970
|
} = React.useContext(PanelContext);
|
|
1883
1971
|
const {
|
|
@@ -1891,17 +1979,7 @@ function PanelTitleBar({}) {
|
|
|
1891
1979
|
paddingBottom: "5px"
|
|
1892
1980
|
},
|
|
1893
1981
|
children: [/* @__PURE__ */ jsx(Group, {
|
|
1894
|
-
children:
|
|
1895
|
-
label: description,
|
|
1896
|
-
withArrow: true,
|
|
1897
|
-
children: /* @__PURE__ */ jsx(InfoCircle, {
|
|
1898
|
-
size: 12,
|
|
1899
|
-
style: {
|
|
1900
|
-
verticalAlign: "baseline",
|
|
1901
|
-
cursor: "pointer"
|
|
1902
|
-
}
|
|
1903
|
-
})
|
|
1904
|
-
})
|
|
1982
|
+
children: /* @__PURE__ */ jsx(DescriptionPopover, {})
|
|
1905
1983
|
}), /* @__PURE__ */ jsx(Group, {
|
|
1906
1984
|
grow: true,
|
|
1907
1985
|
position: "center",
|
|
@@ -1947,7 +2025,7 @@ function PanelTitleBar({}) {
|
|
|
1947
2025
|
var index$1 = "";
|
|
1948
2026
|
function Panel({
|
|
1949
2027
|
viz: initialViz,
|
|
1950
|
-
|
|
2028
|
+
dataSourceID: initialDataSourceID,
|
|
1951
2029
|
title: initialTitle,
|
|
1952
2030
|
description: initialDesc,
|
|
1953
2031
|
update,
|
|
@@ -1958,24 +2036,35 @@ function Panel({
|
|
|
1958
2036
|
const definitions = React.useContext(DefinitionContext);
|
|
1959
2037
|
const [title, setTitle] = React.useState(initialTitle);
|
|
1960
2038
|
const [description, setDescription] = React.useState(initialDesc);
|
|
1961
|
-
const [
|
|
2039
|
+
const [dataSourceID, setDataSourceID] = React.useState(initialDataSourceID);
|
|
1962
2040
|
const [viz, setViz] = React.useState(initialViz);
|
|
2041
|
+
const dataSource = React.useMemo(() => {
|
|
2042
|
+
if (!dataSourceID) {
|
|
2043
|
+
return void 0;
|
|
2044
|
+
}
|
|
2045
|
+
return definitions.dataSources.find((d) => d.id === dataSourceID);
|
|
2046
|
+
}, [dataSourceID, definitions.dataSources]);
|
|
1963
2047
|
React.useEffect(() => {
|
|
1964
2048
|
update == null ? void 0 : update({
|
|
1965
2049
|
id,
|
|
1966
2050
|
layout,
|
|
1967
2051
|
title,
|
|
1968
2052
|
description,
|
|
1969
|
-
|
|
2053
|
+
dataSourceID,
|
|
1970
2054
|
viz
|
|
1971
2055
|
});
|
|
1972
|
-
}, [title, description,
|
|
2056
|
+
}, [title, description, dataSource, viz, id, layout, dataSourceID]);
|
|
1973
2057
|
const {
|
|
1974
2058
|
data = [],
|
|
1975
2059
|
loading,
|
|
1976
2060
|
refresh
|
|
1977
|
-
} = useRequest(queryBySQL(
|
|
1978
|
-
|
|
2061
|
+
} = useRequest(queryBySQL({
|
|
2062
|
+
context: contextInfo,
|
|
2063
|
+
definitions,
|
|
2064
|
+
title,
|
|
2065
|
+
dataSource
|
|
2066
|
+
}), {
|
|
2067
|
+
refreshDeps: [contextInfo, definitions, dataSource]
|
|
1979
2068
|
});
|
|
1980
2069
|
const refreshData = refresh;
|
|
1981
2070
|
return /* @__PURE__ */ jsx(PanelContext.Provider, {
|
|
@@ -1986,8 +2075,8 @@ function Panel({
|
|
|
1986
2075
|
setTitle,
|
|
1987
2076
|
description,
|
|
1988
2077
|
setDescription,
|
|
1989
|
-
|
|
1990
|
-
|
|
2078
|
+
dataSourceID,
|
|
2079
|
+
setDataSourceID,
|
|
1991
2080
|
viz,
|
|
1992
2081
|
setViz,
|
|
1993
2082
|
refreshData
|
|
@@ -2041,7 +2130,7 @@ function DashboardLayout({
|
|
|
2041
2130
|
const newPanels = panels.map((p2) => __spreadProps(__spreadValues({}, p2), {
|
|
2042
2131
|
layout: m2.get(p2.id)
|
|
2043
2132
|
}));
|
|
2044
|
-
setPanels
|
|
2133
|
+
setPanels(newPanels);
|
|
2045
2134
|
}, [panels, setPanels]);
|
|
2046
2135
|
return /* @__PURE__ */ jsx(ResponsiveReactGridLayout$1, {
|
|
2047
2136
|
onBreakpointChange,
|
|
@@ -2064,7 +2153,10 @@ function DashboardLayout({
|
|
|
2064
2153
|
}, rest), {
|
|
2065
2154
|
destroy: () => onRemoveItem(id),
|
|
2066
2155
|
update: (panel) => {
|
|
2067
|
-
setPanels
|
|
2156
|
+
setPanels((prevs) => {
|
|
2157
|
+
prevs.splice(index2, 1, panel);
|
|
2158
|
+
return [...prevs];
|
|
2159
|
+
});
|
|
2068
2160
|
}
|
|
2069
2161
|
}))
|
|
2070
2162
|
}, id);
|
|
@@ -2101,147 +2193,763 @@ function ModeToggler({
|
|
|
2101
2193
|
}]
|
|
2102
2194
|
});
|
|
2103
2195
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2196
|
+
const example = `
|
|
2197
|
+
-- You may reference context data or SQL snippets *by name*
|
|
2198
|
+
-- in SQL or VizConfig.
|
|
2199
|
+
SELECT *
|
|
2200
|
+
FROM commit
|
|
2201
|
+
WHERE
|
|
2202
|
+
-- context data
|
|
2203
|
+
author_time BETWEEN '\${timeRange?.[0].toISOString()}' AND '\${timeRange?.[1].toISOString()}'
|
|
2204
|
+
-- SQL snippets
|
|
2205
|
+
AND \${author_email_condition}
|
|
2206
|
+
\${order_by_clause}
|
|
2207
|
+
`;
|
|
2208
|
+
function ContextAndSnippets({}) {
|
|
2209
|
+
const contextInfo = React.useContext(ContextInfoContext);
|
|
2210
|
+
const {
|
|
2211
|
+
sqlSnippets
|
|
2212
|
+
} = React.useContext(DefinitionContext);
|
|
2213
|
+
const snippets = React.useMemo(() => {
|
|
2214
|
+
const snippets2 = sqlSnippets.reduce((prev, curr) => {
|
|
2215
|
+
prev[curr.key] = curr.value;
|
|
2216
|
+
return prev;
|
|
2217
|
+
}, {});
|
|
2218
|
+
return JSON.stringify(snippets2, null, 2);
|
|
2219
|
+
}, [sqlSnippets]);
|
|
2220
|
+
const context = React.useMemo(() => {
|
|
2221
|
+
return JSON.stringify(contextInfo, null, 2);
|
|
2222
|
+
}, [contextInfo]);
|
|
2112
2223
|
return /* @__PURE__ */ jsxs(Group, {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2224
|
+
direction: "column",
|
|
2225
|
+
grow: true,
|
|
2226
|
+
sx: {
|
|
2227
|
+
border: "1px solid #eee",
|
|
2228
|
+
maxWidth: "48%",
|
|
2229
|
+
overflow: "hidden"
|
|
2230
|
+
},
|
|
2116
2231
|
children: [/* @__PURE__ */ jsx(Group, {
|
|
2117
2232
|
position: "left",
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2233
|
+
pl: "md",
|
|
2234
|
+
py: "md",
|
|
2235
|
+
sx: {
|
|
2236
|
+
borderBottom: "1px solid #eee",
|
|
2237
|
+
background: "#efefef",
|
|
2238
|
+
flexGrow: 0
|
|
2239
|
+
},
|
|
2240
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2241
|
+
weight: 500,
|
|
2242
|
+
children: "Context"
|
|
2121
2243
|
})
|
|
2122
|
-
}),
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2244
|
+
}), /* @__PURE__ */ jsxs(Group, {
|
|
2245
|
+
direction: "column",
|
|
2246
|
+
px: "md",
|
|
2247
|
+
pb: "md",
|
|
2248
|
+
sx: {
|
|
2249
|
+
width: "100%"
|
|
2250
|
+
},
|
|
2251
|
+
children: [/* @__PURE__ */ jsx(Prism, {
|
|
2252
|
+
language: "sql",
|
|
2253
|
+
sx: {
|
|
2254
|
+
width: "100%"
|
|
2255
|
+
},
|
|
2256
|
+
noCopy: true,
|
|
2257
|
+
colorScheme: "dark",
|
|
2258
|
+
children: example
|
|
2259
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
2260
|
+
weight: 500,
|
|
2261
|
+
sx: {
|
|
2262
|
+
flexGrow: 0
|
|
2263
|
+
},
|
|
2264
|
+
children: "Avaiable context"
|
|
2265
|
+
}), /* @__PURE__ */ jsx(Prism, {
|
|
2266
|
+
language: "json",
|
|
2267
|
+
sx: {
|
|
2268
|
+
width: "100%"
|
|
2269
|
+
},
|
|
2270
|
+
noCopy: true,
|
|
2271
|
+
colorScheme: "dark",
|
|
2272
|
+
children: context
|
|
2273
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
2274
|
+
weight: 500,
|
|
2275
|
+
sx: {
|
|
2276
|
+
flexGrow: 0
|
|
2277
|
+
},
|
|
2278
|
+
children: "Avaiable SQL Snippets"
|
|
2279
|
+
}), /* @__PURE__ */ jsx(Prism, {
|
|
2280
|
+
language: "json",
|
|
2281
|
+
sx: {
|
|
2282
|
+
width: "100%"
|
|
2283
|
+
},
|
|
2284
|
+
noCopy: true,
|
|
2285
|
+
colorScheme: "dark",
|
|
2286
|
+
children: snippets
|
|
2149
2287
|
})]
|
|
2150
|
-
}), !inEditMode && /* @__PURE__ */ jsx(Button, {
|
|
2151
|
-
variant: "default",
|
|
2152
|
-
size: "sm",
|
|
2153
|
-
disabled: true,
|
|
2154
|
-
leftIcon: /* @__PURE__ */ jsx(Share, {
|
|
2155
|
-
size: 20
|
|
2156
|
-
}),
|
|
2157
|
-
children: "Share"
|
|
2158
2288
|
})]
|
|
2159
2289
|
});
|
|
2160
2290
|
}
|
|
2161
|
-
function
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
className = "dashboard"
|
|
2291
|
+
function DataSourceForm({
|
|
2292
|
+
value,
|
|
2293
|
+
onChange
|
|
2165
2294
|
}) {
|
|
2166
|
-
const
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
const
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
const
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2295
|
+
const form = useForm$1({
|
|
2296
|
+
initialValues: value
|
|
2297
|
+
});
|
|
2298
|
+
const submit = React.useCallback((values) => {
|
|
2299
|
+
onChange(values);
|
|
2300
|
+
}, [onChange]);
|
|
2301
|
+
const changed = React.useMemo(() => {
|
|
2302
|
+
return !_.isEqual(value, form.values);
|
|
2303
|
+
}, [value, form.values]);
|
|
2304
|
+
React.useEffect(() => {
|
|
2305
|
+
form.reset();
|
|
2306
|
+
}, [value]);
|
|
2307
|
+
return /* @__PURE__ */ jsx(Group, {
|
|
2308
|
+
direction: "column",
|
|
2309
|
+
grow: true,
|
|
2310
|
+
sx: {
|
|
2311
|
+
border: "1px solid #eee",
|
|
2312
|
+
flexGrow: 1
|
|
2313
|
+
},
|
|
2314
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
2315
|
+
onSubmit: form.onSubmit(submit),
|
|
2316
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
2317
|
+
position: "left",
|
|
2318
|
+
py: "md",
|
|
2319
|
+
pl: "md",
|
|
2320
|
+
sx: {
|
|
2321
|
+
borderBottom: "1px solid #eee",
|
|
2322
|
+
background: "#efefef"
|
|
2323
|
+
},
|
|
2324
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
2325
|
+
weight: 500,
|
|
2326
|
+
children: "Data Source Configuration"
|
|
2327
|
+
}), /* @__PURE__ */ jsx(ActionIcon, {
|
|
2328
|
+
type: "submit",
|
|
2329
|
+
mr: 5,
|
|
2330
|
+
variant: "filled",
|
|
2331
|
+
color: "blue",
|
|
2332
|
+
disabled: !changed,
|
|
2333
|
+
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
2334
|
+
size: 20
|
|
2335
|
+
})
|
|
2336
|
+
})]
|
|
2337
|
+
}), /* @__PURE__ */ jsxs(Group, {
|
|
2338
|
+
direction: "column",
|
|
2339
|
+
grow: true,
|
|
2340
|
+
my: 0,
|
|
2341
|
+
p: "md",
|
|
2342
|
+
pr: 40,
|
|
2343
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
2344
|
+
grow: true,
|
|
2345
|
+
children: [/* @__PURE__ */ jsx(TextInput, __spreadValues({
|
|
2346
|
+
placeholder: "An ID unique in this dashboard",
|
|
2347
|
+
label: "ID",
|
|
2348
|
+
required: true,
|
|
2349
|
+
sx: {
|
|
2350
|
+
flex: 1
|
|
2351
|
+
}
|
|
2352
|
+
}, form.getInputProps("id"))), /* @__PURE__ */ jsx(TextInput, __spreadValues({
|
|
2353
|
+
placeholder: "TODO: use a dedicated UI component for this",
|
|
2354
|
+
label: "Data Source Key",
|
|
2355
|
+
required: true,
|
|
2356
|
+
sx: {
|
|
2357
|
+
flex: 1
|
|
2358
|
+
}
|
|
2359
|
+
}, form.getInputProps("key"))), /* @__PURE__ */ jsx(TextInput, __spreadValues({
|
|
2360
|
+
placeholder: "Type of the data source",
|
|
2361
|
+
label: "Type",
|
|
2362
|
+
disabled: true,
|
|
2363
|
+
sx: {
|
|
2364
|
+
flex: 1
|
|
2365
|
+
}
|
|
2366
|
+
}, form.getInputProps("type")))]
|
|
2367
|
+
}), /* @__PURE__ */ jsx(Textarea, __spreadValues({
|
|
2368
|
+
autosize: true,
|
|
2369
|
+
minRows: 12,
|
|
2370
|
+
maxRows: 24
|
|
2371
|
+
}, form.getInputProps("sql")))]
|
|
2372
|
+
})]
|
|
2373
|
+
})
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
function DataSourceEditor({
|
|
2377
|
+
id
|
|
2378
|
+
}) {
|
|
2379
|
+
const {
|
|
2380
|
+
dataSources,
|
|
2381
|
+
setDataSources
|
|
2382
|
+
} = React.useContext(DefinitionContext);
|
|
2383
|
+
const dataSource = React.useMemo(() => {
|
|
2384
|
+
return dataSources.find((d) => d.id === id);
|
|
2385
|
+
}, [dataSources, id]);
|
|
2386
|
+
const update = React.useCallback((value) => {
|
|
2387
|
+
const index2 = dataSources.findIndex((d) => d.id === value.id);
|
|
2388
|
+
if (!index2) {
|
|
2389
|
+
console.error(new Error("Invalid data source id when updating by id"));
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
setDataSources((prevs) => {
|
|
2393
|
+
const index22 = prevs.findIndex((p2) => p2.id === id);
|
|
2394
|
+
prevs.splice(index22, 1, value);
|
|
2395
|
+
return [...prevs];
|
|
2396
|
+
});
|
|
2397
|
+
}, [setDataSources]);
|
|
2398
|
+
if (!dataSource) {
|
|
2399
|
+
return /* @__PURE__ */ jsx("span", {
|
|
2400
|
+
children: "Invalid Data Source ID"
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
2404
|
+
direction: "row",
|
|
2405
|
+
position: "apart",
|
|
2406
|
+
grow: true,
|
|
2407
|
+
align: "stretch",
|
|
2408
|
+
noWrap: true,
|
|
2409
|
+
children: [/* @__PURE__ */ jsx(DataSourceForm, {
|
|
2410
|
+
value: dataSource,
|
|
2411
|
+
onChange: update
|
|
2412
|
+
}), /* @__PURE__ */ jsx(ContextAndSnippets, {})]
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
function SelectOrAddDataSource({
|
|
2416
|
+
id,
|
|
2417
|
+
setID
|
|
2418
|
+
}) {
|
|
2419
|
+
const {
|
|
2420
|
+
dataSources,
|
|
2421
|
+
setDataSources
|
|
2422
|
+
} = React.useContext(DefinitionContext);
|
|
2423
|
+
const chooseDefault = React.useCallback(() => {
|
|
2424
|
+
var _a, _b;
|
|
2425
|
+
setID((_b = (_a = dataSources[0]) == null ? void 0 : _a.id) != null ? _b : "");
|
|
2426
|
+
}, [setID, dataSources]);
|
|
2427
|
+
React.useEffect(() => {
|
|
2428
|
+
if (!id) {
|
|
2429
|
+
chooseDefault();
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
const index2 = dataSources.findIndex((d) => d.id === id);
|
|
2433
|
+
if (index2 === -1) {
|
|
2434
|
+
chooseDefault();
|
|
2435
|
+
}
|
|
2436
|
+
}, [id, dataSources, chooseDefault]);
|
|
2437
|
+
const options = React.useMemo(() => {
|
|
2438
|
+
return dataSources.map((d) => ({
|
|
2439
|
+
value: d.id,
|
|
2440
|
+
label: d.id
|
|
2441
|
+
}));
|
|
2442
|
+
}, [dataSources]);
|
|
2443
|
+
const add = React.useCallback(() => {
|
|
2444
|
+
const newDataSource = {
|
|
2445
|
+
id: randomId(),
|
|
2446
|
+
type: "postgresql",
|
|
2447
|
+
key: "",
|
|
2448
|
+
sql: ""
|
|
2449
|
+
};
|
|
2450
|
+
setDataSources((prevs) => [...prevs, newDataSource]);
|
|
2451
|
+
}, [setDataSources]);
|
|
2452
|
+
return /* @__PURE__ */ jsx(Group, {
|
|
2453
|
+
pb: "xl",
|
|
2454
|
+
children: /* @__PURE__ */ jsxs(Group, {
|
|
2455
|
+
position: "left",
|
|
2456
|
+
sx: {
|
|
2457
|
+
maxWidth: "600px",
|
|
2458
|
+
alignItems: "baseline"
|
|
2459
|
+
},
|
|
2460
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
2461
|
+
children: "Select a Data Source"
|
|
2462
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
2463
|
+
data: options,
|
|
2464
|
+
value: id,
|
|
2465
|
+
onChange: setID,
|
|
2466
|
+
allowDeselect: false,
|
|
2467
|
+
clearable: false,
|
|
2468
|
+
sx: {
|
|
2469
|
+
flexGrow: 1
|
|
2470
|
+
}
|
|
2471
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
2472
|
+
children: "or"
|
|
2473
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
2474
|
+
position: "center",
|
|
2475
|
+
mt: "md",
|
|
2476
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
2477
|
+
onClick: add,
|
|
2478
|
+
children: "Add a Data Source"
|
|
2479
|
+
})
|
|
2480
|
+
})]
|
|
2481
|
+
})
|
|
2482
|
+
});
|
|
2483
|
+
}
|
|
2484
|
+
function EditDataSourcesModal({
|
|
2485
|
+
opened,
|
|
2486
|
+
close
|
|
2487
|
+
}) {
|
|
2488
|
+
const [id, setID] = React.useState("");
|
|
2489
|
+
const {
|
|
2490
|
+
freezeLayout
|
|
2491
|
+
} = React.useContext(LayoutStateContext);
|
|
2492
|
+
React.useEffect(() => {
|
|
2493
|
+
freezeLayout(opened);
|
|
2494
|
+
}, [opened]);
|
|
2495
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
2496
|
+
size: "96vw",
|
|
2497
|
+
overflow: "inside",
|
|
2498
|
+
opened,
|
|
2499
|
+
onClose: close,
|
|
2500
|
+
title: "Data Sources",
|
|
2501
|
+
trapFocus: true,
|
|
2502
|
+
onDragStart: (e) => {
|
|
2503
|
+
e.stopPropagation();
|
|
2504
|
+
},
|
|
2505
|
+
children: /* @__PURE__ */ jsxs(AppShell, {
|
|
2506
|
+
sx: {
|
|
2507
|
+
height: "90vh",
|
|
2508
|
+
maxHeight: "calc(100vh - 185px)",
|
|
2509
|
+
".mantine-AppShell-body": {
|
|
2510
|
+
height: "100%"
|
|
2511
|
+
},
|
|
2512
|
+
main: {
|
|
2513
|
+
height: "100%",
|
|
2514
|
+
width: "100%",
|
|
2515
|
+
padding: 0,
|
|
2516
|
+
margin: 0
|
|
2517
|
+
}
|
|
2518
|
+
},
|
|
2519
|
+
padding: "md",
|
|
2520
|
+
header: /* @__PURE__ */ jsx(SelectOrAddDataSource, {
|
|
2521
|
+
id,
|
|
2522
|
+
setID
|
|
2523
|
+
}),
|
|
2524
|
+
children: [/* @__PURE__ */ jsx(DataSourceEditor, {
|
|
2525
|
+
id
|
|
2526
|
+
}), /* @__PURE__ */ jsx(DataPreview, {
|
|
2527
|
+
id
|
|
2528
|
+
})]
|
|
2529
|
+
})
|
|
2530
|
+
});
|
|
2531
|
+
}
|
|
2532
|
+
function ContextInfo({}) {
|
|
2533
|
+
const contextInfo = React.useContext(ContextInfoContext);
|
|
2534
|
+
const sampleSQL = `SELECT *
|
|
2535
|
+
FROM commit
|
|
2536
|
+
WHERE author_time BETWEEN '\${timeRange?.[0].toISOString()}' AND '\${timeRange?.[1].toISOString()}'`;
|
|
2537
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
2538
|
+
direction: "column",
|
|
2539
|
+
grow: true,
|
|
2540
|
+
sx: {
|
|
2541
|
+
border: "1px solid #eee",
|
|
2542
|
+
maxWidth: "48%",
|
|
2543
|
+
overflow: "hidden"
|
|
2544
|
+
},
|
|
2545
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
2546
|
+
position: "left",
|
|
2547
|
+
pl: "md",
|
|
2548
|
+
py: "md",
|
|
2549
|
+
sx: {
|
|
2550
|
+
borderBottom: "1px solid #eee",
|
|
2551
|
+
background: "#efefef",
|
|
2552
|
+
flexGrow: 0
|
|
2553
|
+
},
|
|
2554
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2555
|
+
weight: 500,
|
|
2556
|
+
children: "Context"
|
|
2557
|
+
})
|
|
2558
|
+
}), /* @__PURE__ */ jsxs(Group, {
|
|
2559
|
+
direction: "column",
|
|
2560
|
+
px: "md",
|
|
2561
|
+
pb: "md",
|
|
2562
|
+
sx: {
|
|
2563
|
+
width: "100%"
|
|
2564
|
+
},
|
|
2565
|
+
children: [/* @__PURE__ */ jsx(Prism, {
|
|
2566
|
+
language: "sql",
|
|
2567
|
+
sx: {
|
|
2568
|
+
width: "100%"
|
|
2569
|
+
},
|
|
2570
|
+
noCopy: true,
|
|
2571
|
+
colorScheme: "dark",
|
|
2572
|
+
children: `-- You may refer context data *by name*
|
|
2573
|
+
-- in SQL or VizConfig.
|
|
2574
|
+
|
|
2575
|
+
${sampleSQL}`
|
|
2576
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
2577
|
+
weight: 500,
|
|
2578
|
+
sx: {
|
|
2579
|
+
flexGrow: 0
|
|
2580
|
+
},
|
|
2581
|
+
children: "Avaiable context entries"
|
|
2582
|
+
}), /* @__PURE__ */ jsx(Prism, {
|
|
2583
|
+
language: "json",
|
|
2584
|
+
sx: {
|
|
2585
|
+
width: "100%"
|
|
2586
|
+
},
|
|
2587
|
+
noCopy: true,
|
|
2588
|
+
colorScheme: "dark",
|
|
2589
|
+
children: JSON.stringify(contextInfo, null, 2)
|
|
2590
|
+
})]
|
|
2591
|
+
})]
|
|
2592
|
+
});
|
|
2593
|
+
}
|
|
2594
|
+
function SQLSnippetsEditor({}) {
|
|
2595
|
+
const {
|
|
2596
|
+
sqlSnippets,
|
|
2597
|
+
setSQLSnippets
|
|
2598
|
+
} = React.useContext(DefinitionContext);
|
|
2599
|
+
const sampleSQL = `SELECT *
|
|
2600
|
+
FROM commit
|
|
2601
|
+
WHERE \${author_time_condition}`;
|
|
2602
|
+
const initialValues = React.useMemo(() => ({
|
|
2603
|
+
snippets: formList(sqlSnippets != null ? sqlSnippets : [])
|
|
2604
|
+
}), [sqlSnippets]);
|
|
2605
|
+
const form = useForm$1({
|
|
2606
|
+
initialValues
|
|
2607
|
+
});
|
|
2608
|
+
const addSnippet = () => form.addListItem("snippets", {
|
|
2609
|
+
key: randomId(),
|
|
2610
|
+
value: ""
|
|
2611
|
+
});
|
|
2612
|
+
const changed = React.useMemo(() => !_.isEqual(form.values, initialValues), [form.values, initialValues]);
|
|
2613
|
+
const submit = ({
|
|
2614
|
+
snippets
|
|
2615
|
+
}) => {
|
|
2616
|
+
setSQLSnippets(snippets);
|
|
2617
|
+
};
|
|
2618
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
2619
|
+
direction: "column",
|
|
2620
|
+
grow: true,
|
|
2621
|
+
sx: {
|
|
2622
|
+
border: "1px solid #eee"
|
|
2623
|
+
},
|
|
2624
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
2625
|
+
position: "left",
|
|
2626
|
+
pl: "md",
|
|
2627
|
+
py: "md",
|
|
2628
|
+
sx: {
|
|
2629
|
+
borderBottom: "1px solid #eee",
|
|
2630
|
+
background: "#efefef",
|
|
2631
|
+
flexGrow: 0
|
|
2632
|
+
},
|
|
2633
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
2634
|
+
weight: 500,
|
|
2635
|
+
children: "SQL Snippets"
|
|
2636
|
+
}), /* @__PURE__ */ jsx(ActionIcon, {
|
|
2637
|
+
type: "submit",
|
|
2638
|
+
mr: 5,
|
|
2639
|
+
variant: "filled",
|
|
2640
|
+
color: "blue",
|
|
2641
|
+
disabled: !changed,
|
|
2642
|
+
children: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
2643
|
+
size: 20
|
|
2644
|
+
})
|
|
2645
|
+
})]
|
|
2646
|
+
}), /* @__PURE__ */ jsxs(Group, {
|
|
2647
|
+
px: "md",
|
|
2648
|
+
pb: "md",
|
|
2649
|
+
children: [/* @__PURE__ */ jsx(Prism, {
|
|
2650
|
+
language: "sql",
|
|
2651
|
+
sx: {
|
|
2652
|
+
width: "100%"
|
|
2653
|
+
},
|
|
2654
|
+
noCopy: true,
|
|
2655
|
+
trim: false,
|
|
2656
|
+
colorScheme: "dark",
|
|
2657
|
+
children: `-- You may refer context data *by name*
|
|
2658
|
+
-- in SQL or VizConfig.
|
|
2659
|
+
|
|
2660
|
+
${sampleSQL}
|
|
2661
|
+
|
|
2662
|
+
-- where author_time_condition is:
|
|
2663
|
+
author_time BETWEEN '\${timeRange?.[0].toISOString()}' AND '\${timeRange?.[1].toISOString()}'
|
|
2664
|
+
`
|
|
2665
|
+
}), /* @__PURE__ */ jsx(Group, {
|
|
2666
|
+
direction: "column",
|
|
2667
|
+
sx: {
|
|
2668
|
+
width: "100%",
|
|
2669
|
+
position: "relative"
|
|
2670
|
+
},
|
|
2671
|
+
grow: true,
|
|
2672
|
+
children: /* @__PURE__ */ jsxs("form", {
|
|
2673
|
+
onSubmit: form.onSubmit(submit),
|
|
2674
|
+
children: [form.values.snippets.map((_item, index2) => /* @__PURE__ */ jsxs(Group, {
|
|
2675
|
+
direction: "column",
|
|
2676
|
+
grow: true,
|
|
2677
|
+
my: 0,
|
|
2678
|
+
p: "md",
|
|
2679
|
+
pr: 40,
|
|
2680
|
+
sx: {
|
|
2681
|
+
border: "1px solid #eee",
|
|
2682
|
+
position: "relative"
|
|
2683
|
+
},
|
|
2684
|
+
children: [/* @__PURE__ */ jsx(TextInput, __spreadValues({
|
|
2685
|
+
label: "Key",
|
|
2686
|
+
required: true
|
|
2687
|
+
}, form.getListInputProps("snippets", index2, "key"))), /* @__PURE__ */ jsx(Textarea, __spreadValues({
|
|
2688
|
+
minRows: 3,
|
|
2689
|
+
label: "Value",
|
|
2690
|
+
required: true
|
|
2691
|
+
}, form.getListInputProps("snippets", index2, "value"))), /* @__PURE__ */ jsx(ActionIcon, {
|
|
2692
|
+
color: "red",
|
|
2693
|
+
variant: "hover",
|
|
2694
|
+
onClick: () => form.removeListItem("snippets", index2),
|
|
2695
|
+
sx: {
|
|
2696
|
+
position: "absolute",
|
|
2697
|
+
top: 15,
|
|
2698
|
+
right: 5
|
|
2699
|
+
},
|
|
2700
|
+
children: /* @__PURE__ */ jsx(Trash, {
|
|
2701
|
+
size: 16
|
|
2702
|
+
})
|
|
2703
|
+
})]
|
|
2704
|
+
}, index2)), /* @__PURE__ */ jsx(Group, {
|
|
2705
|
+
position: "center",
|
|
2706
|
+
mt: "xl",
|
|
2707
|
+
grow: true,
|
|
2708
|
+
sx: {
|
|
2709
|
+
width: "40%"
|
|
2710
|
+
},
|
|
2711
|
+
mx: "auto",
|
|
2712
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
2713
|
+
variant: "default",
|
|
2714
|
+
onClick: addSnippet,
|
|
2715
|
+
children: "Add a snippet"
|
|
2716
|
+
})
|
|
2717
|
+
})]
|
|
2718
|
+
})
|
|
2719
|
+
})]
|
|
2720
|
+
})]
|
|
2721
|
+
});
|
|
2722
|
+
}
|
|
2723
|
+
function EditSQLSnippetsModal({
|
|
2724
|
+
opened,
|
|
2725
|
+
close
|
|
2726
|
+
}) {
|
|
2727
|
+
const {
|
|
2728
|
+
freezeLayout
|
|
2729
|
+
} = React.useContext(LayoutStateContext);
|
|
2730
|
+
React.useEffect(() => {
|
|
2731
|
+
freezeLayout(opened);
|
|
2732
|
+
}, [opened]);
|
|
2733
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
2734
|
+
size: "96vw",
|
|
2735
|
+
overflow: "inside",
|
|
2736
|
+
opened,
|
|
2737
|
+
onClose: close,
|
|
2738
|
+
title: "SQL Snippets",
|
|
2739
|
+
trapFocus: true,
|
|
2740
|
+
onDragStart: (e) => {
|
|
2741
|
+
e.stopPropagation();
|
|
2742
|
+
},
|
|
2743
|
+
children: /* @__PURE__ */ jsx(AppShell, {
|
|
2744
|
+
sx: {
|
|
2745
|
+
height: "90vh",
|
|
2746
|
+
maxHeight: "calc(100vh - 185px)",
|
|
2747
|
+
".mantine-AppShell-body": {
|
|
2748
|
+
height: "100%"
|
|
2749
|
+
},
|
|
2750
|
+
main: {
|
|
2751
|
+
height: "100%",
|
|
2752
|
+
width: "100%",
|
|
2753
|
+
padding: 0,
|
|
2754
|
+
margin: 0
|
|
2755
|
+
}
|
|
2756
|
+
},
|
|
2757
|
+
padding: "md",
|
|
2758
|
+
children: /* @__PURE__ */ jsxs(Group, {
|
|
2759
|
+
direction: "row",
|
|
2760
|
+
position: "apart",
|
|
2761
|
+
grow: true,
|
|
2762
|
+
align: "stretch",
|
|
2763
|
+
noWrap: true,
|
|
2764
|
+
children: [/* @__PURE__ */ jsx(SQLSnippetsEditor, {}), /* @__PURE__ */ jsx(ContextInfo, {})]
|
|
2765
|
+
})
|
|
2766
|
+
})
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
function DashboardActions({
|
|
2770
|
+
mode,
|
|
2771
|
+
setMode,
|
|
2772
|
+
hasChanges,
|
|
2773
|
+
addPanel,
|
|
2774
|
+
saveChanges
|
|
2775
|
+
}) {
|
|
2776
|
+
const [dataSourcesOpened, setDataSourcesOpened] = React.useState(false);
|
|
2777
|
+
const openDataSources = () => setDataSourcesOpened(true);
|
|
2778
|
+
const closeDataSources = () => setDataSourcesOpened(false);
|
|
2779
|
+
const [sqlSnippetsOpened, setSQLSnippetsOpened] = React.useState(false);
|
|
2780
|
+
const openSQLSnippets = () => setSQLSnippetsOpened(true);
|
|
2781
|
+
const closeSQLSnippets = () => setSQLSnippetsOpened(false);
|
|
2782
|
+
const inEditMode = mode === DashboardMode.Edit;
|
|
2783
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
2784
|
+
position: "apart",
|
|
2785
|
+
pt: "sm",
|
|
2786
|
+
pb: "xs",
|
|
2787
|
+
children: [/* @__PURE__ */ jsx(Group, {
|
|
2788
|
+
position: "left",
|
|
2789
|
+
children: /* @__PURE__ */ jsx(ModeToggler, {
|
|
2790
|
+
mode,
|
|
2791
|
+
setMode
|
|
2792
|
+
})
|
|
2793
|
+
}), inEditMode && /* @__PURE__ */ jsxs(Fragment, {
|
|
2794
|
+
children: [/* @__PURE__ */ jsxs(Group, {
|
|
2795
|
+
position: "right",
|
|
2796
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
2797
|
+
variant: "default",
|
|
2798
|
+
size: "sm",
|
|
2799
|
+
onClick: addPanel,
|
|
2800
|
+
leftIcon: /* @__PURE__ */ jsx(PlaylistAdd, {
|
|
2801
|
+
size: 20
|
|
2802
|
+
}),
|
|
2803
|
+
children: "Add a Panel"
|
|
2804
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2805
|
+
variant: "default",
|
|
2806
|
+
size: "sm",
|
|
2807
|
+
onClick: openSQLSnippets,
|
|
2808
|
+
leftIcon: /* @__PURE__ */ jsx(ClipboardText, {
|
|
2809
|
+
size: 20
|
|
2810
|
+
}),
|
|
2811
|
+
children: "SQL Snippets"
|
|
2812
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2813
|
+
variant: "default",
|
|
2814
|
+
size: "sm",
|
|
2815
|
+
onClick: openDataSources,
|
|
2816
|
+
leftIcon: /* @__PURE__ */ jsx(Database, {
|
|
2817
|
+
size: 20
|
|
2818
|
+
}),
|
|
2819
|
+
children: "Data Sources"
|
|
2820
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2821
|
+
variant: "default",
|
|
2822
|
+
size: "sm",
|
|
2823
|
+
onClick: saveChanges,
|
|
2824
|
+
disabled: !hasChanges,
|
|
2825
|
+
leftIcon: /* @__PURE__ */ jsx(DeviceFloppy, {
|
|
2826
|
+
size: 20
|
|
2827
|
+
}),
|
|
2828
|
+
children: "Save Changes"
|
|
2829
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
2830
|
+
color: "red",
|
|
2831
|
+
size: "sm",
|
|
2832
|
+
disabled: !hasChanges,
|
|
2833
|
+
leftIcon: /* @__PURE__ */ jsx(Recycle, {
|
|
2834
|
+
size: 20
|
|
2835
|
+
}),
|
|
2836
|
+
children: "Revert Changes"
|
|
2837
|
+
})]
|
|
2838
|
+
}), /* @__PURE__ */ jsx(EditDataSourcesModal, {
|
|
2839
|
+
opened: dataSourcesOpened,
|
|
2840
|
+
close: closeDataSources
|
|
2841
|
+
}), /* @__PURE__ */ jsx(EditSQLSnippetsModal, {
|
|
2842
|
+
opened: sqlSnippetsOpened,
|
|
2843
|
+
close: closeSQLSnippets
|
|
2844
|
+
})]
|
|
2845
|
+
}), !inEditMode && /* @__PURE__ */ jsx(Button, {
|
|
2846
|
+
variant: "default",
|
|
2847
|
+
size: "sm",
|
|
2848
|
+
disabled: true,
|
|
2849
|
+
leftIcon: /* @__PURE__ */ jsx(Share, {
|
|
2850
|
+
size: 20
|
|
2851
|
+
}),
|
|
2852
|
+
children: "Share"
|
|
2853
|
+
})]
|
|
2854
|
+
});
|
|
2855
|
+
}
|
|
2856
|
+
function Dashboard({
|
|
2857
|
+
context,
|
|
2858
|
+
dashboard,
|
|
2859
|
+
update,
|
|
2860
|
+
className = "dashboard"
|
|
2861
|
+
}) {
|
|
2862
|
+
const [layoutFrozen, freezeLayout] = React.useState(false);
|
|
2863
|
+
const [breakpoint, setBreakpoint] = React.useState();
|
|
2864
|
+
const [localCols, setLocalCols] = React.useState();
|
|
2865
|
+
const [panels, setPanels] = React.useState(dashboard.panels);
|
|
2866
|
+
const [sqlSnippets, setSQLSnippets] = React.useState(dashboard.definition.sqlSnippets);
|
|
2867
|
+
const [dataSources, setDataSources] = React.useState(dashboard.definition.dataSources);
|
|
2868
|
+
const [mode, setMode] = React.useState(DashboardMode.Edit);
|
|
2869
|
+
const hasChanges = React.useMemo(() => {
|
|
2870
|
+
const cleanJSON = (v) => JSON.parse(JSON.stringify(v));
|
|
2871
|
+
const panelsEqual = _.isEqual(cleanJSON(panels), cleanJSON(dashboard.panels));
|
|
2872
|
+
if (!panelsEqual) {
|
|
2873
|
+
return true;
|
|
2874
|
+
}
|
|
2875
|
+
if (!_.isEqual(sqlSnippets, dashboard.definition.sqlSnippets)) {
|
|
2876
|
+
return true;
|
|
2877
|
+
}
|
|
2878
|
+
return !_.isEqual(dataSources, dashboard.definition.dataSources);
|
|
2879
|
+
}, [dashboard, panels, sqlSnippets, dataSources]);
|
|
2880
|
+
const saveDashboardChanges = async () => {
|
|
2881
|
+
const d = _.merge({}, dashboard, {
|
|
2882
|
+
panels
|
|
2883
|
+
}, {
|
|
2884
|
+
definition: {
|
|
2885
|
+
sqlSnippets
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2888
|
+
await update(d);
|
|
2889
|
+
};
|
|
2890
|
+
const addPanel = () => {
|
|
2891
|
+
const id = randomId();
|
|
2892
|
+
const newItem = {
|
|
2893
|
+
id,
|
|
2894
|
+
layout: {
|
|
2895
|
+
x: 0,
|
|
2896
|
+
y: Infinity,
|
|
2897
|
+
w: 3,
|
|
2198
2898
|
h: 4
|
|
2199
2899
|
},
|
|
2200
2900
|
title: `New Panel - ${id}`,
|
|
2201
2901
|
description: "description goes here",
|
|
2202
|
-
|
|
2902
|
+
dataSourceID: "",
|
|
2203
2903
|
viz: {
|
|
2204
2904
|
type: "table",
|
|
2205
2905
|
conf: {}
|
|
2206
2906
|
}
|
|
2207
2907
|
};
|
|
2208
|
-
setPanels
|
|
2908
|
+
setPanels((prevs) => [...prevs, newItem]);
|
|
2209
2909
|
};
|
|
2210
2910
|
const removePanelByID = (id) => {
|
|
2211
2911
|
const index2 = panels.findIndex((p2) => p2.id === id);
|
|
2212
|
-
setPanels
|
|
2912
|
+
setPanels((prevs) => {
|
|
2913
|
+
prevs.splice(index2, 1);
|
|
2914
|
+
return [...prevs];
|
|
2915
|
+
});
|
|
2213
2916
|
};
|
|
2214
2917
|
const inEditMode = mode === DashboardMode.Edit;
|
|
2215
2918
|
const definitions = React.useMemo(() => ({
|
|
2216
2919
|
sqlSnippets,
|
|
2217
|
-
setSQLSnippets
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2920
|
+
setSQLSnippets,
|
|
2921
|
+
dataSources,
|
|
2922
|
+
setDataSources
|
|
2923
|
+
}), [sqlSnippets, setSQLSnippets, dataSources, setDataSources]);
|
|
2924
|
+
return /* @__PURE__ */ jsx(ContextInfoContext.Provider, {
|
|
2925
|
+
value: context,
|
|
2926
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2927
|
+
className,
|
|
2928
|
+
children: /* @__PURE__ */ jsx(DefinitionContext.Provider, {
|
|
2929
|
+
value: definitions,
|
|
2930
|
+
children: /* @__PURE__ */ jsxs(LayoutStateContext.Provider, {
|
|
2931
|
+
value: {
|
|
2932
|
+
layoutFrozen,
|
|
2933
|
+
freezeLayout,
|
|
2934
|
+
mode,
|
|
2935
|
+
inEditMode
|
|
2936
|
+
},
|
|
2937
|
+
children: [/* @__PURE__ */ jsx(DashboardActions, {
|
|
2938
|
+
mode,
|
|
2939
|
+
setMode,
|
|
2940
|
+
hasChanges,
|
|
2941
|
+
addPanel,
|
|
2942
|
+
saveChanges: saveDashboardChanges
|
|
2943
|
+
}), /* @__PURE__ */ jsx(DashboardLayout, {
|
|
2944
|
+
panels,
|
|
2945
|
+
setPanels,
|
|
2946
|
+
isDraggable: inEditMode && !layoutFrozen,
|
|
2947
|
+
isResizable: inEditMode && !layoutFrozen,
|
|
2948
|
+
onRemoveItem: removePanelByID,
|
|
2949
|
+
setLocalCols,
|
|
2950
|
+
setBreakpoint
|
|
2951
|
+
})]
|
|
2952
|
+
})
|
|
2245
2953
|
})
|
|
2246
2954
|
})
|
|
2247
2955
|
});
|
|
@@ -2281,29 +2989,33 @@ function ReadOnlyDashboardLayout({
|
|
|
2281
2989
|
});
|
|
2282
2990
|
}
|
|
2283
2991
|
function ReadOnlyDashboard({
|
|
2992
|
+
context,
|
|
2284
2993
|
dashboard,
|
|
2285
2994
|
className = "dashboard"
|
|
2286
2995
|
}) {
|
|
2287
|
-
const
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
}), [
|
|
2293
|
-
return /* @__PURE__ */ jsx(
|
|
2294
|
-
|
|
2295
|
-
children: /* @__PURE__ */ jsx(
|
|
2296
|
-
|
|
2297
|
-
children: /* @__PURE__ */ jsx(
|
|
2298
|
-
value:
|
|
2299
|
-
|
|
2300
|
-
|
|
2996
|
+
const definition = React.useMemo(() => __spreadProps(__spreadValues({}, dashboard.definition), {
|
|
2997
|
+
setSQLSnippets: () => {
|
|
2998
|
+
},
|
|
2999
|
+
setDataSources: () => {
|
|
3000
|
+
}
|
|
3001
|
+
}), [dashboard]);
|
|
3002
|
+
return /* @__PURE__ */ jsx(ContextInfoContext.Provider, {
|
|
3003
|
+
value: context,
|
|
3004
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3005
|
+
className,
|
|
3006
|
+
children: /* @__PURE__ */ jsx(DefinitionContext.Provider, {
|
|
3007
|
+
value: definition,
|
|
3008
|
+
children: /* @__PURE__ */ jsx(LayoutStateContext.Provider, {
|
|
3009
|
+
value: {
|
|
3010
|
+
layoutFrozen: true,
|
|
3011
|
+
freezeLayout: () => {
|
|
3012
|
+
},
|
|
3013
|
+
mode: DashboardMode.Use,
|
|
3014
|
+
inEditMode: false
|
|
2301
3015
|
},
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
children: /* @__PURE__ */ jsx(ReadOnlyDashboardLayout, {
|
|
2306
|
-
panels
|
|
3016
|
+
children: /* @__PURE__ */ jsx(ReadOnlyDashboardLayout, {
|
|
3017
|
+
panels: dashboard.panels
|
|
3018
|
+
})
|
|
2307
3019
|
})
|
|
2308
3020
|
})
|
|
2309
3021
|
})
|