@lobb-js/studio 0.1.31 → 0.1.33

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 (81) hide show
  1. package/package.json +24 -14
  2. package/src/{Studio.svelte → lib/components/Studio.svelte} +8 -8
  3. package/src/lib/components/dataTable/childRecords.svelte +1 -1
  4. package/src/lib/components/detailView/create/children.svelte +1 -1
  5. package/src/lib/components/detailView/create/createDetailView.svelte +1 -1
  6. package/src/lib/components/detailView/fieldInput.svelte +1 -1
  7. package/src/lib/components/detailView/update/children.svelte +1 -1
  8. package/src/lib/components/detailView/update/updateDetailView.svelte +1 -1
  9. package/src/lib/components/extensionsComponents.svelte +1 -2
  10. package/src/lib/components/miniSidebar.svelte +1 -1
  11. package/{vite-plugin-contextual-lib.js → vite-plugins/contextual-lib-alias.js} +2 -7
  12. package/vite-plugins/index.js +21 -0
  13. package/vite-plugins/studio-source-resolver.js +41 -0
  14. package/.env.example +0 -1
  15. package/.storybook/main.ts +0 -31
  16. package/.storybook/preview.ts +0 -21
  17. package/.storybook/vitest.setup.ts +0 -7
  18. package/components.json +0 -16
  19. package/docker-entrypoint.sh +0 -7
  20. package/dockerfile +0 -27
  21. package/index.html +0 -13
  22. package/public/lobb.svg +0 -15
  23. package/src/app.css +0 -121
  24. package/src/components-export.ts +0 -21
  25. package/src/extensions/extension.types.ts +0 -93
  26. package/src/extensions/extensionUtils.ts +0 -192
  27. package/src/lib/Lobb.ts +0 -241
  28. package/src/lib/eventSystem.ts +0 -38
  29. package/src/lib/index.ts +0 -40
  30. package/src/lib/store.svelte.ts +0 -21
  31. package/src/lib/store.types.ts +0 -28
  32. package/src/lib/utils.ts +0 -84
  33. package/src/main.ts +0 -18
  34. package/src/routes/collections/collection.svelte +0 -46
  35. package/src/routes/collections/collections.svelte +0 -43
  36. package/src/routes/data_model/dataModel.svelte +0 -40
  37. package/src/routes/data_model/flow.css +0 -22
  38. package/src/routes/data_model/flow.svelte +0 -82
  39. package/src/routes/data_model/syncManager.svelte +0 -93
  40. package/src/routes/data_model/utils.ts +0 -35
  41. package/src/routes/extensions/extension.svelte +0 -16
  42. package/src/routes/home.svelte +0 -36
  43. package/src/routes/workflows/workflows.svelte +0 -135
  44. package/src/stories/Configure.mdx +0 -364
  45. package/src/stories/assets/accessibility.png +0 -0
  46. package/src/stories/assets/accessibility.svg +0 -1
  47. package/src/stories/assets/addon-library.png +0 -0
  48. package/src/stories/assets/assets.png +0 -0
  49. package/src/stories/assets/avif-test-image.avif +0 -0
  50. package/src/stories/assets/context.png +0 -0
  51. package/src/stories/assets/discord.svg +0 -1
  52. package/src/stories/assets/docs.png +0 -0
  53. package/src/stories/assets/figma-plugin.png +0 -0
  54. package/src/stories/assets/github.svg +0 -1
  55. package/src/stories/assets/share.png +0 -0
  56. package/src/stories/assets/styling.png +0 -0
  57. package/src/stories/assets/testing.png +0 -0
  58. package/src/stories/assets/theming.png +0 -0
  59. package/src/stories/assets/tutorials.svg +0 -1
  60. package/src/stories/assets/youtube.svg +0 -1
  61. package/src/stories/detailView/detailViewForm.stories.svelte +0 -79
  62. package/src/stories/examples/Button.stories.svelte +0 -31
  63. package/src/stories/examples/Button.svelte +0 -30
  64. package/src/stories/examples/Header.stories.svelte +0 -26
  65. package/src/stories/examples/Header.svelte +0 -45
  66. package/src/stories/examples/Page.stories.svelte +0 -29
  67. package/src/stories/examples/Page.svelte +0 -70
  68. package/src/stories/examples/button.css +0 -30
  69. package/src/stories/examples/header.css +0 -32
  70. package/src/stories/examples/page.css +0 -68
  71. package/src/vite-env.d.ts +0 -2
  72. package/svelte.config.js +0 -7
  73. package/todo.md +0 -24
  74. package/tsconfig.app.json +0 -25
  75. package/tsconfig.json +0 -14
  76. package/tsconfig.node.json +0 -24
  77. package/vite.build.svelte.config.ts +0 -18
  78. package/vite.config.ts +0 -84
  79. package/vite.extension.config.ts +0 -81
  80. package/vite_utils.ts +0 -28
  81. package/vitest.shims.d.ts +0 -1
