@lobb-js/studio 0.7.1 → 0.7.3
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/package.json +3 -2
- package/src/App.svelte +5 -0
- package/src/app.css +124 -0
- package/src/lib/components/LlmButton.svelte +137 -0
- package/src/lib/components/Studio.svelte +129 -0
- package/src/lib/components/alertView.svelte +20 -0
- package/src/lib/components/breadCrumbs.svelte +60 -0
- package/src/lib/components/codeEditor.svelte +152 -0
- package/src/lib/components/combobox.svelte +92 -0
- package/src/lib/components/confirmationDialog/confirmationDialog.svelte +33 -0
- package/src/lib/components/confirmationDialog/store.svelte.ts +28 -0
- package/src/lib/components/createManyButton.svelte +109 -0
- package/src/lib/components/dataTable/childRecords.svelte +142 -0
- package/src/lib/components/dataTable/dataTable.svelte +225 -0
- package/src/lib/components/dataTable/fieldCell.svelte +77 -0
- package/src/lib/components/dataTable/filter.svelte +284 -0
- package/src/lib/components/dataTable/filterButton.svelte +39 -0
- package/src/lib/components/dataTable/footer.svelte +84 -0
- package/src/lib/components/dataTable/header.svelte +155 -0
- package/src/lib/components/dataTable/sort.svelte +173 -0
- package/src/lib/components/dataTable/sortButton.svelte +36 -0
- package/src/lib/components/dataTable/table.svelte +337 -0
- package/src/lib/components/dataTable/utils.ts +127 -0
- package/src/lib/components/detailView/create/children.svelte +70 -0
- package/src/lib/components/detailView/create/createDetailView.svelte +228 -0
- package/src/lib/components/detailView/create/createDetailViewButton.svelte +37 -0
- package/src/lib/components/detailView/create/createManyView.svelte +252 -0
- package/src/lib/components/detailView/create/subRecords.svelte +50 -0
- package/src/lib/components/detailView/detailViewForm.svelte +104 -0
- package/src/lib/components/detailView/fieldCustomInput.svelte +26 -0
- package/src/lib/components/detailView/fieldInput.svelte +258 -0
- package/src/lib/components/detailView/fieldInputReplacement.svelte +199 -0
- package/src/lib/components/detailView/store.svelte.ts +59 -0
- package/src/lib/components/detailView/update/children.svelte +96 -0
- package/src/lib/components/detailView/update/updateDetailView.svelte +176 -0
- package/src/lib/components/detailView/update/updateDetailViewButton.svelte +56 -0
- package/src/lib/components/detailView/utils.ts +176 -0
- package/src/lib/components/diffViewer.svelte +105 -0
- package/src/lib/components/drawer.svelte +28 -0
- package/src/lib/components/extensionsComponents.svelte +33 -0
- package/src/lib/components/foreingKeyInput.svelte +80 -0
- package/src/lib/components/header.svelte +45 -0
- package/src/lib/components/loadingTypesForMonacoEditor.ts +36 -0
- package/src/lib/components/miniSidebar.svelte +226 -0
- package/src/lib/components/rangeCalendarButton.svelte +257 -0
- package/src/lib/components/richTextEditor.svelte +284 -0
- package/src/lib/components/routes/collections/collection.svelte +57 -0
- package/src/lib/components/routes/collections/collections.svelte +45 -0
- package/src/lib/components/routes/data_model/dataModel.svelte +40 -0
- package/src/lib/components/routes/data_model/flow.css +22 -0
- package/src/lib/components/routes/data_model/flow.svelte +84 -0
- package/src/lib/components/routes/data_model/syncManager.svelte +94 -0
- package/src/lib/components/routes/data_model/utils.ts +35 -0
- package/src/lib/components/routes/extensions/extension.svelte +19 -0
- package/src/lib/components/routes/home.svelte +40 -0
- package/src/lib/components/routes/workflows/workflows.svelte +136 -0
- package/src/lib/components/selectRecord.svelte +130 -0
- package/src/lib/components/setServerPage.svelte +50 -0
- package/src/lib/components/sidebar/index.ts +4 -0
- package/src/lib/components/sidebar/sidebar.svelte +149 -0
- package/src/lib/components/sidebar/sidebarElements.svelte +144 -0
- package/src/lib/components/sidebar/sidebarTrigger.svelte +33 -0
- package/src/lib/components/singletone.svelte +71 -0
- package/src/lib/components/ui/accordion/accordion-content.svelte +22 -0
- package/src/lib/components/ui/accordion/accordion-item.svelte +12 -0
- package/src/lib/components/ui/accordion/accordion-trigger.svelte +31 -0
- package/src/lib/components/ui/accordion/index.ts +17 -0
- package/src/lib/components/ui/alert/alert-description.svelte +16 -0
- package/src/lib/components/ui/alert/alert-title.svelte +24 -0
- package/src/lib/components/ui/alert/alert.svelte +39 -0
- package/src/lib/components/ui/alert/index.ts +14 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +13 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +17 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +26 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +20 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +19 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +18 -0
- package/src/lib/components/ui/alert-dialog/index.ts +40 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte +16 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte +31 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte +27 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb.svelte +15 -0
- package/src/lib/components/ui/breadcrumb/index.ts +25 -0
- package/src/lib/components/ui/button/button.svelte +110 -0
- package/src/lib/components/ui/button/index.ts +17 -0
- package/src/lib/components/ui/checkbox/checkbox.svelte +35 -0
- package/src/lib/components/ui/checkbox/index.ts +6 -0
- package/src/lib/components/ui/command/command-dialog.svelte +35 -0
- package/src/lib/components/ui/command/command-empty.svelte +12 -0
- package/src/lib/components/ui/command/command-group.svelte +31 -0
- package/src/lib/components/ui/command/command-input.svelte +25 -0
- package/src/lib/components/ui/command/command-item.svelte +19 -0
- package/src/lib/components/ui/command/command-link-item.svelte +19 -0
- package/src/lib/components/ui/command/command-list.svelte +16 -0
- package/src/lib/components/ui/command/command-separator.svelte +12 -0
- package/src/lib/components/ui/command/command-shortcut.svelte +20 -0
- package/src/lib/components/ui/command/command.svelte +21 -0
- package/src/lib/components/ui/command/index.ts +40 -0
- package/src/lib/components/ui/dialog/dialog-content.svelte +38 -0
- package/src/lib/components/ui/dialog/dialog-description.svelte +16 -0
- package/src/lib/components/ui/dialog/dialog-footer.svelte +20 -0
- package/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/src/lib/components/ui/dialog/dialog-overlay.svelte +19 -0
- package/src/lib/components/ui/dialog/dialog-title.svelte +16 -0
- package/src/lib/components/ui/dialog/index.ts +37 -0
- package/src/lib/components/ui/input/index.ts +7 -0
- package/src/lib/components/ui/input/input.svelte +46 -0
- package/src/lib/components/ui/label/index.ts +7 -0
- package/src/lib/components/ui/label/label.svelte +19 -0
- package/src/lib/components/ui/popover/index.ts +17 -0
- package/src/lib/components/ui/popover/popover-content.svelte +28 -0
- package/src/lib/components/ui/range-calendar/index.ts +30 -0
- package/src/lib/components/ui/range-calendar/range-calendar-cell.svelte +19 -0
- package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +35 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-header.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-heading.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-months.svelte +20 -0
- package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +27 -0
- package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +27 -0
- package/src/lib/components/ui/range-calendar/range-calendar.svelte +57 -0
- package/src/lib/components/ui/select/index.ts +34 -0
- package/src/lib/components/ui/select/select-content.svelte +38 -0
- package/src/lib/components/ui/select/select-group-heading.svelte +16 -0
- package/src/lib/components/ui/select/select-item.svelte +37 -0
- package/src/lib/components/ui/select/select-scroll-down-button.svelte +19 -0
- package/src/lib/components/ui/select/select-scroll-up-button.svelte +19 -0
- package/src/lib/components/ui/select/select-separator.svelte +13 -0
- package/src/lib/components/ui/select/select-trigger.svelte +24 -0
- package/src/lib/components/ui/separator/index.ts +7 -0
- package/src/lib/components/ui/separator/separator.svelte +22 -0
- package/src/lib/components/ui/skeleton/index.ts +7 -0
- package/src/lib/components/ui/skeleton/skeleton.svelte +22 -0
- package/src/lib/components/ui/sonner/index.ts +1 -0
- package/src/lib/components/ui/sonner/sonner.svelte +20 -0
- package/src/lib/components/ui/switch/index.ts +7 -0
- package/src/lib/components/ui/switch/switch.svelte +27 -0
- package/src/lib/components/ui/textarea/index.ts +7 -0
- package/src/lib/components/ui/textarea/textarea.svelte +22 -0
- package/src/lib/components/ui/tooltip/index.ts +18 -0
- package/src/lib/components/ui/tooltip/tooltip-content.svelte +21 -0
- package/src/lib/components/workflowEditor.svelte +188 -0
- package/src/lib/context.ts +22 -0
- package/src/lib/eventSystem.ts +40 -0
- package/src/lib/extensions/extension.types.ts +92 -0
- package/src/lib/extensions/extensionUtils.ts +156 -0
- package/src/lib/index.ts +24 -0
- package/src/lib/store.svelte.ts +13 -0
- package/src/lib/store.types.ts +28 -0
- package/src/lib/utils.ts +68 -0
- package/src/main.ts +18 -0
- package/src/stories/detailView/detailViewForm.stories.svelte +79 -0
- package/src/vite-env.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/studio",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
+
"src",
|
|
9
10
|
"dist",
|
|
10
11
|
"vite-plugins"
|
|
11
12
|
],
|
|
@@ -83,7 +84,7 @@
|
|
|
83
84
|
"@codemirror/theme-one-dark": "^6.1.3",
|
|
84
85
|
"@codemirror/view": "^6.39.12",
|
|
85
86
|
"@dagrejs/dagre": "^1.1.5",
|
|
86
|
-
"@lobb-js/sdk": "0.1.
|
|
87
|
+
"@lobb-js/sdk": "^0.1.5",
|
|
87
88
|
"@lucide/svelte": "^0.563.1",
|
|
88
89
|
"@tailwindcss/vite": "^4.1.18",
|
|
89
90
|
"@wjfe/n-savant": "^0.3.0",
|
package/src/App.svelte
ADDED
package/src/app.css
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
@import "tw-animate-css";
|
|
4
|
+
|
|
5
|
+
@source "../../../packages";
|
|
6
|
+
@source "../node_modules/@lobb-js";
|
|
7
|
+
|
|
8
|
+
@custom-variant dark (&:is(.dark *));
|
|
9
|
+
|
|
10
|
+
:root {
|
|
11
|
+
--radius: 0.625rem;
|
|
12
|
+
--background: oklch(1 0 0);
|
|
13
|
+
--foreground: oklch(0.129 0.042 264.695);
|
|
14
|
+
--card: oklch(1 0 0);
|
|
15
|
+
--card-foreground: oklch(0.129 0.042 264.695);
|
|
16
|
+
--popover: oklch(1 0 0);
|
|
17
|
+
--popover-foreground: oklch(0.129 0.042 264.695);
|
|
18
|
+
--primary: oklch(0.208 0.042 265.755);
|
|
19
|
+
--primary-foreground: oklch(0.984 0.003 247.858);
|
|
20
|
+
--secondary: oklch(0.968 0.007 247.896);
|
|
21
|
+
--secondary-foreground: oklch(0.208 0.042 265.755);
|
|
22
|
+
--muted: oklch(0.968 0.007 247.896);
|
|
23
|
+
--muted-foreground: oklch(0.554 0.046 257.417);
|
|
24
|
+
--accent: oklch(0.968 0.007 247.896);
|
|
25
|
+
--accent-foreground: oklch(0.208 0.042 265.755);
|
|
26
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
27
|
+
--border: oklch(0.929 0.013 255.508);
|
|
28
|
+
--input: oklch(0.929 0.013 255.508);
|
|
29
|
+
--ring: oklch(0.704 0.04 256.788);
|
|
30
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
31
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
32
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
33
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
34
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
35
|
+
--sidebar: oklch(0.984 0.003 247.858);
|
|
36
|
+
--sidebar-foreground: oklch(0.129 0.042 264.695);
|
|
37
|
+
--sidebar-primary: oklch(0.208 0.042 265.755);
|
|
38
|
+
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
|
39
|
+
--sidebar-accent: oklch(0.968 0.007 247.896);
|
|
40
|
+
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
|
|
41
|
+
--sidebar-border: oklch(0.929 0.013 255.508);
|
|
42
|
+
--sidebar-ring: oklch(0.704 0.04 256.788);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dark {
|
|
46
|
+
--background: oklch(0.129 0.042 264.695);
|
|
47
|
+
--foreground: oklch(0.984 0.003 247.858);
|
|
48
|
+
--card: oklch(0.208 0.042 265.755);
|
|
49
|
+
--card-foreground: oklch(0.984 0.003 247.858);
|
|
50
|
+
--popover: oklch(0.208 0.042 265.755);
|
|
51
|
+
--popover-foreground: oklch(0.984 0.003 247.858);
|
|
52
|
+
--primary: oklch(0.929 0.013 255.508);
|
|
53
|
+
--primary-foreground: oklch(0.208 0.042 265.755);
|
|
54
|
+
--secondary: oklch(0.279 0.041 260.031);
|
|
55
|
+
--secondary-foreground: oklch(0.984 0.003 247.858);
|
|
56
|
+
--muted: oklch(0.279 0.041 260.031);
|
|
57
|
+
--muted-foreground: oklch(0.704 0.04 256.788);
|
|
58
|
+
--accent: oklch(0.279 0.041 260.031);
|
|
59
|
+
--accent-foreground: oklch(0.984 0.003 247.858);
|
|
60
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
61
|
+
--border: oklch(1 0 0 / 10%);
|
|
62
|
+
--input: oklch(1 0 0 / 15%);
|
|
63
|
+
--ring: oklch(0.551 0.027 264.364);
|
|
64
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
65
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
66
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
67
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
68
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
69
|
+
--sidebar: oklch(0.208 0.042 265.755);
|
|
70
|
+
--sidebar-foreground: oklch(0.984 0.003 247.858);
|
|
71
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
72
|
+
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
|
|
73
|
+
--sidebar-accent: oklch(0.279 0.041 260.031);
|
|
74
|
+
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
|
|
75
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
76
|
+
--sidebar-ring: oklch(0.551 0.027 264.364);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@theme inline {
|
|
80
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
81
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
82
|
+
--radius-lg: var(--radius);
|
|
83
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
84
|
+
--color-background: var(--background);
|
|
85
|
+
--color-foreground: var(--foreground);
|
|
86
|
+
--color-card: var(--card);
|
|
87
|
+
--color-card-foreground: var(--card-foreground);
|
|
88
|
+
--color-popover: var(--popover);
|
|
89
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
90
|
+
--color-primary: var(--primary);
|
|
91
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
92
|
+
--color-secondary: var(--secondary);
|
|
93
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
94
|
+
--color-muted: var(--muted);
|
|
95
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
96
|
+
--color-accent: var(--accent);
|
|
97
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
98
|
+
--color-destructive: var(--destructive);
|
|
99
|
+
--color-border: var(--border);
|
|
100
|
+
--color-input: var(--input);
|
|
101
|
+
--color-ring: var(--ring);
|
|
102
|
+
--color-chart-1: var(--chart-1);
|
|
103
|
+
--color-chart-2: var(--chart-2);
|
|
104
|
+
--color-chart-3: var(--chart-3);
|
|
105
|
+
--color-chart-4: var(--chart-4);
|
|
106
|
+
--color-chart-5: var(--chart-5);
|
|
107
|
+
--color-sidebar: var(--sidebar);
|
|
108
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
109
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
110
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
111
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
112
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
113
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
114
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@layer base {
|
|
118
|
+
* {
|
|
119
|
+
@apply border-border outline-ring/50;
|
|
120
|
+
}
|
|
121
|
+
body {
|
|
122
|
+
@apply bg-background text-foreground;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getStudioContext } from "../context";
|
|
3
|
+
import { Brain, LoaderIcon, Send } from "lucide-svelte";
|
|
4
|
+
|
|
5
|
+
const { lobb, ctx } = getStudioContext();
|
|
6
|
+
import Button, { type ButtonProps } from "./ui/button/button.svelte";
|
|
7
|
+
import * as Popover from "./ui/popover";
|
|
8
|
+
import Textarea from "./ui/textarea/textarea.svelte";
|
|
9
|
+
import { toast } from "svelte-sonner";
|
|
10
|
+
|
|
11
|
+
interface LocalProp {
|
|
12
|
+
value?: any;
|
|
13
|
+
title: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
format?: any;
|
|
17
|
+
messages?: any[];
|
|
18
|
+
variant?: ButtonProps["variant"];
|
|
19
|
+
class?: ButtonProps["class"];
|
|
20
|
+
Icon?: ButtonProps["Icon"];
|
|
21
|
+
children?: ButtonProps["children"];
|
|
22
|
+
onApiResponseComplete?: (res: any) => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let {
|
|
26
|
+
value = $bindable(),
|
|
27
|
+
title,
|
|
28
|
+
description,
|
|
29
|
+
placeholder = "write prompt description",
|
|
30
|
+
variant = "default",
|
|
31
|
+
Icon = Brain,
|
|
32
|
+
onApiResponseComplete,
|
|
33
|
+
messages,
|
|
34
|
+
format = { type: "text" },
|
|
35
|
+
...props
|
|
36
|
+
}: LocalProp = $props();
|
|
37
|
+
|
|
38
|
+
let loading = $state(false);
|
|
39
|
+
let popoverOpen = $state(false);
|
|
40
|
+
let prompt = $state("");
|
|
41
|
+
|
|
42
|
+
let localMessages: any[] = [];
|
|
43
|
+
if (messages) {
|
|
44
|
+
localMessages.push(...messages);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function handleSubmit(e: Event) {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
loading = true;
|
|
50
|
+
popoverOpen = false;
|
|
51
|
+
if (prompt) {
|
|
52
|
+
const response = await fetch(
|
|
53
|
+
`${lobb.lobbUrl}/api/collections/llm_chat`,
|
|
54
|
+
{
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: lobb.getHeaders(),
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
stream: true,
|
|
59
|
+
format: format,
|
|
60
|
+
messages: [
|
|
61
|
+
...localMessages,
|
|
62
|
+
{
|
|
63
|
+
role: "user",
|
|
64
|
+
content: prompt,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
if (response.ok && response.body) {
|
|
71
|
+
value = "";
|
|
72
|
+
const reader = response.body.getReader();
|
|
73
|
+
const textDecoder = new TextDecoder();
|
|
74
|
+
let done = false;
|
|
75
|
+
while (!done) {
|
|
76
|
+
const { done: readerDone, ...stream } = await reader.read();
|
|
77
|
+
const llmValue = stream.value;
|
|
78
|
+
done = readerDone;
|
|
79
|
+
const chunk = textDecoder.decode(llmValue, {
|
|
80
|
+
stream: true,
|
|
81
|
+
});
|
|
82
|
+
value += chunk;
|
|
83
|
+
}
|
|
84
|
+
if (format.type === "json_object") {
|
|
85
|
+
value = JSON.stringify(JSON.parse(value), null, 2);
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
toast.error("Failed to fetch stream");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (onApiResponseComplete) {
|
|
92
|
+
await onApiResponseComplete(value);
|
|
93
|
+
}
|
|
94
|
+
loading = false;
|
|
95
|
+
}
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
{#if ctx.meta.extensions.llm && ctx.meta.collections.llm_chat}
|
|
99
|
+
<Popover.Root bind:open={popoverOpen}>
|
|
100
|
+
<Popover.Trigger>
|
|
101
|
+
<Button {variant} class={props.class}>
|
|
102
|
+
{#if loading}
|
|
103
|
+
<LoaderIcon class="animate-spin" />
|
|
104
|
+
{:else}
|
|
105
|
+
<Icon />
|
|
106
|
+
{/if}
|
|
107
|
+
{#if props.children}
|
|
108
|
+
{@render props.children()}
|
|
109
|
+
{/if}
|
|
110
|
+
</Button>
|
|
111
|
+
</Popover.Trigger>
|
|
112
|
+
<Popover.Content collisionPadding={20} class="mt-2 w-screen max-w-[20rem]">
|
|
113
|
+
<form
|
|
114
|
+
onsubmit={handleSubmit}
|
|
115
|
+
class="flex flex-col items-start gap-4"
|
|
116
|
+
>
|
|
117
|
+
<div>
|
|
118
|
+
<div class="text-sm font-semibold">{title}</div>
|
|
119
|
+
<div class="text-xs text-muted-foreground">
|
|
120
|
+
{description}
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
<Textarea
|
|
124
|
+
bind:value={prompt}
|
|
125
|
+
placeholder="Type here..."
|
|
126
|
+
rows={5}
|
|
127
|
+
class="bg-muted text-xs"
|
|
128
|
+
/>
|
|
129
|
+
<Button
|
|
130
|
+
type="submit"
|
|
131
|
+
Icon={Send}
|
|
132
|
+
class="h-7 px-3 text-xs font-normal">Submit</Button
|
|
133
|
+
>
|
|
134
|
+
</form>
|
|
135
|
+
</Popover.Content>
|
|
136
|
+
</Popover.Root>
|
|
137
|
+
{/if}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Toaster } from "../components/ui/sonner";
|
|
3
|
+
import { onMount, onDestroy } from "svelte";
|
|
4
|
+
import { ModeWatcher } from "mode-watcher";
|
|
5
|
+
import { createLobb } from "../store.svelte";
|
|
6
|
+
import { setStudioContext } from "../context";
|
|
7
|
+
import Header from "../components/header.svelte";
|
|
8
|
+
import { LoaderCircle, ServerOff } from "lucide-svelte";
|
|
9
|
+
import MiniSidebar from "../components/miniSidebar.svelte";
|
|
10
|
+
import * as Tooltip from "../components/ui/tooltip";
|
|
11
|
+
import { Router, Route, Fallback, init as initRouter } from "@wjfe/n-savant";
|
|
12
|
+
import {
|
|
13
|
+
executeExtensionsOnStartup,
|
|
14
|
+
loadExtensions,
|
|
15
|
+
} from "../extensions/extensionUtils";
|
|
16
|
+
import extensionMap from 'virtual:lobb-studio-extensions';
|
|
17
|
+
import { mediaQueries } from "../utils";
|
|
18
|
+
import Home from "./routes/home.svelte";
|
|
19
|
+
import DataModel from "./routes/data_model/dataModel.svelte";
|
|
20
|
+
import Collections from "./routes/collections/collections.svelte";
|
|
21
|
+
import Workflows from "./routes/workflows/workflows.svelte";
|
|
22
|
+
import Extension from "./routes/extensions/extension.svelte";
|
|
23
|
+
|
|
24
|
+
interface StudioProps {
|
|
25
|
+
lobbUrl?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { lobbUrl }: StudioProps = $props();
|
|
29
|
+
|
|
30
|
+
const ctx = $state({
|
|
31
|
+
lobbUrl: lobbUrl ?? "",
|
|
32
|
+
extensions: {},
|
|
33
|
+
meta: null,
|
|
34
|
+
currentUrl: new URL(window.location.href),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const lobb = createLobb(lobbUrl ?? "");
|
|
38
|
+
|
|
39
|
+
setStudioContext({ ctx, lobb });
|
|
40
|
+
|
|
41
|
+
let status: "loading" | "error" | "ready" = $state("loading");
|
|
42
|
+
let isSmallScreen = $derived(!mediaQueries.sm.current);
|
|
43
|
+
let cleanupRouter: (() => void) | undefined;
|
|
44
|
+
|
|
45
|
+
onMount(async () => {
|
|
46
|
+
cleanupRouter = initRouter();
|
|
47
|
+
try {
|
|
48
|
+
ctx.meta = await lobb.getMeta();
|
|
49
|
+
ctx.extensions = await loadExtensions(lobb, ctx, extensionMap);
|
|
50
|
+
await executeExtensionsOnStartup(lobb, ctx);
|
|
51
|
+
status = "ready";
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error(err);
|
|
54
|
+
status = "error";
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
onDestroy(() => {
|
|
59
|
+
if (cleanupRouter) cleanupRouter();
|
|
60
|
+
});
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<ModeWatcher defaultMode="light" />
|
|
64
|
+
<Toaster position="top-right" class="z-50" />
|
|
65
|
+
|
|
66
|
+
{#if status === "loading"}
|
|
67
|
+
<div class="flex h-screen w-full flex-col items-center justify-center gap-4 text-muted-foreground">
|
|
68
|
+
<LoaderCircle class="animate-spin opacity-50" size="50" />
|
|
69
|
+
<div class="flex flex-col items-center justify-center">
|
|
70
|
+
<div>Loading the dashboard, please wait...</div>
|
|
71
|
+
<div class="text-xs">Loading and importing all necessary data and components from the lobb server.</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
{:else if status === "error"}
|
|
75
|
+
<div class="flex h-screen w-full flex-col items-center justify-center gap-4 text-muted-foreground">
|
|
76
|
+
<ServerOff class="opacity-50" size="50" />
|
|
77
|
+
<div class="flex flex-col items-center justify-center">
|
|
78
|
+
<div>Could not connect to the server</div>
|
|
79
|
+
<div class="text-xs">Could not connect to the lobb server at this endpoint ({ctx.lobbUrl})</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
{:else}
|
|
83
|
+
<Tooltip.Provider delayDuration={0} disableHoverableContent={true}>
|
|
84
|
+
<main
|
|
85
|
+
class="bg-muted h-screen w-screen"
|
|
86
|
+
style="display: grid; grid-template-columns: {isSmallScreen ? '1fr' : '3.5rem 1fr'};"
|
|
87
|
+
>
|
|
88
|
+
<MiniSidebar />
|
|
89
|
+
<div class="second_grid">
|
|
90
|
+
<Header />
|
|
91
|
+
<Router id="root-router" basePath="/studio">
|
|
92
|
+
<Route key="home" path="/">
|
|
93
|
+
{#snippet children(params)}
|
|
94
|
+
<Home />
|
|
95
|
+
{/snippet}
|
|
96
|
+
</Route>
|
|
97
|
+
<Route key="collections" path="/collections/:collection?">
|
|
98
|
+
{#snippet children(params)}
|
|
99
|
+
<Collections collectionName={params?.collection} />
|
|
100
|
+
{/snippet}
|
|
101
|
+
</Route>
|
|
102
|
+
<Route key="datamodel" path="/datamodel/*">
|
|
103
|
+
{#snippet children(params)}
|
|
104
|
+
<DataModel />
|
|
105
|
+
{/snippet}
|
|
106
|
+
</Route>
|
|
107
|
+
<Route key="workflows" path="/workflows/:workflow?">
|
|
108
|
+
{#snippet children(params)}
|
|
109
|
+
<Workflows workflowName={params?.workflow} />
|
|
110
|
+
{/snippet}
|
|
111
|
+
</Route>
|
|
112
|
+
<Route key="extensions" path="/extensions/:extension?/:page?/*">
|
|
113
|
+
{#snippet children(params)}
|
|
114
|
+
<Extension extension={params?.extension} page={params?.page} />
|
|
115
|
+
{/snippet}
|
|
116
|
+
</Route>
|
|
117
|
+
<Fallback>Not Found</Fallback>
|
|
118
|
+
</Router>
|
|
119
|
+
</div>
|
|
120
|
+
</main>
|
|
121
|
+
</Tooltip.Provider>
|
|
122
|
+
{/if}
|
|
123
|
+
|
|
124
|
+
<style>
|
|
125
|
+
.second_grid {
|
|
126
|
+
display: grid;
|
|
127
|
+
grid-template-rows: 2.5rem 1fr;
|
|
128
|
+
}
|
|
129
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Alert from "./ui/alert/index.js";
|
|
3
|
+
import { AlertCircleIcon } from "lucide-svelte";
|
|
4
|
+
import type { Snippet } from "svelte";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
title: string;
|
|
8
|
+
children: Snippet<[]>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { title, children }: Props = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Alert.Root variant="destructive">
|
|
15
|
+
<AlertCircleIcon />
|
|
16
|
+
<Alert.Title>{title}</Alert.Title>
|
|
17
|
+
<Alert.Description>
|
|
18
|
+
{@render children?.()}
|
|
19
|
+
</Alert.Description>
|
|
20
|
+
</Alert.Root>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Breadcrumb from "./ui/breadcrumb";
|
|
3
|
+
import { mediaQueries } from "../utils";
|
|
4
|
+
import { location } from "@wjfe/n-savant";
|
|
5
|
+
|
|
6
|
+
const isSmall = $derived(!mediaQueries.sm.current);
|
|
7
|
+
const pathNames = $derived(
|
|
8
|
+
location.url.pathname
|
|
9
|
+
.replace("/studio", "")
|
|
10
|
+
.split("/")
|
|
11
|
+
.filter((el: any) => el !== "")
|
|
12
|
+
.slice(0, 3),
|
|
13
|
+
);
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
{#if isSmall}
|
|
17
|
+
<div class="text-muted-foreground text-sm">
|
|
18
|
+
{pathNames[pathNames.length - 1] || "Home"}
|
|
19
|
+
</div>
|
|
20
|
+
{:else}
|
|
21
|
+
<Breadcrumb.Root>
|
|
22
|
+
<Breadcrumb.List class="flex-nowrap">
|
|
23
|
+
<Breadcrumb.Item>
|
|
24
|
+
{#if pathNames.length === 0}
|
|
25
|
+
<Breadcrumb.Page>Home</Breadcrumb.Page>
|
|
26
|
+
{:else}
|
|
27
|
+
<Breadcrumb.Link
|
|
28
|
+
class="cursor-pointer"
|
|
29
|
+
onclick={() => location.navigate("/studio")}
|
|
30
|
+
>
|
|
31
|
+
Home
|
|
32
|
+
</Breadcrumb.Link>
|
|
33
|
+
<Breadcrumb.Separator />
|
|
34
|
+
{/if}
|
|
35
|
+
</Breadcrumb.Item>
|
|
36
|
+
{#each pathNames as path, index}
|
|
37
|
+
{@const isLastElement = pathNames.length - 1 === index}
|
|
38
|
+
{@const currentFullPaths = pathNames
|
|
39
|
+
.slice(0, index + 1)
|
|
40
|
+
.join("/")}
|
|
41
|
+
<Breadcrumb.Item>
|
|
42
|
+
{#if isLastElement}
|
|
43
|
+
<Breadcrumb.Page>{path}</Breadcrumb.Page>
|
|
44
|
+
{:else}
|
|
45
|
+
<Breadcrumb.Link
|
|
46
|
+
class="cursor-pointer"
|
|
47
|
+
onclick={() =>
|
|
48
|
+
location.navigate(`/studio/${currentFullPaths}`)}
|
|
49
|
+
>
|
|
50
|
+
{path}
|
|
51
|
+
</Breadcrumb.Link>
|
|
52
|
+
{/if}
|
|
53
|
+
</Breadcrumb.Item>
|
|
54
|
+
{#if !isLastElement}
|
|
55
|
+
<Breadcrumb.Separator />
|
|
56
|
+
{/if}
|
|
57
|
+
{/each}
|
|
58
|
+
</Breadcrumb.List>
|
|
59
|
+
</Breadcrumb.Root>
|
|
60
|
+
{/if}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy } from 'svelte';
|
|
3
|
+
import { keymap } from '@codemirror/view';
|
|
4
|
+
import { EditorState } from '@codemirror/state';
|
|
5
|
+
import { basicSetup, EditorView } from 'codemirror';
|
|
6
|
+
import { javascript } from '@codemirror/lang-javascript';
|
|
7
|
+
import { sql } from '@codemirror/lang-sql';
|
|
8
|
+
import { oneDark } from '@codemirror/theme-one-dark';
|
|
9
|
+
import { cn } from '../utils.js';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
type: 'javascript' | 'typescript' | 'json' | 'sql';
|
|
13
|
+
name: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
default?: string;
|
|
16
|
+
types?: string;
|
|
17
|
+
class?: string;
|
|
18
|
+
handleCtrlSave?: () => void;
|
|
19
|
+
onChange?: (value: string) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
type,
|
|
24
|
+
name,
|
|
25
|
+
value = $bindable(''),
|
|
26
|
+
class: className,
|
|
27
|
+
types,
|
|
28
|
+
handleCtrlSave,
|
|
29
|
+
onChange,
|
|
30
|
+
...props
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
if (props.default) {
|
|
34
|
+
value = props.default;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let editorContainer: HTMLDivElement;
|
|
38
|
+
let editorView: EditorView | null = null;
|
|
39
|
+
|
|
40
|
+
const getLanguageExtension = () => {
|
|
41
|
+
switch (type) {
|
|
42
|
+
case 'javascript':
|
|
43
|
+
case 'typescript':
|
|
44
|
+
case 'json':
|
|
45
|
+
return javascript();
|
|
46
|
+
case 'sql':
|
|
47
|
+
return sql();
|
|
48
|
+
default:
|
|
49
|
+
return javascript();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const createEditor = () => {
|
|
54
|
+
if (!editorContainer) return;
|
|
55
|
+
|
|
56
|
+
const extensions = [
|
|
57
|
+
basicSetup,
|
|
58
|
+
getLanguageExtension(),
|
|
59
|
+
EditorView.updateListener.of((update) => {
|
|
60
|
+
if (update.docChanged) {
|
|
61
|
+
const newValue = update.state.doc.toString();
|
|
62
|
+
value = newValue;
|
|
63
|
+
onChange?.(newValue);
|
|
64
|
+
}
|
|
65
|
+
}),
|
|
66
|
+
EditorView.theme({
|
|
67
|
+
'&': {
|
|
68
|
+
backgroundColor: 'transparent',
|
|
69
|
+
},
|
|
70
|
+
'.cm-gutters': {
|
|
71
|
+
backgroundColor: 'transparent',
|
|
72
|
+
border: 'none',
|
|
73
|
+
},
|
|
74
|
+
'.cm-content': {
|
|
75
|
+
paddingTop: '10px',
|
|
76
|
+
paddingBottom: '1px',
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
// Add Ctrl+S / Cmd+S handler if provided
|
|
82
|
+
if (handleCtrlSave) {
|
|
83
|
+
extensions.push(
|
|
84
|
+
keymap.of([
|
|
85
|
+
{
|
|
86
|
+
key: 'Mod-s',
|
|
87
|
+
run: () => {
|
|
88
|
+
handleCtrlSave();
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
])
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const state = EditorState.create({
|
|
97
|
+
doc: value,
|
|
98
|
+
extensions
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
editorView = new EditorView({
|
|
102
|
+
state,
|
|
103
|
+
parent: editorContainer
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const updateEditor = () => {
|
|
108
|
+
if (!editorView) return;
|
|
109
|
+
|
|
110
|
+
const currentValue = editorView.state.doc.toString();
|
|
111
|
+
if (currentValue !== value) {
|
|
112
|
+
editorView.dispatch({
|
|
113
|
+
changes: {
|
|
114
|
+
from: 0,
|
|
115
|
+
to: currentValue.length,
|
|
116
|
+
insert: value
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
onMount(() => {
|
|
123
|
+
createEditor();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
onDestroy(() => {
|
|
127
|
+
editorView?.destroy();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
$effect(() => {
|
|
131
|
+
updateEditor();
|
|
132
|
+
});
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<div class={cn('resize-y rounded-md border bg-muted/30 h-60', className)}>
|
|
136
|
+
<div bind:this={editorContainer} class="h-full w-full pl-2" />
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<style>
|
|
140
|
+
:global(.cm-editor) {
|
|
141
|
+
height: 100%;
|
|
142
|
+
font-size: 14px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:global(.cm-scroller) {
|
|
146
|
+
overflow: auto;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
:global(.cm-focused) {
|
|
150
|
+
outline: none !important;
|
|
151
|
+
}
|
|
152
|
+
</style>
|