@lobb-js/studio 0.25.0 → 0.26.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/dataTable/dataTable.svelte +8 -6
- package/dist/components/dataTable/dataTable.svelte.d.ts +1 -0
- package/dist/components/dataTable/listViewChildren.svelte +99 -0
- package/dist/components/dataTable/listViewChildren.svelte.d.ts +9 -0
- package/dist/components/detailView/create/createManyView.svelte +2 -2
- package/dist/components/detailView/update/detailViewChildren.svelte +77 -0
- package/dist/components/detailView/update/detailViewChildren.svelte.d.ts +7 -0
- package/dist/components/detailView/update/updateDetailView.svelte +2 -2
- package/dist/components/routes/collections/collections.svelte +44 -23
- package/dist/components/routes/data_model/dataModel.svelte +2 -8
- package/dist/components/routes/workflows/workflows.svelte +24 -11
- package/dist/components/sidebar/sidebar.svelte +12 -5
- package/dist/components/sidebar/sidebar.svelte.d.ts +1 -2
- package/dist/components/sidebar/sidebarElements.svelte +50 -75
- package/dist/components/sidebar/sidebarElements.svelte.d.ts +10 -3
- package/package.json +2 -2
- package/src/lib/components/dataTable/dataTable.svelte +8 -6
- package/src/lib/components/dataTable/listViewChildren.svelte +99 -0
- package/src/lib/components/detailView/create/createManyView.svelte +2 -2
- package/src/lib/components/detailView/update/detailViewChildren.svelte +77 -0
- package/src/lib/components/detailView/update/updateDetailView.svelte +2 -2
- package/src/lib/components/routes/collections/collections.svelte +44 -23
- package/src/lib/components/routes/data_model/dataModel.svelte +2 -8
- package/src/lib/components/routes/workflows/workflows.svelte +24 -11
- package/src/lib/components/sidebar/sidebar.svelte +12 -5
- package/src/lib/components/sidebar/sidebarElements.svelte +50 -75
- package/dist/components/dataTable/childRecords.svelte +0 -142
- package/dist/components/dataTable/childRecords.svelte.d.ts +0 -9
- package/dist/components/detailView/update/children.svelte +0 -96
- package/dist/components/detailView/update/children.svelte.d.ts +0 -7
- package/src/lib/components/dataTable/childRecords.svelte +0 -142
- package/src/lib/components/detailView/update/children.svelte +0 -96
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { getCollectionColumns, getCollectionParamsFields } from "./utils";
|
|
8
8
|
import { Pencil, Trash } from "lucide-svelte";
|
|
9
9
|
import * as icons from "lucide-svelte";
|
|
10
|
-
import
|
|
10
|
+
import ListViewChildren from "./listViewChildren.svelte";
|
|
11
11
|
import FieldCell from "./fieldCell.svelte";
|
|
12
12
|
import Skeleton from "../ui/skeleton/skeleton.svelte";
|
|
13
13
|
import Button from "../ui/button/button.svelte";
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
interface Props {
|
|
26
26
|
collectionName: string;
|
|
27
27
|
filter?: any;
|
|
28
|
+
searchParams?: Record<string, any>;
|
|
28
29
|
showHeader?: boolean;
|
|
29
30
|
showFooter?: boolean;
|
|
30
31
|
unifiedBgColor?: "bg-muted/30" | "bg-background";
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
let {
|
|
37
38
|
collectionName,
|
|
38
39
|
filter,
|
|
40
|
+
searchParams,
|
|
39
41
|
showHeader = true,
|
|
40
42
|
showFooter = true,
|
|
41
43
|
unifiedBgColor,
|
|
@@ -57,6 +59,7 @@
|
|
|
57
59
|
sort: {},
|
|
58
60
|
limit: "100",
|
|
59
61
|
page: 1,
|
|
62
|
+
...searchParams,
|
|
60
63
|
});
|
|
61
64
|
|
|
62
65
|
$effect(() => {
|
|
@@ -73,10 +76,9 @@
|
|
|
73
76
|
);
|
|
74
77
|
let dataTableContainerWidth: number = $state(0);
|
|
75
78
|
let dataTableWidth: number = $state(0);
|
|
76
|
-
const doesCollectionHasChildren =
|
|
77
|
-
ctx.meta.
|
|
78
|
-
(
|
|
79
|
-
),
|
|
79
|
+
const doesCollectionHasChildren = $derived(
|
|
80
|
+
(ctx.meta.collections[collectionName]?.children ?? [])
|
|
81
|
+
.some((c: any) => c.type === "fk" || c.type === "m2m")
|
|
80
82
|
);
|
|
81
83
|
|
|
82
84
|
// requests the data from the server when the params is changed
|
|
@@ -232,7 +234,7 @@
|
|
|
232
234
|
/>
|
|
233
235
|
{/snippet}
|
|
234
236
|
{#snippet collapsible(entry)}
|
|
235
|
-
<
|
|
237
|
+
<ListViewChildren
|
|
236
238
|
{collectionName}
|
|
237
239
|
recordId={entry.id}
|
|
238
240
|
width={dataTableWidth > dataTableContainerWidth
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getStudioContext } from "../../context";
|
|
3
|
+
import { ChevronRight, Table, Plus } from "lucide-svelte";
|
|
4
|
+
import DataTable from "./dataTable.svelte";
|
|
5
|
+
import CreateDetailViewButton from "../detailView/create/createDetailViewButton.svelte";
|
|
6
|
+
import ExtensionsComponents from "../extensionsComponents.svelte";
|
|
7
|
+
import { getExtensionUtils } from "../../extensions/extensionUtils";
|
|
8
|
+
|
|
9
|
+
const { ctx, lobb } = getStudioContext();
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
collectionName: string;
|
|
13
|
+
recordId: string;
|
|
14
|
+
width: number;
|
|
15
|
+
unifiedBgColor?: "bg-muted/30" | "bg-background";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let { collectionName, recordId, width, unifiedBgColor }: Props = $props();
|
|
19
|
+
|
|
20
|
+
const children = (ctx.meta.collections[collectionName]?.children ?? [])
|
|
21
|
+
.filter((c: any) => c.type === "fk" || c.type === "m2m");
|
|
22
|
+
|
|
23
|
+
let expandedRows: boolean[] = $state(new Array(children.length).fill(false));
|
|
24
|
+
let refreshDataTable = $state(true);
|
|
25
|
+
let tableHeaderWidth = $state(0);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class="flex" style="width: {width}px;">
|
|
29
|
+
<div
|
|
30
|
+
class="flex justify-center border-r {unifiedBgColor ? unifiedBgColor : 'bg-background'}"
|
|
31
|
+
style="width: 40px"
|
|
32
|
+
></div>
|
|
33
|
+
<div class="flex-1 flex flex-col">
|
|
34
|
+
{#each children as child, index}
|
|
35
|
+
{@const lastRow = children.length - 1 === index}
|
|
36
|
+
<div class="overflow-hidden {unifiedBgColor ? unifiedBgColor : 'bg-background'}">
|
|
37
|
+
<div
|
|
38
|
+
bind:clientWidth={tableHeaderWidth}
|
|
39
|
+
class="flex justify-between items-center gap-2 text-sm h-10 {expandedRows[index] || !lastRow ? 'border-b' : ''}"
|
|
40
|
+
>
|
|
41
|
+
<button
|
|
42
|
+
class="flex gap-2 px-2 flex-1 h-full items-center"
|
|
43
|
+
onclick={() => { expandedRows[index] = !expandedRows[index]; }}
|
|
44
|
+
>
|
|
45
|
+
<ChevronRight
|
|
46
|
+
size="17.5"
|
|
47
|
+
class="text-muted-foreground transition-transform"
|
|
48
|
+
style={expandedRows[index] ? "transform: rotate(90deg);" : "transform: rotate(0deg);"}
|
|
49
|
+
/>
|
|
50
|
+
<Table size="17.5" class="text-muted-foreground" />
|
|
51
|
+
<div class="text-muted-foreground">{child.collection}</div>
|
|
52
|
+
</button>
|
|
53
|
+
{#if child.type === "fk"}
|
|
54
|
+
<div class="flex items-center px-2">
|
|
55
|
+
<CreateDetailViewButton
|
|
56
|
+
collectionName={child.collection}
|
|
57
|
+
variant="ghost"
|
|
58
|
+
class="h-7 px-3 text-xs font-normal"
|
|
59
|
+
Icon={Plus}
|
|
60
|
+
values={{ [child.field]: { id: recordId } }}
|
|
61
|
+
onSuccessfullSave={async () => { refreshDataTable = !refreshDataTable; }}
|
|
62
|
+
>
|
|
63
|
+
Create
|
|
64
|
+
</CreateDetailViewButton>
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
67
|
+
</div>
|
|
68
|
+
{#if expandedRows[index]}
|
|
69
|
+
<div class="flex max-h-96 overflow-auto {lastRow ? '' : 'border-b'}">
|
|
70
|
+
<div
|
|
71
|
+
class="border-r {unifiedBgColor ? unifiedBgColor : ''}"
|
|
72
|
+
style="width: 100vw; max-width: 40px"
|
|
73
|
+
></div>
|
|
74
|
+
<div class="flex-1" style="width: {tableHeaderWidth - 40}px;">
|
|
75
|
+
{#key refreshDataTable}
|
|
76
|
+
<ExtensionsComponents
|
|
77
|
+
name="listView.entry.children.{child.collection}"
|
|
78
|
+
collectionName={child.collection}
|
|
79
|
+
searchParams={{ children_of: collectionName, parent_id: recordId }}
|
|
80
|
+
utils={getExtensionUtils(lobb, ctx)}
|
|
81
|
+
>
|
|
82
|
+
<DataTable
|
|
83
|
+
collectionName={child.collection}
|
|
84
|
+
searchParams={{ children_of: collectionName, parent_id: recordId }}
|
|
85
|
+
showHeader={false}
|
|
86
|
+
showFooter={false}
|
|
87
|
+
showDelete={child.type === "fk"}
|
|
88
|
+
{unifiedBgColor}
|
|
89
|
+
tableProps={{ showLastRowBorder: false, showLastColumnBorder: false, showCheckboxes: false }}
|
|
90
|
+
/>
|
|
91
|
+
</ExtensionsComponents>
|
|
92
|
+
{/key}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
{/if}
|
|
96
|
+
</div>
|
|
97
|
+
{/each}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
collectionName: string;
|
|
3
|
+
recordId: string;
|
|
4
|
+
width: number;
|
|
5
|
+
unifiedBgColor?: "bg-muted/30" | "bg-background";
|
|
6
|
+
}
|
|
7
|
+
declare const ListViewChildren: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type ListViewChildren = ReturnType<typeof ListViewChildren>;
|
|
9
|
+
export default ListViewChildren;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import SelectRecord from "../../../components/selectRecord.svelte";
|
|
16
16
|
import FieldCell from "../../../components/dataTable/fieldCell.svelte";
|
|
17
17
|
import SubRecords from "./subRecords.svelte";
|
|
18
|
-
import
|
|
18
|
+
import ListViewChildren from "../../../components/dataTable/listViewChildren.svelte";
|
|
19
19
|
import { getStudioContext } from "../../../context";
|
|
20
20
|
|
|
21
21
|
const { ctx } = getStudioContext();
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
{/snippet}
|
|
233
233
|
{#snippet collapsible(entry, index)}
|
|
234
234
|
{#if entry.id}
|
|
235
|
-
<
|
|
235
|
+
<ListViewChildren
|
|
236
236
|
{collectionName}
|
|
237
237
|
recordId={entry.id}
|
|
238
238
|
width={tableWidth}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import DataTable from "../../../components/dataTable/dataTable.svelte";
|
|
3
|
+
import { getStudioContext } from "../../../context";
|
|
4
|
+
import { Link, Plus, TableIcon } from "lucide-svelte";
|
|
5
|
+
import CreateDetailViewButton from "../create/createDetailViewButton.svelte";
|
|
6
|
+
import ExtensionsComponents from "../../../components/extensionsComponents.svelte";
|
|
7
|
+
import { getExtensionUtils } from "../../../extensions/extensionUtils";
|
|
8
|
+
|
|
9
|
+
const { ctx, lobb } = getStudioContext();
|
|
10
|
+
|
|
11
|
+
interface LocalProp {
|
|
12
|
+
collectionName: string;
|
|
13
|
+
entry: any;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let { collectionName, entry }: LocalProp = $props();
|
|
17
|
+
|
|
18
|
+
const children = (ctx.meta.collections[collectionName]?.children ?? [])
|
|
19
|
+
.filter((c: any) => c.type === "fk" || c.type === "m2m");
|
|
20
|
+
|
|
21
|
+
const refresh: boolean[] = $state(new Array(children.length).fill(true));
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{#if children.length}
|
|
25
|
+
<div class="flex flex-col gap-4 border-t p-4">
|
|
26
|
+
<div class="flex items-center gap-2">
|
|
27
|
+
<Link size="17.5" />
|
|
28
|
+
<div>Sub Records</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="flex flex-col gap-4">
|
|
31
|
+
{#each children as child, index}
|
|
32
|
+
<ExtensionsComponents
|
|
33
|
+
name="detailView.update.subRecords.{child.collection}"
|
|
34
|
+
utils={getExtensionUtils(lobb, ctx)}
|
|
35
|
+
collectionName={child.collection}
|
|
36
|
+
searchParams={{ children_of: collectionName, parent_id: entry.id }}
|
|
37
|
+
class="bg-muted/30 border rounded-md overflow-hidden"
|
|
38
|
+
>
|
|
39
|
+
<div class="border rounded-md overflow-clip">
|
|
40
|
+
<div class="flex items-center justify-between px-2 h-10 bg-muted/30 border-b">
|
|
41
|
+
<div class="flex-1 flex h-full items-center gap-2">
|
|
42
|
+
<TableIcon class="text-muted-foreground" size="17.5" />
|
|
43
|
+
<div class="text-sm text-muted-foreground">{child.collection}</div>
|
|
44
|
+
</div>
|
|
45
|
+
{#if child.type === "fk"}
|
|
46
|
+
<div class="flex gap-2">
|
|
47
|
+
<CreateDetailViewButton
|
|
48
|
+
variant="ghost"
|
|
49
|
+
class="h-7 px-2 font-normal text-xs"
|
|
50
|
+
Icon={Plus}
|
|
51
|
+
collectionName={child.collection}
|
|
52
|
+
onSuccessfullSave={async () => { refresh[index] = !refresh[index]; }}
|
|
53
|
+
>
|
|
54
|
+
Create
|
|
55
|
+
</CreateDetailViewButton>
|
|
56
|
+
</div>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
<div class="max-h-72 overflow-auto rounded-md">
|
|
60
|
+
{#key refresh[index]}
|
|
61
|
+
<DataTable
|
|
62
|
+
collectionName={child.collection}
|
|
63
|
+
searchParams={{ children_of: collectionName, parent_id: entry.id }}
|
|
64
|
+
unifiedBgColor="bg-muted/30"
|
|
65
|
+
showHeader={false}
|
|
66
|
+
showFooter={false}
|
|
67
|
+
showDelete={child.type === "fk"}
|
|
68
|
+
tableProps={{ showLastColumnBorder: false, showLastRowBorder: false, showCheckboxes: false }}
|
|
69
|
+
/>
|
|
70
|
+
{/key}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</ExtensionsComponents>
|
|
74
|
+
{/each}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
{/if}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
const { lobb, ctx } = getStudioContext();
|
|
30
30
|
import { calculateDrawerWidth, getChangedProperties } from "../../../utils";
|
|
31
31
|
import { getField, getFieldIcon } from "../../dataTable/utils";
|
|
32
|
-
import
|
|
32
|
+
import DetailViewChildren from "../update/detailViewChildren.svelte";
|
|
33
33
|
import type { Snippet } from "svelte";
|
|
34
34
|
import { getDefaultEntry, parseDetailViewValues, serializeEntry } from "../utils";
|
|
35
35
|
import FieldInput from "../fieldInput.svelte";
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
{/each}
|
|
146
146
|
</div>
|
|
147
147
|
{#if showRelatedRecords}
|
|
148
|
-
<
|
|
148
|
+
<DetailViewChildren {collectionName} {entry} />
|
|
149
149
|
{/if}
|
|
150
150
|
</div>
|
|
151
151
|
<div class="flex h-12 items-center justify-end gap-2 border-t px-4">
|
|
@@ -1,40 +1,61 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { SideBarData } from "../../../components/sidebar/sidebarElements.svelte";
|
|
2
|
+
import type { SideBarData, SideBarNode } from "../../../components/sidebar/sidebarElements.svelte";
|
|
3
3
|
import Sidebar from "../../../components/sidebar/sidebar.svelte";
|
|
4
4
|
import { getStudioContext } from "../../../context";
|
|
5
5
|
import Collection from "./collection.svelte";
|
|
6
6
|
|
|
7
7
|
const { ctx } = getStudioContext();
|
|
8
|
-
import { Table } from "lucide-svelte";
|
|
8
|
+
import { Table, Cpu, LibraryBig } from "lucide-svelte";
|
|
9
|
+
import * as Icons from "lucide-svelte";
|
|
10
|
+
|
|
11
|
+
const directoryIcons: Record<string, any> = {
|
|
12
|
+
project: LibraryBig,
|
|
13
|
+
core: Cpu,
|
|
14
|
+
};
|
|
9
15
|
|
|
10
16
|
let { collectionName } = $props();
|
|
11
17
|
|
|
12
18
|
const collectionsList = $state(getCollectionsList());
|
|
13
19
|
|
|
14
|
-
function getCollectionsList() {
|
|
20
|
+
function getCollectionsList(): SideBarData {
|
|
15
21
|
const collections = ctx.meta.collections;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// updating the path from '__project' and '__core' to a more readable names
|
|
28
|
-
collectionsOwners = collectionsOwners.map((item) => {
|
|
29
|
-
if (item.path === "__project") {
|
|
30
|
-
item.path = "project";
|
|
31
|
-
} else if (item.path === "__core") {
|
|
32
|
-
item.path = "core";
|
|
22
|
+
|
|
23
|
+
const groups = new Map<string, SideBarNode[]>();
|
|
24
|
+
|
|
25
|
+
for (const [name, value] of Object.entries(collections)) {
|
|
26
|
+
let groupKey: string = (value as any).category ?? (value as any).owner;
|
|
27
|
+
if (groupKey === "__project") groupKey = "project";
|
|
28
|
+
else if (groupKey === "__core") groupKey = "core";
|
|
29
|
+
|
|
30
|
+
if (!groups.has(groupKey)) {
|
|
31
|
+
groups.set(groupKey, []);
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
groups.get(groupKey)!.push({
|
|
34
|
+
type: "element",
|
|
35
|
+
name,
|
|
36
|
+
icon: Table,
|
|
37
|
+
href: `/studio/collections/${name}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const result: SideBarData = [];
|
|
42
|
+
for (const [groupKey, children] of groups) {
|
|
43
|
+
const extensionIconName = ctx.meta.extensions?.[groupKey]?.icon;
|
|
44
|
+
const isProject = groupKey === "project";
|
|
45
|
+
result.push({
|
|
46
|
+
type: "directory",
|
|
47
|
+
name: isProject ? "Collections" : groupKey,
|
|
48
|
+
icon: directoryIcons[groupKey] ?? (extensionIconName ? (Icons as any)[extensionIconName] : undefined),
|
|
49
|
+
collapsed: isProject ? false : true,
|
|
50
|
+
children,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
36
53
|
|
|
37
|
-
return
|
|
54
|
+
return result.sort((a, b) => {
|
|
55
|
+
if ((a as any).name === "core") return 1;
|
|
56
|
+
if ((b as any).name === "core") return -1;
|
|
57
|
+
return 0;
|
|
58
|
+
});
|
|
38
59
|
}
|
|
39
60
|
</script>
|
|
40
61
|
|
|
@@ -13,14 +13,8 @@
|
|
|
13
13
|
title="Data Model"
|
|
14
14
|
showSearch={false}
|
|
15
15
|
data={[
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
href: "/studio/datamodel/graph",
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: "query_editor",
|
|
22
|
-
href: "/studio/datamodel/query_editor",
|
|
23
|
-
},
|
|
16
|
+
{ type: "element", name: "graph", href: "/studio/datamodel/graph" },
|
|
17
|
+
{ type: "element", name: "query_editor", href: "/studio/datamodel/query_editor" },
|
|
24
18
|
]}
|
|
25
19
|
>
|
|
26
20
|
<div class="relative h-full w-full">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { SideBarData } from "../../../components/sidebar/sidebarElements.svelte";
|
|
2
|
+
import type { SideBarData, SideBarNode } from "../../../components/sidebar/sidebarElements.svelte";
|
|
3
3
|
import WorkflowEditor, {
|
|
4
4
|
type WorkflowEntry,
|
|
5
5
|
} from "../../../components/workflowEditor.svelte";
|
|
@@ -31,18 +31,31 @@
|
|
|
31
31
|
const response = await lobb.findAll("core_workflows", {});
|
|
32
32
|
const result = await response.json();
|
|
33
33
|
const workflows: any[] = result.data;
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
|
|
35
|
+
const groups = new Map<string, SideBarNode[]>();
|
|
36
|
+
const nodes: SideBarData = [];
|
|
37
|
+
|
|
38
|
+
for (const workflow of workflows) {
|
|
39
|
+
const item: SideBarNode = {
|
|
40
|
+
type: "element",
|
|
36
41
|
name: workflow.name,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
location.navigate(`/studio/workflows/${workflow.name}`);
|
|
40
|
-
},
|
|
41
|
-
meta: {
|
|
42
|
-
id: workflow.id,
|
|
43
|
-
},
|
|
42
|
+
onclick: () => location.navigate(`/studio/workflows/${workflow.name}`),
|
|
43
|
+
meta: { id: workflow.id },
|
|
44
44
|
};
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
if (workflow.directory) {
|
|
47
|
+
if (!groups.has(workflow.directory)) {
|
|
48
|
+
const children: SideBarNode[] = [];
|
|
49
|
+
groups.set(workflow.directory, children);
|
|
50
|
+
nodes.push({ type: "directory", name: workflow.directory, children });
|
|
51
|
+
}
|
|
52
|
+
groups.get(workflow.directory)!.push(item);
|
|
53
|
+
} else {
|
|
54
|
+
nodes.push(item);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
sidebarData = nodes;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
async function fetchWorkflowData(workflowName: string) {
|
|
@@ -13,13 +13,12 @@
|
|
|
13
13
|
import SidebarElements, {
|
|
14
14
|
type SideBarData,
|
|
15
15
|
type SideBarElement,
|
|
16
|
-
type
|
|
16
|
+
type SideBarNode,
|
|
17
17
|
} from "./sidebarElements.svelte";
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
title: string;
|
|
21
21
|
data: SideBarData | null;
|
|
22
|
-
sidebarElementsProps?: Partial<SidebarElementsProps>;
|
|
23
22
|
showSearch?: boolean;
|
|
24
23
|
children: Snippet<[]>;
|
|
25
24
|
belowSearch?: Snippet;
|
|
@@ -29,7 +28,6 @@
|
|
|
29
28
|
let {
|
|
30
29
|
title,
|
|
31
30
|
data,
|
|
32
|
-
sidebarElementsProps,
|
|
33
31
|
showSearch = true,
|
|
34
32
|
children,
|
|
35
33
|
belowSearch,
|
|
@@ -67,7 +65,17 @@
|
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
function filterSidebarData(items: SideBarData, term: string): SideBarData {
|
|
70
|
-
return items.
|
|
68
|
+
return items.reduce<SideBarData>((acc, node) => {
|
|
69
|
+
if (node.type === "directory") {
|
|
70
|
+
const filteredChildren = filterSidebarData(node.children, term);
|
|
71
|
+
if (filteredChildren.length > 0) {
|
|
72
|
+
acc.push({ ...node, collapsed: false, children: filteredChildren });
|
|
73
|
+
}
|
|
74
|
+
} else if (node.name.toLowerCase().includes(term)) {
|
|
75
|
+
acc.push(node);
|
|
76
|
+
}
|
|
77
|
+
return acc;
|
|
78
|
+
}, []);
|
|
71
79
|
}
|
|
72
80
|
</script>
|
|
73
81
|
|
|
@@ -124,7 +132,6 @@
|
|
|
124
132
|
<SidebarElements
|
|
125
133
|
bind:data={visibleData}
|
|
126
134
|
{elementRightSide}
|
|
127
|
-
{...sidebarElementsProps}
|
|
128
135
|
/>
|
|
129
136
|
{/key}
|
|
130
137
|
</div>
|
|
@@ -2,11 +2,10 @@ export interface SidebarProperties {
|
|
|
2
2
|
collapsed: boolean;
|
|
3
3
|
}
|
|
4
4
|
import { type Snippet } from "svelte";
|
|
5
|
-
import { type SideBarData, type SideBarElement
|
|
5
|
+
import { type SideBarData, type SideBarElement } from "./sidebarElements.svelte";
|
|
6
6
|
interface Props {
|
|
7
7
|
title: string;
|
|
8
8
|
data: SideBarData | null;
|
|
9
|
-
sidebarElementsProps?: Partial<SidebarElementsProps>;
|
|
10
9
|
showSearch?: boolean;
|
|
11
10
|
children: Snippet<[]>;
|
|
12
11
|
belowSearch?: Snippet;
|