package/src/lib/utils.ts DELETED
@@ -1,84 +0,0 @@
1
- import { clsx, type ClassValue } from "clsx";
2
- import { twMerge } from "tailwind-merge";
3
-
4
- import { fileOpen } from 'browser-fs-access';
5
- import { MediaQuery } from 'svelte/reactivity';
6
- import { ctx } from "./store.svelte";
7
-
8
- export function cn(...inputs: ClassValue[]) {
9
- return twMerge(clsx(inputs));
10
- }
11
-
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
- export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
16
- export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
17
- export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
18
-
19
-
20
- export const mediaQueries = {
21
- sm: new MediaQuery('min-width: 640px'),
22
- md: new MediaQuery('min-width: 768px'),
23
- lg: new MediaQuery('min-width: 1024px'),
24
- xl: new MediaQuery('min-width: 1280px'),
25
- '2xl': new MediaQuery('min-width: 1536px'),
26
- }
27
-
28
- export async function getFileFromUser() {
29
- return await fileOpen()
30
- };
31
-
32
- export function getFieldRelation(collectionName: string, fieldName: string) {
33
- const relations = ctx.meta.relations;
34
- for (let index = 0; index < relations.length; index++) {
35
- const relation = relations[index];
36
- if (relation.from.collection === collectionName && relation.from.field === fieldName) {
37
- return relation;
38
- }
39
- }
40
- return null;
41
- };
42
-
43
- export function getDiscriminatorFieldRelation(collectionName: string, fieldName: string) {
44
- const relations = ctx.meta.relations;
45
- for (let index = 0; index < relations.length; index++) {
46
- const relation = relations[index];
47
- if (relation.from.collection === collectionName && relation.from.discriminator === fieldName) {
48
- return relation;
49
- }
50
- }
51
- return null;
52
- };
53
-
54
- export function recordHasChildrean(collectionName: string) {
55
- for (let index = 0; index < ctx.meta.relations.length; index++) {
56
- const relation = ctx.meta.relations[index];
57
- if (relation.to.collection === collectionName) {
58
- return true;
59
- }
60
- }
61
- return false;
62
- };
63
-
64
- export function calculateDrawerWidth() {
65
- const backgroundDrawerButtons = document.querySelectorAll(".backgroundDrawerButton");
66
- const drawersCount = Array.from(backgroundDrawerButtons).length;
67
- const width = 672 - (30 * drawersCount);
68
- return width;
69
- };
70
-
71
- export function getChangedProperties(oldObj: Record<string, any>, newObj: Record<string, any>) {
72
- const changes: Record<string, any> = {};
73
- for (const key of Object.keys(newObj)) {
74
- if (oldObj[key] !== newObj[key]) {
75
- changes[key] = newObj[key];
76
- }
77
- }
78
- return changes;
79
- }
80
-
81
- export function parseFunction(functionString: string) {
82
- const functionObj = new Function("return " + functionString)();
83
- return functionObj;
84
- };
package/src/main.ts DELETED
@@ -1,18 +0,0 @@
1
- import "./app.css";
2
-
3
- import { mount } from 'svelte'
4
- import Studio from './Studio.svelte'
5
-
6
- declare global {
7
- interface Window {
8
- APP_ENV: {
9
- LOBB_URL: string
10
- }
11
- }
12
- }
13
-
14
- const app = mount(Studio, {
15
- target: document.getElementById('app')!,
16
- })
17
-
18
- export default app
@@ -1,46 +0,0 @@
1
- <script>
2
- import { CircleSlash2 } from "lucide-svelte";
3
- import DataTable from "$lib/components/dataTable/dataTable.svelte";
4
- import SidebarTrigger from "$lib/components/sidebar/sidebarTrigger.svelte";
5
- import { ctx } from "$lib/store.svelte";
6
- import Singletone from "$lib/components/singletone.svelte";
7
-
8
- let { collectionName } = $props();
9
- let isSingletonCollection = $derived(ctx.meta.collections[collectionName].singleton);
10
-
11
- let containerWidth = $state();
12
- </script>
13
-
14
- <div bind:clientWidth={containerWidth} class="h-full">
15
- {#if collectionName}
16
- {#if isSingletonCollection}
17
- <Singletone collectionName={collectionName} />
18
- {:else}
19
- <DataTable
20
- {collectionName}
21
- tableProps={{
22
- parentWidth: containerWidth,
23
- }}
24
- >
25
- {#snippet headerLeft()}
26
- <SidebarTrigger />
27
- {/snippet}
28
- </DataTable>
29
- {/if}
30
- {:else}
31
- <div
32
- class="relative flex h-full w-full flex-col items-center justify-center gap-4 text-muted-foreground"
33
- >
34
- <CircleSlash2 class="opacity-50" size="50" />
35
- <div class="flex flex-col items-center justify-center">
36
- <div>No collection selected</div>
37
- <div class="text-xs">
38
- Select a collection to view its entries or create new ones
39
- </div>
40
- </div>
41
- <div class="absolute top-0 left-0 p-2.5">
42
- <SidebarTrigger />
43
- </div>
44
- </div>
45
- {/if}
46
- </div>
@@ -1,43 +0,0 @@
1
- <script lang="ts">
2
- import type { SideBarData } from "$lib/components/sidebar/sidebarElements.svelte";
3
- import Sidebar from "$lib/components/sidebar/sidebar.svelte";
4
- import { ctx } from "$lib/store.svelte";
5
- import Collection from "./collection.svelte";
6
- import { Table } from "lucide-svelte";
7
-
8
- let { collectionName } = $props();
9
-
10
- const collectionsList = $state(getCollectionsList());
11
-
12
- function getCollectionsList() {
13
- const collections = ctx.meta.collections;
14
- let collectionsOwners: SideBarData = Object.entries(collections).map(
15
- ([collectionName, collectionValue]) => {
16
- return {
17
- name: collectionName,
18
- path: collectionValue.category ?? collectionValue.owner,
19
- icon: Table,
20
- href: `/collections/${collectionName}`,
21
- };
22
- },
23
- );
24
-
25
- // updating the path from '__project' and '__core' to a more readable names
26
- collectionsOwners = collectionsOwners.map((item) => {
27
- if (item.path === "__project") {
28
- item.path = "project";
29
- } else if (item.path === "__core") {
30
- item.path = "core";
31
- }
32
- return item;
33
- });
34
-
35
- return collectionsOwners;
36
- }
37
- </script>
38
-
39
- <Sidebar title="Collections" data={collectionsList}>
40
- {#key collectionName}
41
- <Collection {collectionName} />
42
- {/key}
43
- </Sidebar>
@@ -1,40 +0,0 @@
1
- <script lang="ts">
2
- import { SvelteFlowProvider } from "@xyflow/svelte";
3
- import Flow from "./flow.svelte";
4
- import Sidebar from "$lib/components/sidebar/sidebar.svelte";
5
- import { location } from "@wjfe/n-savant";
6
- import SyncManager from "./syncManager.svelte";
7
- import SidebarTrigger from "$lib/components/sidebar/sidebarTrigger.svelte";
8
-
9
- const currentPage = $derived(location.url.pathname.split("/")[2]);
10
- </script>
11
-
12
- <Sidebar
13
- title="Data Model"
14
- showSearch={false}
15
- data={[
16
- {
17
- name: "graph",
18
- href: "/datamodel/graph",
19
- },
20
- {
21
- name: "query_editor",
22
- href: "/datamodel/query_editor",
23
- },
24
- ]}
25
- >
26
- <div class="relative h-full w-full">
27
- {#if currentPage === "graph"}
28
- <SvelteFlowProvider>
29
- <div style:width="100%" style:height="100%">
30
- <Flow />
31
- </div>
32
- </SvelteFlowProvider>
33
- {:else if currentPage === "query_editor"}
34
- <SyncManager />
35
- {/if}
36
- <div class="absolute top-0 left-0 p-2.5">
37
- <SidebarTrigger />
38
- </div>
39
- </div>
40
- </Sidebar>
@@ -1,22 +0,0 @@
1
- .svelte-flow {
2
- --xy-edge-stroke-default: hsl(var(--muted-foreground));
3
- --xy-edge-stroke-selected-default: hsl(var(--primary));
4
- --xy-connectionline-stroke-default: hsl(var(--primary));
5
- --xy-attribution-background-color-default: transparent;
6
- --xy-minimap-background-color-default: hsl(var(--background));
7
- --xy-minimap-mask-background-color-default: hsl(var(--primary) / 0.1);
8
- --xy-minimap-node-background-color-default: hsl(var(--primary) / 0.2);
9
- --xy-background-color-default: hsl(var(--soft));
10
- --xy-background-pattern-dots-color-default: hsl(var(--muted-foreground));
11
- --xy-background-pattern-lines-color-default: hsl(var(--background));
12
- --xy-background-pattern-cross-color-default: hsl(var(--soft));
13
- --xy-node-border-default: 1px solid hsl(var(--primary) / 0.25);
14
- --xy-node-background-color-default: hsl(var(--background));
15
- --xy-node-boxshadow-selected-default: 0 0 0 0.5px hsl(var(--primary) / 0.5);
16
- --xy-handle-background-color-default: hsl(var(--primary));
17
- --xy-handle-border-color-default: hsl(var(--background));
18
- --xy-controls-button-background-color-default: hsl(var(--background));
19
- --xy-controls-button-background-color-hover-default: hsl(var(--muted));
20
- --xy-controls-button-border-color-default: hsl(var(--muted));
21
- --xy-edge-label-background-color-default: hsl(var(--background));
22
- }
@@ -1,82 +0,0 @@
1
- <script lang="ts">
2
- import "@xyflow/svelte/dist/style.css";
3
- import "./flow.css";
4
-
5
- import type { Node, Edge } from "@xyflow/svelte";
6
-
7
- import {
8
- SvelteFlow,
9
- Background,
10
- MiniMap,
11
- Controls,
12
- useSvelteFlow,
13
- } from "@xyflow/svelte";
14
- import { getLayoutedElements } from "./utils";
15
- import { onMount } from "svelte";
16
- import { ctx } from "$lib/store.svelte";
17
-
18
- const { fitView } = useSvelteFlow();
19
-
20
- let nodes = $state.raw<Node[]>(generateNodes());
21
- let edges = $state.raw<Edge[]>(generateEdges());
22
-
23
- onMount(() => {
24
- setTimeout(() => {
25
- onLayout();
26
- }, 0);
27
- });
28
-
29
- function generateNodes() {
30
- const localNodes: Node[] = [];
31
-
32
- for (const [collectionName, collectionValue] of Object.entries(
33
- ctx.meta.collections,
34
- )) {
35
- if (collectionValue.owner !== "__project") {
36
- continue;
37
- }
38
-
39
- localNodes.push({
40
- id: collectionName,
41
- data: { label: collectionName },
42
- position: { x: 0, y: 0 },
43
- });
44
- }
45
-
46
- return localNodes;
47
- }
48
-
49
- function generateEdges() {
50
- const localEdges: Edge[] = [];
51
-
52
- const relations = ctx.meta.relations;
53
- for (let index = 0; index < relations.length; index++) {
54
- const relation = relations[index];
55
- localEdges.push({
56
- id: `${relation.from.collection}_${relation.to.collection}`,
57
- source: relation.from.collection,
58
- target: relation.to.collection,
59
- animated: true,
60
- });
61
- }
62
-
63
- return localEdges;
64
- }
65
-
66
- function onLayout() {
67
- const layouted = getLayoutedElements(nodes, edges);
68
-
69
- nodes = [...layouted.nodes];
70
- edges = [...layouted.edges];
71
-
72
- fitView({
73
- padding: 0.5,
74
- });
75
- }
76
- </script>
77
-
78
- <SvelteFlow bind:nodes bind:edges>
79
- <Background />
80
- <MiniMap />
81
- <Controls />
82
- </SvelteFlow>
@@ -1,93 +0,0 @@
1
- <script lang="ts">
2
- import DiffViewer from "$lib/components/diffViewer.svelte";
3
- import { ctx } from "$lib/store.svelte";
4
- import { onMount } from "svelte";
5
- import stringify from "json-stable-stringify";
6
- import MonacoEditor from "$lib/components/monacoEditor.svelte";
7
- import Table from "$lib/components/dataTable/table.svelte";
8
- import Button from "$lib/components/ui/button/button.svelte";
9
- import { LoaderCircle, SendHorizontal } from "lucide-svelte";
10
- import { lobb } from "$lib";
11
-
12
- let configSchema: string = $state("");
13
- let dbSchema: string = $state("");
14
- let sqlPrompt = $state("");
15
- let sqlResult = $state([]);
16
-
17
- onMount(() => {
18
- loadSchemas();
19
- });
20
-
21
- async function loadSchemas() {
22
- configSchema = "";
23
- dbSchema = "";
24
- const response = await fetch(`${ctx.lobbUrl}/api/schema/diff`);
25
- const result = await response.json();
26
- configSchema = stringify(result.dbSchema, {
27
- space: 2,
28
- }) as string;
29
- dbSchema = stringify(result.configSchema, {
30
- space: 2,
31
- }) as string;
32
- }
33
-
34
- async function handleExecute() {
35
- const response = await lobb.createOne("core_query", {
36
- query: sqlPrompt,
37
- });
38
- const result = await response.json();
39
- sqlResult = result.data;
40
- loadSchemas();
41
- }
42
- </script>
43
-
44
- <div class="h-[50%] border-b">
45
- {#if configSchema && dbSchema}
46
- <DiffViewer
47
- type="json"
48
- original={configSchema}
49
- modified={dbSchema}
50
- class="h-full rounded-none border-0"
51
- />
52
- {:else}
53
- <div class="flex justify-center items-center h-full gap-2">
54
- <LoaderCircle class="animate-spin" />
55
- <div>loading...</div>
56
- </div>
57
- {/if}
58
- </div>
59
- <div class="flex h-[50%] w-full">
60
- <div class="h-full flex-1 flex flex-col border-r">
61
- <div
62
- class="h-10 flex items-center px-2 bg-background border-b justify-between"
63
- >
64
- <div>Query Editor</div>
65
- <Button
66
- class="h-7 px-3 text-xs font-normal"
67
- Icon={SendHorizontal}
68
- onclick={handleExecute}
69
- >
70
- Execute
71
- </Button>
72
- </div>
73
- <MonacoEditor
74
- type="sql"
75
- name="prompt"
76
- bind:value={sqlPrompt}
77
- class="flex-1 rounded-none border-0"
78
- />
79
- </div>
80
- <div class="flex-1">
81
- {#if Array.isArray(sqlResult) && sqlResult.length}
82
- <Table
83
- data={sqlResult}
84
- showLastRowBorder={true}
85
- showLastColumnBorder={true}
86
- />
87
- {:else}
88
- <div class="flex flex-1 h-full items-center justify-center">
89
- No results
90
- </div>
91
- {/if}
92
- </div>
93
- </div>
@@ -1,35 +0,0 @@
1
- import Dagre from '@dagrejs/dagre';
2
-
3
- export function getLayoutedElements(nodes: any[], edges: any[]) {
4
- const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
5
- g.setGraph({ rankdir: "LR" });
6
-
7
- edges.forEach((edge) => g.setEdge(edge.source, edge.target));
8
- nodes.forEach((node) => {
9
- return g.setNode(node.id, {
10
- ...node,
11
- width: node.measured?.width ?? 0,
12
- height: node.measured?.height ?? 0,
13
- });
14
- });
15
-
16
- Dagre.layout(g);
17
-
18
- return {
19
- nodes: nodes.map((node) => {
20
- const position = g.node(node.id);
21
- // We are shifting the dagre node position (anchor=center center) to the top left
22
- // so it matches the Svelte Flow node anchor point (top left).
23
- const x = position.x - (node.measured?.width ?? 0) / 2;
24
- const y = position.y - (node.measured?.height ?? 0) / 2;
25
-
26
- return {
27
- ...node,
28
- position: { x, y },
29
- targetPosition: "left",
30
- sourcePosition: "right",
31
- };
32
- }),
33
- edges,
34
- };
35
- }
@@ -1,16 +0,0 @@
1
- <script>
2
- import ExtensionsComponents from "$lib/components/extensionsComponents.svelte";
3
- import { getExtensionUtils } from "../../extensions/extensionUtils";
4
-
5
- let { extension, page } = $props();
6
- </script>
7
-
8
- <div class="grid overflow-auto bg-background">
9
- {#key extension && page}
10
- <ExtensionsComponents
11
- name="pages.{page}"
12
- utils={getExtensionUtils()}
13
- filterByExtensions={[extension]}
14
- />
15
- {/key}
16
- </div>
@@ -1,36 +0,0 @@
1
- <script>
2
- import Button from "$lib/components/ui/button/button.svelte";
3
- import { ctx } from "$lib/store.svelte";
4
- import { location } from "@wjfe/n-savant";
5
- import { ArrowRight } from "lucide-svelte";
6
- </script>
7
-
8
- <div class="flex flex-col">
9
- <div
10
- class="flex flex-1 w-full flex-col items-center justify-center gap-4 text-muted-foreground"
11
- >
12
- <div class="flex flex-col items-center justify-center p-4">
13
- <div class="text-3xl">Welcome to Lobb!</div>
14
- <div class="text-xs text-center">
15
- Your journey starts here. Explore and make the most of your
16
- experience.
17
- </div>
18
- </div>
19
- <div class="flex flex-col items-center justify-center">
20
- <Button
21
- Icon={ArrowRight}
22
- variant="outline"
23
- class="h-7 px-3 text-xs font-normal"
24
- onclick={() => location.navigate("/collections")}
25
- >
26
- Go to collections
27
- </Button>
28
- </div>
29
- </div>
30
- <div class="flex justify-end p-2 text-xs text-muted-foreground/50">
31
- <div class="flex flex-col text-end">
32
- <div>studio: v{ctx.studioVersion}</div>
33
- <div>core: v{ctx.meta.version}</div>
34
- </div>
35
- </div>
36
- </div>
@@ -1,135 +0,0 @@
1
- <script lang="ts">
2
- import type { SideBarData } from "$lib/components/sidebar/sidebarElements.svelte";
3
- import WorkflowEditor, {
4
- type WorkflowEntry,
5
- } from "$lib/components/workflowEditor.svelte";
6
- import { lobb } from "$lib";
7
- import Sidebar from "$lib/components/sidebar/sidebar.svelte";
8
- import Button from "$lib/components/ui/button/button.svelte";
9
- import { ctx } from "$lib/store.svelte";
10
- import { location } from "@wjfe/n-savant";
11
- import { CircleSlash2, Plus, Trash2 } from "lucide-svelte";
12
- import { onMount } from "svelte";
13
- import { showDialog } from "$lib/components/confirmationDialog/store.svelte";
14
- import SidebarTrigger from "$lib/components/sidebar/sidebarTrigger.svelte";
15
-
16
- let { workflowName } = $props();
17
-
18
- let sidebarData: SideBarData | null = $state(null);
19
- let workflowEntry: WorkflowEntry | null = $state(null);
20
-
21
- onMount(async () => {
22
- getSidebarData();
23
- });
24
-
25
- $effect(() => {
26
- fetchWorkflowData(workflowName);
27
- });
28
-
29
- async function getSidebarData() {
30
- const response = await lobb.findAll("core_workflows", {});
31
- const result = await response.json();
32
- const workflows: any[] = result.data;
33
- sidebarData = workflows.map((workflow) => {
34
- return {
35
- name: workflow.name,
36
- path: workflow.directory,
37
- onclick: () => {
38
- location.navigate(`/workflows/${workflow.name}`);
39
- },
40
- meta: {
41
- id: workflow.id,
42
- },
43
- };
44
- });
45
- }
46
-
47
- async function fetchWorkflowData(workflowName: string) {
48
- if (workflowName && workflowName !== "new") {
49
- const response = await lobb.findAll("core_workflows", {
50
- filter: {
51
- name: workflowName,
52
- },
53
- });
54
- const result = await response.json();
55
- const workflow = result.data[0];
56
- workflowEntry = workflow;
57
- } else {
58
- const workflowHandlerDefaultValue =
59
- ctx.meta.collections.core_workflows.fields.handler
60
- .pre_processors.default;
61
- workflowEntry = {
62
- name: "",
63
- event_name: "",
64
- handler: workflowHandlerDefaultValue,
65
- directory: "",
66
- };
67
- }
68
- }
69
-
70
- async function handleWorkflowDelete(
71
- workflowName: string,
72
- workflowId: string,
73
- ) {
74
- const result = await showDialog(
75
- "Are you sure?",
76
- "This will delete the Workflow you selected.",
77
- );
78
- if (result) {
79
- await lobb.deleteOne("core_workflows", workflowId);
80
- getSidebarData();
81
- if (workflowEntry && workflowName === workflowEntry.name) {
82
- location.navigate("/workflows");
83
- }
84
- }
85
- }
86
- </script>
87
-
88
- <Sidebar title="Workflows" data={sidebarData}>
89
- {#snippet belowSearch()}
90
- <div class="pb-4 px-2">
91
- <Button
92
- class="h-7 px-3 text-xs font-normal w-full"
93
- variant="outline"
94
- onclick={() => location.navigate("/workflows/new")}
95
- Icon={Plus}
96
- >
97
- Create a Workflow
98
- </Button>
99
- </div>
100
- {/snippet}
101
- {#snippet elementRightSide(element)}
102
- <Button
103
- class="h-6 w-6 text-muted-foreground hover:bg-transparent"
104
- variant="ghost"
105
- size="icon"
106
- onclick={() => handleWorkflowDelete(element.name, element.meta?.id)}
107
- Icon={Trash2}
108
- ></Button>
109
- {/snippet}
110
- <div class="relative h-full w-full">
111
- {#if workflowName === undefined}
112
- <div
113
- class="flex h-full w-full flex-col items-center justify-center gap-4 text-muted-foreground"
114
- >
115
- <CircleSlash2 class="opacity-50" size="50" />
116
- <div class="flex flex-col items-center justify-center">
117
- <div>No workflow selected</div>
118
- <div class="text-xs">
119
- Select a workflow to edit it or create new ones
120
- </div>
121
- </div>
122
- </div>
123
- {:else if workflowEntry}
124
- {#key workflowEntry}
125
- <WorkflowEditor
126
- bind:workflow={workflowEntry}
127
- refreshSidebar={getSidebarData}
128
- />
129
- {/key}
130
- {/if}
131
- <div class="absolute top-0 left-0 p-2.5">
132
- <SidebarTrigger />
133
- </div>
134
- </div>
135
- </Sidebar>