@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.
Files changed (92) hide show
  1. package/dist/components/Studio.svelte +7 -4
  2. package/dist/components/combobox.svelte +3 -3
  3. package/dist/components/confirmationDialog/confirmationDialog.svelte +1 -1
  4. package/dist/components/dataTable/dataTable.svelte +74 -82
  5. package/dist/components/dataTable/dataTable.svelte.d.ts +3 -19
  6. package/dist/components/dataTable/filter.svelte +1 -1
  7. package/dist/components/dataTable/filterButton.svelte +1 -1
  8. package/dist/components/dataTable/header.svelte +33 -54
  9. package/dist/components/dataTable/header.svelte.d.ts +3 -2
  10. package/dist/components/dataTable/sort.svelte +1 -1
  11. package/dist/components/dataTable/sortButton.svelte +2 -2
  12. package/dist/components/detailView/create/children.svelte +1 -1
  13. package/dist/components/detailView/create/createDetailView.svelte +77 -42
  14. package/dist/components/detailView/create/createDetailView.svelte.d.ts +2 -2
  15. package/dist/components/detailView/create/createDetailViewButton.svelte +2 -2
  16. package/dist/components/detailView/create/createDetailViewButton.svelte.d.ts +1 -1
  17. package/dist/components/detailView/create/createManyView.svelte +10 -6
  18. package/dist/components/detailView/fieldInput.svelte +1 -1
  19. package/dist/components/detailView/fieldInputReplacement.svelte +1 -1
  20. package/dist/components/detailView/update/detailViewChildren.svelte +15 -26
  21. package/dist/components/detailView/update/detailViewChildren.svelte.d.ts +3 -8
  22. package/dist/components/detailView/update/updateDetailView.svelte +85 -27
  23. package/dist/components/detailView/update/updateDetailView.svelte.d.ts +2 -2
  24. package/dist/components/detailView/update/updateDetailViewButton.svelte +3 -2
  25. package/dist/components/detailView/update/updateDetailViewButton.svelte.d.ts +1 -1
  26. package/dist/components/detailView/utils.d.ts +17 -0
  27. package/dist/components/miniSidebar.svelte +4 -4
  28. package/dist/components/rangeCalendarButton.svelte +3 -3
  29. package/dist/components/routes/collections/collection.svelte +3 -3
  30. package/dist/components/routes/collections/collections.svelte +2 -2
  31. package/dist/components/routes/data_model/dataModel.svelte +2 -2
  32. package/dist/components/routes/data_model/syncManager.svelte +4 -4
  33. package/dist/components/routes/extensions/extension.svelte +1 -1
  34. package/dist/components/routes/home.svelte +1 -1
  35. package/dist/components/routes/workflows/workflows.svelte +5 -5
  36. package/dist/components/selectRecord.svelte +2 -21
  37. package/dist/components/setServerPage.svelte +1 -1
  38. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
  39. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
  40. package/dist/components/ui/command/command-dialog.svelte +1 -1
  41. package/dist/components/ui/range-calendar/range-calendar-day.svelte +1 -1
  42. package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
  43. package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
  44. package/dist/components/ui/select/select-separator.svelte +1 -1
  45. package/dist/components/workflowEditor.svelte +3 -3
  46. package/dist/store.types.d.ts +1 -1
  47. package/package.json +2 -2
  48. package/src/lib/components/Studio.svelte +7 -4
  49. package/src/lib/components/combobox.svelte +3 -3
  50. package/src/lib/components/confirmationDialog/confirmationDialog.svelte +1 -1
  51. package/src/lib/components/dataTable/dataTable.svelte +74 -82
  52. package/src/lib/components/dataTable/filter.svelte +1 -1
  53. package/src/lib/components/dataTable/filterButton.svelte +1 -1
  54. package/src/lib/components/dataTable/header.svelte +33 -54
  55. package/src/lib/components/dataTable/sort.svelte +1 -1
  56. package/src/lib/components/dataTable/sortButton.svelte +2 -2
  57. package/src/lib/components/detailView/create/children.svelte +1 -1
  58. package/src/lib/components/detailView/create/createDetailView.svelte +77 -42
  59. package/src/lib/components/detailView/create/createDetailViewButton.svelte +2 -2
  60. package/src/lib/components/detailView/create/createManyView.svelte +10 -6
  61. package/src/lib/components/detailView/fieldInput.svelte +1 -1
  62. package/src/lib/components/detailView/fieldInputReplacement.svelte +1 -1
  63. package/src/lib/components/detailView/update/detailViewChildren.svelte +15 -26
  64. package/src/lib/components/detailView/update/updateDetailView.svelte +85 -27
  65. package/src/lib/components/detailView/update/updateDetailViewButton.svelte +3 -2
  66. package/src/lib/components/detailView/utils.ts +13 -0
  67. package/src/lib/components/miniSidebar.svelte +4 -4
  68. package/src/lib/components/rangeCalendarButton.svelte +3 -3
  69. package/src/lib/components/routes/collections/collection.svelte +3 -3
  70. package/src/lib/components/routes/collections/collections.svelte +2 -2
  71. package/src/lib/components/routes/data_model/dataModel.svelte +2 -2
  72. package/src/lib/components/routes/data_model/syncManager.svelte +4 -4
  73. package/src/lib/components/routes/extensions/extension.svelte +1 -1
  74. package/src/lib/components/routes/home.svelte +1 -1
  75. package/src/lib/components/routes/workflows/workflows.svelte +5 -5
  76. package/src/lib/components/selectRecord.svelte +2 -21
  77. package/src/lib/components/setServerPage.svelte +1 -1
  78. package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
  79. package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
  80. package/src/lib/components/ui/command/command-dialog.svelte +1 -1
  81. package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +1 -1
  82. package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
  83. package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
  84. package/src/lib/components/ui/select/select-separator.svelte +1 -1
  85. package/src/lib/components/workflowEditor.svelte +3 -3
  86. package/src/lib/store.types.ts +1 -1
  87. package/vite-plugins/index.js +2 -4
  88. package/vite-plugins/lobb-extensions.js +12 -0
  89. package/vite-plugins/utils.js +15 -0
  90. package/vite-plugins/workspace-fs-allow.js +33 -0
  91. package/vite-plugins/contextual-lib-alias.js +0 -67
  92. package/vite-plugins/workspace-optimize.js +0 -106
