@lobb-js/lobb-ext-reports 0.7.1 → 0.8.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/lib/components/gridStack.svelte +23 -16
- package/dist/lib/components/pages/reports/components/chart.svelte +14 -2
- package/dist/lib/components/pages/reports/components/report.svelte +32 -50
- package/extensions/reports/studio/lib/components/gridStack.svelte +23 -16
- package/extensions/reports/studio/lib/components/pages/reports/components/chart.svelte +14 -2
- package/extensions/reports/studio/lib/components/pages/reports/components/report.svelte +32 -50
- package/package.json +3 -3
|
@@ -8,24 +8,31 @@
|
|
|
8
8
|
interface Props {
|
|
9
9
|
column?: number;
|
|
10
10
|
cellHeight?: string;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
editable?: boolean;
|
|
12
|
+
onLayoutChange?: (layout: LayoutItem[]) => void;
|
|
13
13
|
children: Snippet;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
let {
|
|
17
17
|
column = 12,
|
|
18
18
|
cellHeight = "150px",
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
editable = $bindable(false),
|
|
20
|
+
onLayoutChange,
|
|
21
21
|
children,
|
|
22
22
|
}: Props = $props();
|
|
23
23
|
|
|
24
24
|
let gridEl: HTMLElement | undefined = $state();
|
|
25
25
|
let grid: GridStack | null = null;
|
|
26
|
-
let initialized = false;
|
|
26
|
+
let initialized = $state(false);
|
|
27
27
|
let resizeObserver: ResizeObserver | null = null;
|
|
28
28
|
let lastWidth = 0;
|
|
29
|
+
let containerWidth = $state(0);
|
|
30
|
+
let saveTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
31
|
+
|
|
32
|
+
let editMode = $derived(containerWidth >= 1200);
|
|
33
|
+
|
|
34
|
+
// Keep editable in sync so parent can read it
|
|
35
|
+
$effect(() => { editable = editMode; });
|
|
29
36
|
|
|
30
37
|
function getResponsiveColumns(width: number): number {
|
|
31
38
|
if (width >= 1200) return 12;
|
|
@@ -51,8 +58,9 @@
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
$effect(() => {
|
|
54
|
-
const mode = editMode;
|
|
55
|
-
|
|
61
|
+
const mode = editMode; // force-read so always tracked
|
|
62
|
+
const ready = initialized; // force-read so always tracked
|
|
63
|
+
if (!grid || !ready) return;
|
|
56
64
|
if (mode) {
|
|
57
65
|
grid.column(12);
|
|
58
66
|
grid.enable();
|
|
@@ -66,30 +74,28 @@
|
|
|
66
74
|
if (!gridEl) return;
|
|
67
75
|
|
|
68
76
|
grid = GridStack.init(
|
|
69
|
-
{
|
|
70
|
-
column,
|
|
71
|
-
cellHeight,
|
|
72
|
-
margin: "0.5rem",
|
|
73
|
-
float: false,
|
|
74
|
-
animate: true,
|
|
75
|
-
},
|
|
77
|
+
{ column, cellHeight, margin: "0.5rem", float: false, animate: true },
|
|
76
78
|
gridEl,
|
|
77
79
|
);
|
|
78
80
|
|
|
79
81
|
lastWidth = gridEl.offsetWidth;
|
|
82
|
+
containerWidth = lastWidth;
|
|
80
83
|
grid.column(getResponsiveColumns(lastWidth));
|
|
81
84
|
grid.disable();
|
|
82
85
|
|
|
83
86
|
setTimeout(() => { initialized = true; }, 0);
|
|
84
87
|
|
|
85
|
-
grid.on("
|
|
88
|
+
grid.on("dragstop resizestop", () => {
|
|
86
89
|
grid?.compact();
|
|
87
|
-
|
|
90
|
+
const layout = collectLayout();
|
|
91
|
+
if (saveTimeout) clearTimeout(saveTimeout);
|
|
92
|
+
saveTimeout = setTimeout(() => onLayoutChange?.(layout), 800);
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
resizeObserver = new ResizeObserver((entries) => {
|
|
91
96
|
window.dispatchEvent(new Event("resize"));
|
|
92
97
|
lastWidth = entries[0]?.contentRect.width ?? gridEl!.offsetWidth;
|
|
98
|
+
containerWidth = lastWidth;
|
|
93
99
|
if (!editMode) {
|
|
94
100
|
grid?.column(getResponsiveColumns(lastWidth));
|
|
95
101
|
}
|
|
@@ -98,6 +104,7 @@
|
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
onDestroy(() => {
|
|
107
|
+
if (saveTimeout) clearTimeout(saveTimeout);
|
|
101
108
|
resizeObserver?.disconnect();
|
|
102
109
|
resizeObserver = null;
|
|
103
110
|
grid?.destroy(false);
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
}: Props = $props();
|
|
28
28
|
|
|
29
29
|
const utils = props.utils;
|
|
30
|
-
const { UpdateDetailViewButton, Button } = utils.components;
|
|
30
|
+
const { UpdateDetailViewButton, Button, Tooltip } = utils.components;
|
|
31
31
|
const icons = utils.components.Icons;
|
|
32
32
|
|
|
33
33
|
function findCustomChartComponent(type: string): any {
|
|
@@ -75,7 +75,19 @@
|
|
|
75
75
|
|
|
76
76
|
<div class="gridContainer h-full rounded-md border bg-background">
|
|
77
77
|
<div class="flex items-center justify-between border-b p-2 text-sm">
|
|
78
|
-
<div
|
|
78
|
+
<div class="flex items-center gap-1.5">
|
|
79
|
+
<span>{chartRecord.title}</span>
|
|
80
|
+
{#if chartRecord.description}
|
|
81
|
+
<Tooltip.Root>
|
|
82
|
+
<Tooltip.Trigger>
|
|
83
|
+
<icons.CircleHelp class="text-muted-foreground" size={14} />
|
|
84
|
+
</Tooltip.Trigger>
|
|
85
|
+
<Tooltip.Content class="max-w-64 text-xs">
|
|
86
|
+
{chartRecord.description}
|
|
87
|
+
</Tooltip.Content>
|
|
88
|
+
</Tooltip.Root>
|
|
89
|
+
{/if}
|
|
90
|
+
</div>
|
|
79
91
|
<div class="flex">
|
|
80
92
|
<UpdateDetailViewButton
|
|
81
93
|
collectionName="reports_charts"
|
|
@@ -7,16 +7,14 @@
|
|
|
7
7
|
const {
|
|
8
8
|
SidebarTrigger,
|
|
9
9
|
CreateDetailViewButton,
|
|
10
|
-
Button,
|
|
11
10
|
Icons,
|
|
12
11
|
} = utils.components;
|
|
13
12
|
|
|
14
13
|
let report: any = $state(null);
|
|
15
14
|
let charts: any[] = $state([]);
|
|
16
15
|
let loading = $state(true);
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
let currentLayout = $state<{ id: string; order: number; w: number; h: number }[]>([]);
|
|
16
|
+
let saving = $state(false);
|
|
17
|
+
let editable = $state(false);
|
|
20
18
|
|
|
21
19
|
async function loadCharts({ showLoading = true } = {}) {
|
|
22
20
|
if (showLoading) loading = true;
|
|
@@ -33,7 +31,8 @@
|
|
|
33
31
|
if (showLoading) loading = false;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
async function
|
|
34
|
+
async function handleLayoutChange(changes: { id: string; order: number; w: number; h: number }[]) {
|
|
35
|
+
saving = true;
|
|
37
36
|
for (const change of changes) {
|
|
38
37
|
await utils.lobb.updateOne("reports_charts", change.id, {
|
|
39
38
|
sort_order: change.order,
|
|
@@ -41,6 +40,7 @@
|
|
|
41
40
|
row_span: change.h,
|
|
42
41
|
});
|
|
43
42
|
}
|
|
43
|
+
saving = false;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function getChartGridSize(chart: any): Record<string, unknown> {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
onMount(() => loadCharts());
|
|
62
62
|
</script>
|
|
63
63
|
|
|
64
|
-
<div class="report-layout"
|
|
64
|
+
<div class="report-layout">
|
|
65
65
|
{#if loading}
|
|
66
66
|
<div class="flex h-full w-full flex-col items-center justify-center gap-4" style="grid-row: 1 / -1">
|
|
67
67
|
<Icons.LoaderCircle class="animate-spin opacity-50" size="50" />
|
|
@@ -79,51 +79,33 @@
|
|
|
79
79
|
<div class="text-xs text-muted-foreground">{report.description}</div>
|
|
80
80
|
</div>
|
|
81
81
|
</div>
|
|
82
|
-
<div class="flex gap-2 self-end">
|
|
83
|
-
{#if
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
</Button>
|
|
94
|
-
<Button
|
|
95
|
-
variant="default"
|
|
96
|
-
class="h-7 px-3 text-xs font-normal"
|
|
97
|
-
Icon={Icons.Check}
|
|
98
|
-
onclick={async () => {
|
|
99
|
-
await saveChartsLayout(currentLayout);
|
|
100
|
-
editMode = false;
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
103
|
-
Save layout
|
|
104
|
-
</Button>
|
|
82
|
+
<div class="flex items-center gap-2 self-end">
|
|
83
|
+
{#if saving}
|
|
84
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
85
|
+
<Icons.LoaderCircle class="animate-spin" size={12} />
|
|
86
|
+
Saving...
|
|
87
|
+
</div>
|
|
88
|
+
{:else if editable}
|
|
89
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
90
|
+
<div class="h-1.5 w-1.5 rounded-full bg-green-500"></div>
|
|
91
|
+
Layout editable
|
|
92
|
+
</div>
|
|
105
93
|
{:else}
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Icon={Icons.LayoutDashboard}
|
|
111
|
-
onclick={() => (editMode = true)}
|
|
112
|
-
>
|
|
113
|
-
Edit layout
|
|
114
|
-
</Button>
|
|
115
|
-
{/if}
|
|
116
|
-
<CreateDetailViewButton
|
|
117
|
-
collectionName="reports_charts"
|
|
118
|
-
values={{ report_id: { id: reportId, name: report.name } }}
|
|
119
|
-
variant="default"
|
|
120
|
-
class="h-7 px-3 text-xs font-normal"
|
|
121
|
-
Icon={Icons.Plus}
|
|
122
|
-
onSuccessfullSave={async () => await loadCharts()}
|
|
123
|
-
>
|
|
124
|
-
Create chart
|
|
125
|
-
</CreateDetailViewButton>
|
|
94
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
95
|
+
<div class="h-1.5 w-1.5 rounded-full bg-muted-foreground/40"></div>
|
|
96
|
+
Expand window to rearrange
|
|
97
|
+
</div>
|
|
126
98
|
{/if}
|
|
99
|
+
<CreateDetailViewButton
|
|
100
|
+
collectionName="reports_charts"
|
|
101
|
+
values={{ report_id: { id: reportId, name: report.name } }}
|
|
102
|
+
variant="default"
|
|
103
|
+
class="h-7 px-3 text-xs font-normal"
|
|
104
|
+
Icon={Icons.Plus}
|
|
105
|
+
onSuccessfullSave={async () => await loadCharts()}
|
|
106
|
+
>
|
|
107
|
+
Create chart
|
|
108
|
+
</CreateDetailViewButton>
|
|
127
109
|
</div>
|
|
128
110
|
</div>
|
|
129
111
|
|
|
@@ -138,7 +120,7 @@
|
|
|
138
120
|
</div>
|
|
139
121
|
{:else}
|
|
140
122
|
{#key charts}
|
|
141
|
-
<GridStackComponent bind:
|
|
123
|
+
<GridStackComponent bind:editable onLayoutChange={handleLayoutChange}>
|
|
142
124
|
{#each [...charts].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) as chart (chart.id)}
|
|
143
125
|
<div
|
|
144
126
|
class="grid-stack-item"
|
|
@@ -8,24 +8,31 @@
|
|
|
8
8
|
interface Props {
|
|
9
9
|
column?: number;
|
|
10
10
|
cellHeight?: string;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
editable?: boolean;
|
|
12
|
+
onLayoutChange?: (layout: LayoutItem[]) => void;
|
|
13
13
|
children: Snippet;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
let {
|
|
17
17
|
column = 12,
|
|
18
18
|
cellHeight = "150px",
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
editable = $bindable(false),
|
|
20
|
+
onLayoutChange,
|
|
21
21
|
children,
|
|
22
22
|
}: Props = $props();
|
|
23
23
|
|
|
24
24
|
let gridEl: HTMLElement | undefined = $state();
|
|
25
25
|
let grid: GridStack | null = null;
|
|
26
|
-
let initialized = false;
|
|
26
|
+
let initialized = $state(false);
|
|
27
27
|
let resizeObserver: ResizeObserver | null = null;
|
|
28
28
|
let lastWidth = 0;
|
|
29
|
+
let containerWidth = $state(0);
|
|
30
|
+
let saveTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
31
|
+
|
|
32
|
+
let editMode = $derived(containerWidth >= 1200);
|
|
33
|
+
|
|
34
|
+
// Keep editable in sync so parent can read it
|
|
35
|
+
$effect(() => { editable = editMode; });
|
|
29
36
|
|
|
30
37
|
function getResponsiveColumns(width: number): number {
|
|
31
38
|
if (width >= 1200) return 12;
|
|
@@ -51,8 +58,9 @@
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
$effect(() => {
|
|
54
|
-
const mode = editMode;
|
|
55
|
-
|
|
61
|
+
const mode = editMode; // force-read so always tracked
|
|
62
|
+
const ready = initialized; // force-read so always tracked
|
|
63
|
+
if (!grid || !ready) return;
|
|
56
64
|
if (mode) {
|
|
57
65
|
grid.column(12);
|
|
58
66
|
grid.enable();
|
|
@@ -66,30 +74,28 @@
|
|
|
66
74
|
if (!gridEl) return;
|
|
67
75
|
|
|
68
76
|
grid = GridStack.init(
|
|
69
|
-
{
|
|
70
|
-
column,
|
|
71
|
-
cellHeight,
|
|
72
|
-
margin: "0.5rem",
|
|
73
|
-
float: false,
|
|
74
|
-
animate: true,
|
|
75
|
-
},
|
|
77
|
+
{ column, cellHeight, margin: "0.5rem", float: false, animate: true },
|
|
76
78
|
gridEl,
|
|
77
79
|
);
|
|
78
80
|
|
|
79
81
|
lastWidth = gridEl.offsetWidth;
|
|
82
|
+
containerWidth = lastWidth;
|
|
80
83
|
grid.column(getResponsiveColumns(lastWidth));
|
|
81
84
|
grid.disable();
|
|
82
85
|
|
|
83
86
|
setTimeout(() => { initialized = true; }, 0);
|
|
84
87
|
|
|
85
|
-
grid.on("
|
|
88
|
+
grid.on("dragstop resizestop", () => {
|
|
86
89
|
grid?.compact();
|
|
87
|
-
|
|
90
|
+
const layout = collectLayout();
|
|
91
|
+
if (saveTimeout) clearTimeout(saveTimeout);
|
|
92
|
+
saveTimeout = setTimeout(() => onLayoutChange?.(layout), 800);
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
resizeObserver = new ResizeObserver((entries) => {
|
|
91
96
|
window.dispatchEvent(new Event("resize"));
|
|
92
97
|
lastWidth = entries[0]?.contentRect.width ?? gridEl!.offsetWidth;
|
|
98
|
+
containerWidth = lastWidth;
|
|
93
99
|
if (!editMode) {
|
|
94
100
|
grid?.column(getResponsiveColumns(lastWidth));
|
|
95
101
|
}
|
|
@@ -98,6 +104,7 @@
|
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
onDestroy(() => {
|
|
107
|
+
if (saveTimeout) clearTimeout(saveTimeout);
|
|
101
108
|
resizeObserver?.disconnect();
|
|
102
109
|
resizeObserver = null;
|
|
103
110
|
grid?.destroy(false);
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
}: Props = $props();
|
|
28
28
|
|
|
29
29
|
const utils = props.utils;
|
|
30
|
-
const { UpdateDetailViewButton, Button } = utils.components;
|
|
30
|
+
const { UpdateDetailViewButton, Button, Tooltip } = utils.components;
|
|
31
31
|
const icons = utils.components.Icons;
|
|
32
32
|
|
|
33
33
|
function findCustomChartComponent(type: string): any {
|
|
@@ -75,7 +75,19 @@
|
|
|
75
75
|
|
|
76
76
|
<div class="gridContainer h-full rounded-md border bg-background">
|
|
77
77
|
<div class="flex items-center justify-between border-b p-2 text-sm">
|
|
78
|
-
<div
|
|
78
|
+
<div class="flex items-center gap-1.5">
|
|
79
|
+
<span>{chartRecord.title}</span>
|
|
80
|
+
{#if chartRecord.description}
|
|
81
|
+
<Tooltip.Root>
|
|
82
|
+
<Tooltip.Trigger>
|
|
83
|
+
<icons.CircleHelp class="text-muted-foreground" size={14} />
|
|
84
|
+
</Tooltip.Trigger>
|
|
85
|
+
<Tooltip.Content class="max-w-64 text-xs">
|
|
86
|
+
{chartRecord.description}
|
|
87
|
+
</Tooltip.Content>
|
|
88
|
+
</Tooltip.Root>
|
|
89
|
+
{/if}
|
|
90
|
+
</div>
|
|
79
91
|
<div class="flex">
|
|
80
92
|
<UpdateDetailViewButton
|
|
81
93
|
collectionName="reports_charts"
|
|
@@ -7,16 +7,14 @@
|
|
|
7
7
|
const {
|
|
8
8
|
SidebarTrigger,
|
|
9
9
|
CreateDetailViewButton,
|
|
10
|
-
Button,
|
|
11
10
|
Icons,
|
|
12
11
|
} = utils.components;
|
|
13
12
|
|
|
14
13
|
let report: any = $state(null);
|
|
15
14
|
let charts: any[] = $state([]);
|
|
16
15
|
let loading = $state(true);
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
let currentLayout = $state<{ id: string; order: number; w: number; h: number }[]>([]);
|
|
16
|
+
let saving = $state(false);
|
|
17
|
+
let editable = $state(false);
|
|
20
18
|
|
|
21
19
|
async function loadCharts({ showLoading = true } = {}) {
|
|
22
20
|
if (showLoading) loading = true;
|
|
@@ -33,7 +31,8 @@
|
|
|
33
31
|
if (showLoading) loading = false;
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
async function
|
|
34
|
+
async function handleLayoutChange(changes: { id: string; order: number; w: number; h: number }[]) {
|
|
35
|
+
saving = true;
|
|
37
36
|
for (const change of changes) {
|
|
38
37
|
await utils.lobb.updateOne("reports_charts", change.id, {
|
|
39
38
|
sort_order: change.order,
|
|
@@ -41,6 +40,7 @@
|
|
|
41
40
|
row_span: change.h,
|
|
42
41
|
});
|
|
43
42
|
}
|
|
43
|
+
saving = false;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function getChartGridSize(chart: any): Record<string, unknown> {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
onMount(() => loadCharts());
|
|
62
62
|
</script>
|
|
63
63
|
|
|
64
|
-
<div class="report-layout"
|
|
64
|
+
<div class="report-layout">
|
|
65
65
|
{#if loading}
|
|
66
66
|
<div class="flex h-full w-full flex-col items-center justify-center gap-4" style="grid-row: 1 / -1">
|
|
67
67
|
<Icons.LoaderCircle class="animate-spin opacity-50" size="50" />
|
|
@@ -79,51 +79,33 @@
|
|
|
79
79
|
<div class="text-xs text-muted-foreground">{report.description}</div>
|
|
80
80
|
</div>
|
|
81
81
|
</div>
|
|
82
|
-
<div class="flex gap-2 self-end">
|
|
83
|
-
{#if
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
</Button>
|
|
94
|
-
<Button
|
|
95
|
-
variant="default"
|
|
96
|
-
class="h-7 px-3 text-xs font-normal"
|
|
97
|
-
Icon={Icons.Check}
|
|
98
|
-
onclick={async () => {
|
|
99
|
-
await saveChartsLayout(currentLayout);
|
|
100
|
-
editMode = false;
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
103
|
-
Save layout
|
|
104
|
-
</Button>
|
|
82
|
+
<div class="flex items-center gap-2 self-end">
|
|
83
|
+
{#if saving}
|
|
84
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
85
|
+
<Icons.LoaderCircle class="animate-spin" size={12} />
|
|
86
|
+
Saving...
|
|
87
|
+
</div>
|
|
88
|
+
{:else if editable}
|
|
89
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
90
|
+
<div class="h-1.5 w-1.5 rounded-full bg-green-500"></div>
|
|
91
|
+
Layout editable
|
|
92
|
+
</div>
|
|
105
93
|
{:else}
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Icon={Icons.LayoutDashboard}
|
|
111
|
-
onclick={() => (editMode = true)}
|
|
112
|
-
>
|
|
113
|
-
Edit layout
|
|
114
|
-
</Button>
|
|
115
|
-
{/if}
|
|
116
|
-
<CreateDetailViewButton
|
|
117
|
-
collectionName="reports_charts"
|
|
118
|
-
values={{ report_id: { id: reportId, name: report.name } }}
|
|
119
|
-
variant="default"
|
|
120
|
-
class="h-7 px-3 text-xs font-normal"
|
|
121
|
-
Icon={Icons.Plus}
|
|
122
|
-
onSuccessfullSave={async () => await loadCharts()}
|
|
123
|
-
>
|
|
124
|
-
Create chart
|
|
125
|
-
</CreateDetailViewButton>
|
|
94
|
+
<div class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
95
|
+
<div class="h-1.5 w-1.5 rounded-full bg-muted-foreground/40"></div>
|
|
96
|
+
Expand window to rearrange
|
|
97
|
+
</div>
|
|
126
98
|
{/if}
|
|
99
|
+
<CreateDetailViewButton
|
|
100
|
+
collectionName="reports_charts"
|
|
101
|
+
values={{ report_id: { id: reportId, name: report.name } }}
|
|
102
|
+
variant="default"
|
|
103
|
+
class="h-7 px-3 text-xs font-normal"
|
|
104
|
+
Icon={Icons.Plus}
|
|
105
|
+
onSuccessfullSave={async () => await loadCharts()}
|
|
106
|
+
>
|
|
107
|
+
Create chart
|
|
108
|
+
</CreateDetailViewButton>
|
|
127
109
|
</div>
|
|
128
110
|
</div>
|
|
129
111
|
|
|
@@ -138,7 +120,7 @@
|
|
|
138
120
|
</div>
|
|
139
121
|
{:else}
|
|
140
122
|
{#key charts}
|
|
141
|
-
<GridStackComponent bind:
|
|
123
|
+
<GridStackComponent bind:editable onLayoutChange={handleLayoutChange}>
|
|
142
124
|
{#each [...charts].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) as chart (chart.id)}
|
|
143
125
|
<div
|
|
144
126
|
class="grid-stack-item"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/lobb-ext-reports",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"package": "svelte-package --input extensions/reports/studio"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@lobb-js/core": "^0.
|
|
37
|
+
"@lobb-js/core": "^0.26.1",
|
|
38
38
|
"chart.js": "^4.4.8",
|
|
39
39
|
"gridstack": "^12.6.0",
|
|
40
40
|
"hono": "^4.7.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@faker-js/faker": "^9.6.0",
|
|
48
48
|
"@playwright/test": "^1.58.2",
|
|
49
|
-
"@lobb-js/studio": "^0.
|
|
49
|
+
"@lobb-js/studio": "^0.24.0",
|
|
50
50
|
"@lucide/svelte": "^0.563.1",
|
|
51
51
|
"@sveltejs/adapter-node": "^5.5.4",
|
|
52
52
|
"@sveltejs/kit": "^2.55.0",
|