@lobb-js/studio 0.28.5 → 0.29.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/components/Studio.svelte +7 -4
- package/dist/components/combobox.svelte +3 -3
- package/dist/components/confirmationDialog/confirmationDialog.svelte +1 -1
- package/dist/components/dataTable/dataTable.svelte +74 -82
- package/dist/components/dataTable/dataTable.svelte.d.ts +3 -19
- package/dist/components/dataTable/filter.svelte +1 -1
- package/dist/components/dataTable/filterButton.svelte +1 -1
- package/dist/components/dataTable/header.svelte +33 -54
- package/dist/components/dataTable/header.svelte.d.ts +3 -2
- package/dist/components/dataTable/sort.svelte +1 -1
- package/dist/components/dataTable/sortButton.svelte +2 -2
- package/dist/components/detailView/create/children.svelte +1 -1
- package/dist/components/detailView/create/createDetailView.svelte +77 -42
- package/dist/components/detailView/create/createDetailView.svelte.d.ts +2 -2
- package/dist/components/detailView/create/createDetailViewButton.svelte +2 -2
- package/dist/components/detailView/create/createDetailViewButton.svelte.d.ts +1 -1
- package/dist/components/detailView/create/createManyView.svelte +10 -6
- package/dist/components/detailView/fieldInput.svelte +1 -1
- package/dist/components/detailView/fieldInputReplacement.svelte +1 -1
- package/dist/components/detailView/update/detailViewChildren.svelte +15 -26
- package/dist/components/detailView/update/detailViewChildren.svelte.d.ts +3 -8
- package/dist/components/detailView/update/updateDetailView.svelte +85 -27
- package/dist/components/detailView/update/updateDetailView.svelte.d.ts +2 -2
- package/dist/components/detailView/update/updateDetailViewButton.svelte +3 -2
- package/dist/components/detailView/update/updateDetailViewButton.svelte.d.ts +1 -1
- package/dist/components/detailView/utils.d.ts +17 -0
- package/dist/components/miniSidebar.svelte +4 -4
- package/dist/components/rangeCalendarButton.svelte +3 -3
- package/dist/components/routes/collections/collection.svelte +3 -3
- package/dist/components/routes/collections/collections.svelte +2 -2
- package/dist/components/routes/data_model/dataModel.svelte +2 -2
- package/dist/components/routes/data_model/syncManager.svelte +4 -4
- package/dist/components/routes/extensions/extension.svelte +1 -1
- package/dist/components/routes/home.svelte +1 -1
- package/dist/components/routes/workflows/workflows.svelte +5 -5
- package/dist/components/selectRecord.svelte +2 -21
- package/dist/components/setServerPage.svelte +1 -1
- package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
- package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
- package/dist/components/ui/command/command-dialog.svelte +1 -1
- package/dist/components/ui/range-calendar/range-calendar-day.svelte +1 -1
- package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
- package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
- package/dist/components/ui/select/select-separator.svelte +1 -1
- package/dist/components/workflowEditor.svelte +3 -3
- package/dist/store.types.d.ts +1 -1
- package/package.json +2 -2
- package/src/lib/components/Studio.svelte +7 -4
- package/src/lib/components/combobox.svelte +3 -3
- package/src/lib/components/confirmationDialog/confirmationDialog.svelte +1 -1
- package/src/lib/components/dataTable/dataTable.svelte +74 -82
- package/src/lib/components/dataTable/filter.svelte +1 -1
- package/src/lib/components/dataTable/filterButton.svelte +1 -1
- package/src/lib/components/dataTable/header.svelte +33 -54
- package/src/lib/components/dataTable/sort.svelte +1 -1
- package/src/lib/components/dataTable/sortButton.svelte +2 -2
- package/src/lib/components/detailView/create/children.svelte +1 -1
- package/src/lib/components/detailView/create/createDetailView.svelte +77 -42
- package/src/lib/components/detailView/create/createDetailViewButton.svelte +2 -2
- package/src/lib/components/detailView/create/createManyView.svelte +10 -6
- package/src/lib/components/detailView/fieldInput.svelte +1 -1
- package/src/lib/components/detailView/fieldInputReplacement.svelte +1 -1
- package/src/lib/components/detailView/update/detailViewChildren.svelte +15 -26
- package/src/lib/components/detailView/update/updateDetailView.svelte +85 -27
- package/src/lib/components/detailView/update/updateDetailViewButton.svelte +3 -2
- package/src/lib/components/detailView/utils.ts +13 -0
- package/src/lib/components/miniSidebar.svelte +4 -4
- package/src/lib/components/rangeCalendarButton.svelte +3 -3
- package/src/lib/components/routes/collections/collection.svelte +3 -3
- package/src/lib/components/routes/collections/collections.svelte +2 -2
- package/src/lib/components/routes/data_model/dataModel.svelte +2 -2
- package/src/lib/components/routes/data_model/syncManager.svelte +4 -4
- package/src/lib/components/routes/extensions/extension.svelte +1 -1
- package/src/lib/components/routes/home.svelte +1 -1
- package/src/lib/components/routes/workflows/workflows.svelte +5 -5
- package/src/lib/components/selectRecord.svelte +2 -21
- package/src/lib/components/setServerPage.svelte +1 -1
- package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
- package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
- package/src/lib/components/ui/command/command-dialog.svelte +1 -1
- package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +1 -1
- package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
- package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
- package/src/lib/components/ui/select/select-separator.svelte +1 -1
- package/src/lib/components/workflowEditor.svelte +3 -3
- package/src/lib/store.types.ts +1 -1
- package/vite-plugins/index.js +2 -4
- package/vite-plugins/lobb-extensions.js +12 -0
- package/vite-plugins/utils.js +15 -0
- package/vite-plugins/workspace-fs-allow.js +33 -0
- package/vite-plugins/contextual-lib-alias.js +0 -67
- package/vite-plugins/workspace-optimize.js +0 -106
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { Toaster } from "
|
|
2
|
+
import { Toaster } from "./ui/sonner";
|
|
3
3
|
import { onMount, onDestroy } from "svelte";
|
|
4
4
|
import { ModeWatcher } from "mode-watcher";
|
|
5
5
|
import { createLobb } from "../store.svelte";
|
|
6
6
|
import { setStudioContext } from "../context";
|
|
7
|
-
import Header from "
|
|
7
|
+
import Header from "./header.svelte";
|
|
8
8
|
import { LoaderCircle, ServerOff } from "lucide-svelte";
|
|
9
|
-
import MiniSidebar from "
|
|
10
|
-
import * as Tooltip from "
|
|
9
|
+
import MiniSidebar from "./miniSidebar.svelte";
|
|
10
|
+
import * as Tooltip from "./ui/tooltip";
|
|
11
11
|
import { Router, Route, Fallback, init as initRouter } from "@wjfe/n-savant";
|
|
12
12
|
import {
|
|
13
13
|
executeExtensionsOnStartup,
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
let cleanupRouter: (() => void) | undefined;
|
|
46
46
|
|
|
47
47
|
onMount(async () => {
|
|
48
|
+
// Remove the static loading screen defined in app.html — it shows instantly
|
|
49
|
+
// before JS loads to avoid a blank page, and is replaced by the Studio UI.
|
|
50
|
+
document.getElementById("app-loading")?.remove();
|
|
48
51
|
cleanupRouter = initRouter();
|
|
49
52
|
try {
|
|
50
53
|
ctx.meta = await lobb.getMeta();
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import CheckIcon from "@lucide/svelte/icons/check";
|
|
3
3
|
import ChevronsUpDownIcon from "@lucide/svelte/icons/chevrons-up-down";
|
|
4
4
|
import { tick } from "svelte";
|
|
5
|
-
import * as Command from "
|
|
6
|
-
import * as Popover from "
|
|
7
|
-
import { Button } from "
|
|
5
|
+
import * as Command from "./ui/command/index.js";
|
|
6
|
+
import * as Popover from "./ui/popover/index.js";
|
|
7
|
+
import { Button } from "./ui/button/index.js";
|
|
8
8
|
import { cn } from "../utils.js";
|
|
9
9
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
10
10
|
|
|
@@ -4,12 +4,6 @@
|
|
|
4
4
|
recordId: string | number;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export type RecordOperation =
|
|
8
|
-
| { type: "link"; record: any }
|
|
9
|
-
| { type: "unlink"; id: string | number }
|
|
10
|
-
| { type: "delete"; id: string | number }
|
|
11
|
-
| { type: "create"; record: any }
|
|
12
|
-
| { type: "update"; id: string | number; data: any };
|
|
13
7
|
</script>
|
|
14
8
|
|
|
15
9
|
<script lang="ts">
|
|
@@ -20,15 +14,14 @@
|
|
|
20
14
|
import Table, { type TableProps } from "./table.svelte";
|
|
21
15
|
import { getCollectionColumns, getCollectionParamsFields } from "./utils";
|
|
22
16
|
import { Pencil, Trash, Unlink } from "lucide-svelte";
|
|
23
|
-
import * as icons from "lucide-svelte";
|
|
24
17
|
import ListViewChildren from "./listViewChildren.svelte";
|
|
25
18
|
import FieldCell from "./fieldCell.svelte";
|
|
26
19
|
import Skeleton from "../ui/skeleton/skeleton.svelte";
|
|
27
20
|
import Button from "../ui/button/button.svelte";
|
|
28
21
|
import { showDialog } from "../../actions";
|
|
29
22
|
import UpdateDetailViewButton from "../detailView/update/updateDetailViewButton.svelte";
|
|
30
|
-
import { emitEvent } from "../../eventSystem";
|
|
31
23
|
import type { Snippet } from "svelte";
|
|
24
|
+
import type { Changes, ChildrenChanges } from "../detailView/utils";
|
|
32
25
|
import ExtensionsComponents from "../extensionsComponents.svelte";
|
|
33
26
|
import { getExtensionUtils, loadExtensionComponents } from "../../extensions/extensionUtils";
|
|
34
27
|
import Tabs from "./dataTableTabs.svelte";
|
|
@@ -41,7 +34,7 @@
|
|
|
41
34
|
filter?: any;
|
|
42
35
|
searchParams?: Record<string, any>;
|
|
43
36
|
parentContext?: ParentContext;
|
|
44
|
-
|
|
37
|
+
changes?: ChildrenChanges;
|
|
45
38
|
showHeader?: boolean;
|
|
46
39
|
showFooter?: boolean;
|
|
47
40
|
showImport?: boolean;
|
|
@@ -56,7 +49,7 @@
|
|
|
56
49
|
filter,
|
|
57
50
|
searchParams,
|
|
58
51
|
parentContext,
|
|
59
|
-
|
|
52
|
+
changes = $bindable<ChildrenChanges | undefined>(undefined),
|
|
60
53
|
showHeader = true,
|
|
61
54
|
showFooter = true,
|
|
62
55
|
showImport = true,
|
|
@@ -66,6 +59,46 @@
|
|
|
66
59
|
headerLeft,
|
|
67
60
|
}: Props = $props();
|
|
68
61
|
|
|
62
|
+
function getOrCreateUpdatedSlot(recordId: string): Changes | undefined {
|
|
63
|
+
if (!changes) return undefined;
|
|
64
|
+
let slot = changes.updated.find((u) => String(u.id) === String(recordId));
|
|
65
|
+
if (!slot) {
|
|
66
|
+
slot = { id: recordId, data: {}, children: {} };
|
|
67
|
+
changes.updated.push(slot);
|
|
68
|
+
}
|
|
69
|
+
return slot;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Derives the displayed rows by applying changes on top of server data.
|
|
73
|
+
// This is the single place responsible for optimistic UI — no handler touches data directly.
|
|
74
|
+
const data = $derived.by(() => {
|
|
75
|
+
if (!changes) return serverData;
|
|
76
|
+
|
|
77
|
+
const removedIds = new Set([
|
|
78
|
+
...changes.deleted.map((r) => String(r.id)),
|
|
79
|
+
...changes.unlinked.map((r) => String(r.id)),
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
let result = serverData.filter((r: any) => !removedIds.has(String(r.id)));
|
|
83
|
+
|
|
84
|
+
result = result.map((r: any) => {
|
|
85
|
+
const update = changes.updated.find((u) => String(u.id) === String(r.id));
|
|
86
|
+
return update && Object.keys(update.data).length ? { ...r, ...update.data } : r;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
for (const record of changes.linked) {
|
|
90
|
+
if (!result.some((r: any) => String(r.id) === String(record.id))) {
|
|
91
|
+
result = [...result, record];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for (const item of changes.created) {
|
|
96
|
+
result = [...result, { ...item.data, _pending: true }];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return result;
|
|
100
|
+
});
|
|
101
|
+
|
|
69
102
|
const hasRowActions = $derived(
|
|
70
103
|
loadExtensionComponents(ctx, "listView.entry.actions", undefined, { collectionName }).length > 0
|
|
71
104
|
);
|
|
@@ -89,7 +122,7 @@
|
|
|
89
122
|
|
|
90
123
|
let selectedRecords = $state([]);
|
|
91
124
|
let totalCount = $state(0);
|
|
92
|
-
let
|
|
125
|
+
let serverData: TableProps["data"] = $state([]);
|
|
93
126
|
let loading = $state(true);
|
|
94
127
|
const columns: TableProps["columns"] = $state(
|
|
95
128
|
getCollectionColumns(ctx, collectionName),
|
|
@@ -108,7 +141,6 @@
|
|
|
108
141
|
|
|
109
142
|
async function loadData(params: any) {
|
|
110
143
|
loading = true;
|
|
111
|
-
// parsing sort before sending the request
|
|
112
144
|
const paramsCopy = $state.snapshot(params);
|
|
113
145
|
const sort: TableProps["sort"] = paramsCopy.sort;
|
|
114
146
|
const sortStrings: string[] = [];
|
|
@@ -118,77 +150,43 @@
|
|
|
118
150
|
}
|
|
119
151
|
}
|
|
120
152
|
paramsCopy.sort = sortStrings.join(",");
|
|
121
|
-
|
|
122
|
-
// sending the request
|
|
123
153
|
const response = await lobb.findAll(collectionName, paramsCopy);
|
|
124
154
|
const res = await response.json();
|
|
125
|
-
|
|
126
|
-
data = res.data;
|
|
155
|
+
serverData = res.data;
|
|
127
156
|
totalCount = res.meta.totalCount;
|
|
128
|
-
|
|
129
157
|
loading = false;
|
|
130
158
|
}
|
|
131
159
|
|
|
132
|
-
// Internal handler: updates data optimistically then calls onOperation
|
|
133
|
-
function applyOperation(op: RecordOperation) {
|
|
134
|
-
if (op.type === "link") {
|
|
135
|
-
data = [...data, op.record];
|
|
136
|
-
} else if (op.type === "unlink" || op.type === "delete") {
|
|
137
|
-
data = data.filter((r: any) => String(r.id) !== String(op.id));
|
|
138
|
-
} else if (op.type === "create") {
|
|
139
|
-
data = [...data, { ...op.record, _pending: true }];
|
|
140
|
-
} else if (op.type === "update") {
|
|
141
|
-
data = data.map((r: any) => String(r.id) === String(op.id) ? { ...r, ...op.data } : r);
|
|
142
|
-
}
|
|
143
|
-
onOperation?.(op);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
160
|
async function handleDelete(entryId: string) {
|
|
147
161
|
const result = await showDialog("Are you sure?", "This will permanently delete the record.");
|
|
148
|
-
if (result)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
if (!result) return;
|
|
163
|
+
if (changes) {
|
|
164
|
+
const record = data.find((r: any) => String(r.id) === String(entryId));
|
|
165
|
+
if (record) changes.deleted.push($state.snapshot(record));
|
|
166
|
+
} else if (parentContext) {
|
|
167
|
+
serverData = serverData.filter((r: any) => String(r.id) !== String(entryId));
|
|
168
|
+
await lobb.updateOne(parentContext.collectionName, String(parentContext.recordId), {}, { [collectionName]: { delete: [entryId] } });
|
|
169
|
+
params = { ...params };
|
|
170
|
+
} else {
|
|
171
|
+
serverData = serverData.filter((r: any) => String(r.id) !== String(entryId));
|
|
172
|
+
await lobb.deleteOne(collectionName, entryId);
|
|
173
|
+
params = { ...params };
|
|
158
174
|
}
|
|
159
175
|
}
|
|
160
176
|
|
|
161
177
|
async function handleUnlink(entryId: string) {
|
|
162
178
|
const result = await showDialog("Are you sure?", "This will unlink the record without deleting it.");
|
|
163
|
-
if (result)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
179
|
+
if (!result) return;
|
|
180
|
+
if (changes) {
|
|
181
|
+
const record = data.find((r: any) => String(r.id) === String(entryId));
|
|
182
|
+
if (record) changes.unlinked.push($state.snapshot(record));
|
|
183
|
+
} else {
|
|
184
|
+
serverData = serverData.filter((r: any) => String(r.id) !== String(entryId));
|
|
185
|
+
await lobb.updateOne(parentContext!.collectionName, String(parentContext!.recordId), {}, { [collectionName]: { unlink: [entryId] } });
|
|
186
|
+
params = { ...params };
|
|
170
187
|
}
|
|
171
188
|
}
|
|
172
189
|
|
|
173
|
-
async function getWorkflowTools(
|
|
174
|
-
entry: Record<string, any>,
|
|
175
|
-
): Promise<any[]> {
|
|
176
|
-
// TODO: instead of firing the events like this. get them all the fire them one by one to get their results
|
|
177
|
-
const eventResult = await emitEvent(
|
|
178
|
-
{ lobb, ctx },
|
|
179
|
-
"studio.collections.listView.tools",
|
|
180
|
-
{
|
|
181
|
-
collectionName,
|
|
182
|
-
entry,
|
|
183
|
-
},
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
if (eventResult) {
|
|
187
|
-
return eventResult.tools;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return [];
|
|
191
|
-
}
|
|
192
190
|
</script>
|
|
193
191
|
|
|
194
192
|
<div
|
|
@@ -209,7 +207,14 @@
|
|
|
209
207
|
{/snippet}
|
|
210
208
|
|
|
211
209
|
{#if showHeader}
|
|
212
|
-
<Header
|
|
210
|
+
<Header
|
|
211
|
+
bind:params
|
|
212
|
+
{collectionName}
|
|
213
|
+
bind:selectedRecords
|
|
214
|
+
{showImport}
|
|
215
|
+
{parentContext}
|
|
216
|
+
{changes}
|
|
217
|
+
>
|
|
213
218
|
{#snippet left()}
|
|
214
219
|
{@render headerLeft?.()}
|
|
215
220
|
{/snippet}
|
|
@@ -246,6 +251,7 @@
|
|
|
246
251
|
variant="ghost"
|
|
247
252
|
class="h-5 w-5 px-0 py-0 text-muted-foreground hover:bg-transparent"
|
|
248
253
|
Icon={Pencil}
|
|
254
|
+
changes={getOrCreateUpdatedSlot(String(entry.id))}
|
|
249
255
|
onSuccessfullSave={async () => {
|
|
250
256
|
params = { ...params };
|
|
251
257
|
}}
|
|
@@ -270,20 +276,6 @@
|
|
|
270
276
|
title="Delete permanently"
|
|
271
277
|
></Button>
|
|
272
278
|
{/if}
|
|
273
|
-
{#await getWorkflowTools($state.snapshot(entry))}
|
|
274
|
-
<div></div>
|
|
275
|
-
{:then workflowTools}
|
|
276
|
-
{#each workflowTools as workflowTool}
|
|
277
|
-
<Button
|
|
278
|
-
variant="ghost"
|
|
279
|
-
class="h-5 w-5 px-0 py-0 text-muted-foreground hover:bg-transparent"
|
|
280
|
-
Icon={icons[
|
|
281
|
-
workflowTool.icon as keyof typeof icons
|
|
282
|
-
]}
|
|
283
|
-
onclick={workflowTool.onclick}
|
|
284
|
-
></Button>
|
|
285
|
-
{/each}
|
|
286
|
-
{/await}
|
|
287
279
|
{/snippet}
|
|
288
280
|
{#snippet overrideCell(value, column, entry)}
|
|
289
281
|
<FieldCell
|
|
@@ -2,31 +2,15 @@ export interface ParentContext {
|
|
|
2
2
|
collectionName: string;
|
|
3
3
|
recordId: string | number;
|
|
4
4
|
}
|
|
5
|
-
export type RecordOperation = {
|
|
6
|
-
type: "link";
|
|
7
|
-
record: any;
|
|
8
|
-
} | {
|
|
9
|
-
type: "unlink";
|
|
10
|
-
id: string | number;
|
|
11
|
-
} | {
|
|
12
|
-
type: "delete";
|
|
13
|
-
id: string | number;
|
|
14
|
-
} | {
|
|
15
|
-
type: "create";
|
|
16
|
-
record: any;
|
|
17
|
-
} | {
|
|
18
|
-
type: "update";
|
|
19
|
-
id: string | number;
|
|
20
|
-
data: any;
|
|
21
|
-
};
|
|
22
5
|
import { type TableProps } from "./table.svelte";
|
|
23
6
|
import type { Snippet } from "svelte";
|
|
7
|
+
import type { ChildrenChanges } from "../detailView/utils";
|
|
24
8
|
interface Props {
|
|
25
9
|
collectionName: string;
|
|
26
10
|
filter?: any;
|
|
27
11
|
searchParams?: Record<string, any>;
|
|
28
12
|
parentContext?: ParentContext;
|
|
29
|
-
|
|
13
|
+
changes?: ChildrenChanges;
|
|
30
14
|
showHeader?: boolean;
|
|
31
15
|
showFooter?: boolean;
|
|
32
16
|
showImport?: boolean;
|
|
@@ -35,6 +19,6 @@ interface Props {
|
|
|
35
19
|
tableProps?: Partial<TableProps>;
|
|
36
20
|
headerLeft?: Snippet<[]>;
|
|
37
21
|
}
|
|
38
|
-
declare const DataTable: import("svelte").Component<Props, {}, "">;
|
|
22
|
+
declare const DataTable: import("svelte").Component<Props, {}, "changes">;
|
|
39
23
|
type DataTable = ReturnType<typeof DataTable>;
|
|
40
24
|
export default DataTable;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import * as Popover from "
|
|
2
|
+
import * as Popover from "../ui/popover/index.js";
|
|
3
3
|
import { ListFilter } from "lucide-svelte";
|
|
4
4
|
import { buttonVariants } from "../ui/button";
|
|
5
5
|
import Filter from "./filter.svelte";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getStudioContext } from "../../context";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import type { Changes, ChildrenChanges } from "../detailView/utils";
|
|
4
|
+
import type { ParentContext } from "./dataTable.svelte";
|
|
5
5
|
import { Download, ListRestart, Plus, Trash, Link } from "lucide-svelte";
|
|
6
6
|
import * as Tooltip from "../ui/tooltip";
|
|
7
7
|
import LlmButton from "../LlmButton.svelte";
|
|
@@ -15,14 +15,15 @@
|
|
|
15
15
|
import ExtensionsComponents from "../extensionsComponents.svelte";
|
|
16
16
|
import { getExtensionUtils } from "../../extensions/extensionUtils";
|
|
17
17
|
import type { Snippet } from "svelte";
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
const { lobb, ctx } = getStudioContext();
|
|
19
20
|
|
|
20
21
|
interface Props {
|
|
21
22
|
collectionName: string;
|
|
22
23
|
params: any;
|
|
23
24
|
selectedRecords: string[];
|
|
24
25
|
parentContext?: ParentContext;
|
|
25
|
-
|
|
26
|
+
changes?: ChildrenChanges;
|
|
26
27
|
showImport?: boolean;
|
|
27
28
|
left?: Snippet<[]>;
|
|
28
29
|
}
|
|
@@ -32,37 +33,27 @@
|
|
|
32
33
|
params = $bindable(),
|
|
33
34
|
selectedRecords = $bindable(),
|
|
34
35
|
parentContext,
|
|
35
|
-
|
|
36
|
+
changes,
|
|
36
37
|
showImport = true,
|
|
37
38
|
left
|
|
38
39
|
}: Props = $props();
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{},
|
|
49
|
-
{ [collectionName]: { link: [selected.id] } },
|
|
50
|
-
);
|
|
41
|
+
// Local changes object for the create form (recording mode only)
|
|
42
|
+
let createChanges = $state<Changes>({ data: {}, children: {} });
|
|
43
|
+
|
|
44
|
+
function handleLink(record: any) {
|
|
45
|
+
if (changes) {
|
|
46
|
+
changes.linked.push(record);
|
|
47
|
+
} else if (parentContext) {
|
|
48
|
+
lobb.updateOne(parentContext.collectionName, String(parentContext.recordId), {}, { [collectionName]: { link: [record.id] } });
|
|
51
49
|
resetTable();
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
async function
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
onOperation({ type: "create", record: formData });
|
|
53
|
+
async function handleCreateSuccess(snap: any) {
|
|
54
|
+
if (changes) {
|
|
55
|
+
changes.created.push({ data: snap.data });
|
|
59
56
|
} else {
|
|
60
|
-
await lobb.updateOne(
|
|
61
|
-
parentContext.collectionName,
|
|
62
|
-
String(parentContext.recordId),
|
|
63
|
-
{},
|
|
64
|
-
{ [collectionName]: { create: [formData] } },
|
|
65
|
-
);
|
|
66
57
|
resetTable();
|
|
67
58
|
}
|
|
68
59
|
}
|
|
@@ -199,37 +190,25 @@
|
|
|
199
190
|
refresh={() => { params = { ...params }; }}
|
|
200
191
|
/>
|
|
201
192
|
{#if parentContext}
|
|
202
|
-
|
|
203
|
-
<SelectRecord
|
|
204
|
-
{collectionName}
|
|
205
|
-
variant="outline"
|
|
206
|
-
class="h-7 px-3 text-xs font-normal"
|
|
207
|
-
Icon={Link}
|
|
208
|
-
onSelect={handleLink}
|
|
209
|
-
>
|
|
210
|
-
{headerIsSmall ? "" : "Link"}
|
|
211
|
-
</SelectRecord>
|
|
212
|
-
{/if}
|
|
213
|
-
<CreateDetailViewButton
|
|
193
|
+
<SelectRecord
|
|
214
194
|
{collectionName}
|
|
215
|
-
variant="
|
|
216
|
-
class="h-7 px-3 text-xs font-normal"
|
|
217
|
-
Icon={Plus}
|
|
218
|
-
rollback={true}
|
|
219
|
-
onSuccessfullSave={handleChildCreate}
|
|
220
|
-
>
|
|
221
|
-
{headerIsSmall ? "" : "Create"}
|
|
222
|
-
</CreateDetailViewButton>
|
|
223
|
-
{:else}
|
|
224
|
-
<CreateDetailViewButton
|
|
225
|
-
{collectionName}
|
|
226
|
-
variant="default"
|
|
195
|
+
variant="outline"
|
|
227
196
|
class="h-7 px-3 text-xs font-normal"
|
|
228
|
-
Icon={
|
|
229
|
-
|
|
197
|
+
Icon={Link}
|
|
198
|
+
onSelect={handleLink}
|
|
230
199
|
>
|
|
231
|
-
{headerIsSmall ? "" : "
|
|
232
|
-
</
|
|
200
|
+
{headerIsSmall ? "" : "Link"}
|
|
201
|
+
</SelectRecord>
|
|
233
202
|
{/if}
|
|
203
|
+
<CreateDetailViewButton
|
|
204
|
+
{collectionName}
|
|
205
|
+
variant="default"
|
|
206
|
+
class="h-7 px-3 text-xs font-normal"
|
|
207
|
+
Icon={Plus}
|
|
208
|
+
changes={changes ? createChanges : undefined}
|
|
209
|
+
onSuccessfullSave={handleCreateSuccess}
|
|
210
|
+
>
|
|
211
|
+
{headerIsSmall ? "" : "Create"}
|
|
212
|
+
</CreateDetailViewButton>
|
|
234
213
|
</div>
|
|
235
214
|
</div>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import type { ChildrenChanges } from "../detailView/utils";
|
|
2
|
+
import type { ParentContext } from "./dataTable.svelte";
|
|
1
3
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type { ParentContext, RecordOperation } from "./dataTable.svelte";
|
|
3
4
|
interface Props {
|
|
4
5
|
collectionName: string;
|
|
5
6
|
params: any;
|
|
6
7
|
selectedRecords: string[];
|
|
7
8
|
parentContext?: ParentContext;
|
|
8
|
-
|
|
9
|
+
changes?: ChildrenChanges;
|
|
9
10
|
showImport?: boolean;
|
|
10
11
|
left?: Snippet<[]>;
|
|
11
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import * as _ from "lodash-es";
|
|
3
3
|
|
|
4
|
-
import * as Popover from "
|
|
4
|
+
import * as Popover from "../ui/popover/index.js";
|
|
5
5
|
import { ArrowDown, ArrowUp, GripVertical, Plus, X } from "lucide-svelte";
|
|
6
6
|
import Button, { buttonVariants } from "../ui/button/button.svelte";
|
|
7
7
|
import Label from "../ui/label/label.svelte";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import * as Popover from "
|
|
2
|
+
import * as Popover from "../ui/popover/index.js";
|
|
3
3
|
import { ArrowDownWideNarrow } from "lucide-svelte";
|
|
4
|
-
import { buttonVariants } from "
|
|
4
|
+
import { buttonVariants } from "../ui/button";
|
|
5
5
|
import Sort from "./sort.svelte";
|
|
6
6
|
|
|
7
7
|
interface Props {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { getStudioContext } from "../../../context";
|
|
3
3
|
import { Link } from "lucide-svelte";
|
|
4
4
|
import CreateManyView from "./createManyView.svelte";
|
|
5
|
-
import ExtensionsComponents from "
|
|
5
|
+
import ExtensionsComponents from "../../extensionsComponents.svelte";
|
|
6
6
|
import { getExtensionUtils } from "../../../extensions/extensionUtils";
|
|
7
7
|
|
|
8
8
|
const { ctx, lobb } = getStudioContext();
|