@@ -1,13 +1,13 @@
1
1
  <script lang="ts">
2
- import { Toaster } from "../components/ui/sonner";
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 "../components/header.svelte";
7
+ import Header from "./header.svelte";
8
8
  import { LoaderCircle, ServerOff } from "lucide-svelte";
9
- import MiniSidebar from "../components/miniSidebar.svelte";
10
- import * as Tooltip from "../components/ui/tooltip";
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 "../components/ui/command/index.js";
6
- import * as Popover from "../components/ui/popover/index.js";
7
- import { Button } from "../components/ui/button/index.js";
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
 
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import * as AlertDialog from "../../components/ui/alert-dialog/index";
2
+ import * as AlertDialog from "../ui/alert-dialog/index";
3
3
  import { Check, X } from "lucide-svelte";
4
4
  import Button from "../ui/button/button.svelte";
5
5
 
@@ -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
- onOperation?: (op: RecordOperation) => void;
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
- onOperation,
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 data: TableProps["data"] = $state([]);
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
- if (onOperation) {
150
- applyOperation({ type: "delete", id: entryId });
151
- } else if (parentContext) {
152
- await lobb.updateOne(parentContext.collectionName, String(parentContext.recordId), {}, { [collectionName]: { delete: [entryId] } });
153
- params = { ...params };
154
- } else {
155
- await lobb.deleteOne(collectionName, entryId);
156
- params = { ...params };
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
- if (onOperation) {
165
- applyOperation({ type: "unlink", id: entryId });
166
- } else {
167
- await lobb.updateOne(parentContext!.collectionName, String(parentContext!.recordId), {}, { [collectionName]: { unlink: [entryId] } });
168
- params = { ...params };
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 bind:params {collectionName} bind:selectedRecords {parentContext} {showImport} onOperation={onOperation ? applyOperation : undefined}>
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
- onOperation?: (op: RecordOperation) => void;
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 "../../components/ui/popover/index.js";
2
+ import * as Popover from "../ui/popover/index.js";
3
3
  import Filter from "./filter.svelte";
4
4
  import {
5
5
  Plus,
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import * as Popover from "../../components/ui/popover/index.js";
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
- const { lobb, ctx } = getStudioContext();
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
- import type { ParentContext, RecordOperation } from "./dataTable.svelte";
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
- onOperation?: (op: RecordOperation) => void;
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
- onOperation,
36
+ changes,
36
37
  showImport = true,
37
38
  left
38
39
  }: Props = $props();
39
40
 
40
- async function handleLink(selected: any) {
41
- if (!parentContext) return;
42
- if (onOperation) {
43
- onOperation({ type: "link", record: selected });
44
- } else {
45
- await lobb.updateOne(
46
- parentContext.collectionName,
47
- String(parentContext.recordId),
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 handleChildCreate(formData: any) {
56
- if (!parentContext) return;
57
- if (onOperation) {
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
- {#if parentContext}
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="default"
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={Plus}
229
- onSuccessfullSave={() => (params = { ...params })}
197
+ Icon={Link}
198
+ onSelect={handleLink}
230
199
  >
231
- {headerIsSmall ? "" : "Create"}
232
- </CreateDetailViewButton>
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
- onOperation?: (op: RecordOperation) => void;
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 "../../components/ui/popover/index.js";
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 "../../components/ui/popover/index.js";
2
+ import * as Popover from "../ui/popover/index.js";
3
3
  import { ArrowDownWideNarrow } from "lucide-svelte";
4
- import { buttonVariants } from "../../components/ui/button";
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 "../../../components/extensionsComponents.svelte";
5
+ import ExtensionsComponents from "../../extensionsComponents.svelte";
6
6
  import { getExtensionUtils } from "../../../extensions/extensionUtils";
7
7
 
8
8
  const { ctx, lobb } = getStudioContext();