@lobb-js/studio 0.1.31
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/.env.example +1 -0
- package/.storybook/main.ts +31 -0
- package/.storybook/preview.ts +21 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/README.md +47 -0
- package/components.json +16 -0
- package/docker-entrypoint.sh +7 -0
- package/dockerfile +27 -0
- package/index.html +13 -0
- package/package.json +77 -0
- package/public/lobb.svg +15 -0
- package/src/Studio.svelte +150 -0
- package/src/app.css +121 -0
- package/src/components-export.ts +21 -0
- package/src/extensions/extension.types.ts +93 -0
- package/src/extensions/extensionUtils.ts +192 -0
- package/src/lib/Lobb.ts +241 -0
- package/src/lib/components/LlmButton.svelte +136 -0
- package/src/lib/components/alertView.svelte +20 -0
- package/src/lib/components/breadCrumbs.svelte +60 -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 +107 -0
- package/src/lib/components/dataTable/childRecords.svelte +140 -0
- package/src/lib/components/dataTable/dataTable.svelte +223 -0
- package/src/lib/components/dataTable/fieldCell.svelte +74 -0
- package/src/lib/components/dataTable/filter.svelte +282 -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 +154 -0
- package/src/lib/components/dataTable/sort.svelte +171 -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 +68 -0
- package/src/lib/components/detailView/create/createDetailView.svelte +226 -0
- package/src/lib/components/detailView/create/createDetailViewButton.svelte +32 -0
- package/src/lib/components/detailView/create/createManyView.svelte +250 -0
- package/src/lib/components/detailView/create/subRecords.svelte +48 -0
- package/src/lib/components/detailView/detailViewForm.svelte +104 -0
- package/src/lib/components/detailView/fieldCustomInput.svelte +23 -0
- package/src/lib/components/detailView/fieldInput.svelte +287 -0
- package/src/lib/components/detailView/fieldInputReplacement.svelte +199 -0
- package/src/lib/components/detailView/store.svelte.ts +61 -0
- package/src/lib/components/detailView/update/children.svelte +94 -0
- package/src/lib/components/detailView/update/updateDetailView.svelte +175 -0
- package/src/lib/components/detailView/update/updateDetailViewButton.svelte +32 -0
- package/src/lib/components/detailView/utils.ts +177 -0
- package/src/lib/components/diffViewer.svelte +102 -0
- package/src/lib/components/drawer.svelte +28 -0
- package/src/lib/components/extensionsComponents.svelte +31 -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 +238 -0
- package/src/lib/components/monacoEditor.svelte +181 -0
- package/src/lib/components/rangeCalendarButton.svelte +257 -0
- package/src/lib/components/selectRecord.svelte +126 -0
- package/src/lib/components/setServerPage.svelte +48 -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 +69 -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 +187 -0
- package/src/lib/eventSystem.ts +38 -0
- package/src/lib/index.ts +40 -0
- package/src/lib/store.svelte.ts +21 -0
- package/src/lib/store.types.ts +28 -0
- package/src/lib/utils.ts +84 -0
- package/src/main.ts +18 -0
- package/src/routes/collections/collection.svelte +46 -0
- package/src/routes/collections/collections.svelte +43 -0
- package/src/routes/data_model/dataModel.svelte +40 -0
- package/src/routes/data_model/flow.css +22 -0
- package/src/routes/data_model/flow.svelte +82 -0
- package/src/routes/data_model/syncManager.svelte +93 -0
- package/src/routes/data_model/utils.ts +35 -0
- package/src/routes/extensions/extension.svelte +16 -0
- package/src/routes/home.svelte +36 -0
- package/src/routes/workflows/workflows.svelte +135 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/detailView/detailViewForm.stories.svelte +79 -0
- package/src/stories/examples/Button.stories.svelte +31 -0
- package/src/stories/examples/Button.svelte +30 -0
- package/src/stories/examples/Header.stories.svelte +26 -0
- package/src/stories/examples/Header.svelte +45 -0
- package/src/stories/examples/Page.stories.svelte +29 -0
- package/src/stories/examples/Page.svelte +70 -0
- package/src/stories/examples/button.css +30 -0
- package/src/stories/examples/header.css +32 -0
- package/src/stories/examples/page.css +68 -0
- package/src/vite-env.d.ts +2 -0
- package/svelte.config.js +7 -0
- package/todo.md +24 -0
- package/tsconfig.app.json +25 -0
- package/tsconfig.json +14 -0
- package/tsconfig.node.json +24 -0
- package/vite-plugin-contextual-lib.js +66 -0
- package/vite.build.svelte.config.ts +18 -0
- package/vite.config.ts +84 -0
- package/vite.extension.config.ts +81 -0
- package/vite_utils.ts +28 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import CalendarIcon from "@lucide/svelte/icons/calendar";
|
|
3
|
+
import type { DateRange } from "bits-ui";
|
|
4
|
+
import {
|
|
5
|
+
CalendarDate,
|
|
6
|
+
DateFormatter,
|
|
7
|
+
type DateValue,
|
|
8
|
+
getLocalTimeZone,
|
|
9
|
+
parseDate,
|
|
10
|
+
startOfWeek,
|
|
11
|
+
today,
|
|
12
|
+
} from "@internationalized/date";
|
|
13
|
+
import { cn } from "$lib/utils.js";
|
|
14
|
+
import { buttonVariants } from "$lib/components/ui/button/index.js";
|
|
15
|
+
import { RangeCalendar } from "$lib/components/ui/range-calendar/index.js";
|
|
16
|
+
import * as Popover from "$lib/components/ui/popover/index.js";
|
|
17
|
+
import Input from "./ui/input/input.svelte";
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
value: DateRange;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let { value = $bindable() }: Props = $props();
|
|
24
|
+
|
|
25
|
+
const df = new DateFormatter(navigator.language, {
|
|
26
|
+
dateStyle: "medium",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
let startValue: DateValue | undefined = $state(undefined);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<div class="grid gap-2">
|
|
33
|
+
<Popover.Root>
|
|
34
|
+
<Popover.Trigger
|
|
35
|
+
class={cn(
|
|
36
|
+
buttonVariants({ variant: "outline" }),
|
|
37
|
+
!value && "text-muted-foreground",
|
|
38
|
+
"h-7 px-3 text-xs font-normal",
|
|
39
|
+
)}
|
|
40
|
+
>
|
|
41
|
+
<CalendarIcon class="mr-2 size-4" />
|
|
42
|
+
{#if value && value.start}
|
|
43
|
+
{#if value.end}
|
|
44
|
+
{df.format(value.start.toDate(getLocalTimeZone()))} - {df.format(
|
|
45
|
+
value.end.toDate(getLocalTimeZone()),
|
|
46
|
+
)}
|
|
47
|
+
{:else}
|
|
48
|
+
{df.format(value.start.toDate(getLocalTimeZone()))}
|
|
49
|
+
{/if}
|
|
50
|
+
{:else if startValue}
|
|
51
|
+
{df.format(startValue.toDate(getLocalTimeZone()))}
|
|
52
|
+
{:else}
|
|
53
|
+
Pick a date
|
|
54
|
+
{/if}
|
|
55
|
+
</Popover.Trigger>
|
|
56
|
+
<Popover.Content class="flex w-auto p-0" align="start">
|
|
57
|
+
<div class="flex flex-col border-r">
|
|
58
|
+
<div
|
|
59
|
+
class="flex flex-col overflow-hidden text-muted-foreground"
|
|
60
|
+
>
|
|
61
|
+
<button
|
|
62
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
63
|
+
onclick={() => {
|
|
64
|
+
const currentDate = today(getLocalTimeZone());
|
|
65
|
+
value = {
|
|
66
|
+
start: currentDate,
|
|
67
|
+
end: currentDate,
|
|
68
|
+
};
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
Today
|
|
72
|
+
</button>
|
|
73
|
+
<button
|
|
74
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
75
|
+
onclick={() => {
|
|
76
|
+
const currentDate = today(getLocalTimeZone());
|
|
77
|
+
value = {
|
|
78
|
+
start: currentDate.subtract({ days: 1 }),
|
|
79
|
+
end: currentDate.subtract({ days: 1 }),
|
|
80
|
+
};
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
Yesterday
|
|
84
|
+
</button>
|
|
85
|
+
<button
|
|
86
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
87
|
+
onclick={() => {
|
|
88
|
+
const currentDate = today(getLocalTimeZone());
|
|
89
|
+
const weekStart = startOfWeek(currentDate, "en-US");
|
|
90
|
+
value = {
|
|
91
|
+
start: weekStart,
|
|
92
|
+
end: currentDate,
|
|
93
|
+
};
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
This week (Sun - Today)
|
|
97
|
+
</button>
|
|
98
|
+
<button
|
|
99
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
100
|
+
onclick={() => {
|
|
101
|
+
const currentDate = today(getLocalTimeZone());
|
|
102
|
+
const thisWeekStart = startOfWeek(
|
|
103
|
+
currentDate,
|
|
104
|
+
"en-US",
|
|
105
|
+
);
|
|
106
|
+
const lastWeekEnd = thisWeekStart.subtract({
|
|
107
|
+
days: 1,
|
|
108
|
+
});
|
|
109
|
+
const lastWeekStart = startOfWeek(
|
|
110
|
+
lastWeekEnd,
|
|
111
|
+
"en-US",
|
|
112
|
+
);
|
|
113
|
+
value = {
|
|
114
|
+
start: lastWeekStart,
|
|
115
|
+
end: lastWeekEnd,
|
|
116
|
+
};
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
Last week (Sun - Sat)
|
|
120
|
+
</button>
|
|
121
|
+
<button
|
|
122
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
123
|
+
onclick={() => {
|
|
124
|
+
const currentDate = today(getLocalTimeZone());
|
|
125
|
+
value = {
|
|
126
|
+
start: currentDate.subtract({ days: 6 }),
|
|
127
|
+
end: currentDate,
|
|
128
|
+
};
|
|
129
|
+
}}
|
|
130
|
+
>
|
|
131
|
+
Last 7 days
|
|
132
|
+
</button>
|
|
133
|
+
<button
|
|
134
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
135
|
+
onclick={() => {
|
|
136
|
+
const currentDate = today(getLocalTimeZone());
|
|
137
|
+
value = {
|
|
138
|
+
start: currentDate.subtract({ days: 29 }),
|
|
139
|
+
end: currentDate,
|
|
140
|
+
};
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
143
|
+
Last 30 days
|
|
144
|
+
</button>
|
|
145
|
+
<button
|
|
146
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
147
|
+
onclick={() => {
|
|
148
|
+
const currentDate = today(getLocalTimeZone());
|
|
149
|
+
value = {
|
|
150
|
+
start: currentDate.subtract({ days: 89 }),
|
|
151
|
+
end: currentDate,
|
|
152
|
+
};
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
Last 90 days
|
|
156
|
+
</button>
|
|
157
|
+
<button
|
|
158
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
159
|
+
onclick={() => {
|
|
160
|
+
const currentDate = today(getLocalTimeZone());
|
|
161
|
+
value = {
|
|
162
|
+
start: currentDate.subtract({ months: 12 }),
|
|
163
|
+
end: currentDate,
|
|
164
|
+
};
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
Last 12 months
|
|
168
|
+
</button>
|
|
169
|
+
<button
|
|
170
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
171
|
+
onclick={() => {
|
|
172
|
+
const currentDate = today(getLocalTimeZone());
|
|
173
|
+
const lastYearStart = currentDate
|
|
174
|
+
.subtract({ years: 1 })
|
|
175
|
+
.set({ month: 1, day: 1 });
|
|
176
|
+
const lastYearEnd = currentDate
|
|
177
|
+
.subtract({ years: 1 })
|
|
178
|
+
.set({ month: 12, day: 31 });
|
|
179
|
+
value = {
|
|
180
|
+
start: lastYearStart,
|
|
181
|
+
end: lastYearEnd,
|
|
182
|
+
};
|
|
183
|
+
}}
|
|
184
|
+
>
|
|
185
|
+
Last Calendar year
|
|
186
|
+
</button>
|
|
187
|
+
<button
|
|
188
|
+
class="text-start text-sm py-2 px-2 hover:bg-soft hover:text-primary"
|
|
189
|
+
onclick={() => {
|
|
190
|
+
const currentDate = today(getLocalTimeZone());
|
|
191
|
+
const yearStart = currentDate.set({
|
|
192
|
+
month: 1,
|
|
193
|
+
day: 1,
|
|
194
|
+
});
|
|
195
|
+
value = {
|
|
196
|
+
start: yearStart,
|
|
197
|
+
end: currentDate,
|
|
198
|
+
};
|
|
199
|
+
}}
|
|
200
|
+
>
|
|
201
|
+
This Year (Jan - Today)
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
<div>
|
|
206
|
+
<div class="flex gap-2 p-2 justify-end border-b">
|
|
207
|
+
<!-- Start Date -->
|
|
208
|
+
<Input
|
|
209
|
+
type="date"
|
|
210
|
+
class="w-fit"
|
|
211
|
+
bind:value={
|
|
212
|
+
() => {
|
|
213
|
+
if (!value?.start) return "";
|
|
214
|
+
// Convert CalendarDate → YYYY-MM-DD string
|
|
215
|
+
const jsDate = value.start.toDate("UTC");
|
|
216
|
+
return jsDate.toISOString().split("T")[0];
|
|
217
|
+
},
|
|
218
|
+
(v) => {
|
|
219
|
+
// Convert YYYY-MM-DD string → CalendarDate
|
|
220
|
+
value = {
|
|
221
|
+
...value,
|
|
222
|
+
start: parseDate(v),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/>
|
|
227
|
+
|
|
228
|
+
<!-- End Date -->
|
|
229
|
+
<Input
|
|
230
|
+
type="date"
|
|
231
|
+
class="w-fit"
|
|
232
|
+
bind:value={
|
|
233
|
+
() => {
|
|
234
|
+
if (!value?.end) return "";
|
|
235
|
+
const jsDate = value.end.toDate("UTC");
|
|
236
|
+
return jsDate.toISOString().split("T")[0];
|
|
237
|
+
},
|
|
238
|
+
(v) => {
|
|
239
|
+
value = {
|
|
240
|
+
...value,
|
|
241
|
+
end: parseDate(v),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/>
|
|
246
|
+
</div>
|
|
247
|
+
<RangeCalendar
|
|
248
|
+
bind:value
|
|
249
|
+
onStartValueChange={(v) => {
|
|
250
|
+
startValue = v;
|
|
251
|
+
}}
|
|
252
|
+
numberOfMonths={2}
|
|
253
|
+
/>
|
|
254
|
+
</div>
|
|
255
|
+
</Popover.Content>
|
|
256
|
+
</Popover.Root>
|
|
257
|
+
</div>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ArrowLeft, Link } from "lucide-svelte";
|
|
3
|
+
import Button, { type ButtonProps } from "./ui/button/button.svelte";
|
|
4
|
+
import DataTable from "./dataTable/dataTable.svelte";
|
|
5
|
+
import { getCollectionPrimaryField } from "./dataTable/utils";
|
|
6
|
+
import { emitEvent } from "$lib/eventSystem";
|
|
7
|
+
import Drawer from "./drawer.svelte";
|
|
8
|
+
|
|
9
|
+
interface LocalProps extends ButtonProps {
|
|
10
|
+
collectionName: string;
|
|
11
|
+
parentCollectionName?: string;
|
|
12
|
+
fieldName?: string;
|
|
13
|
+
value?: any;
|
|
14
|
+
onSelect?: (entry: any) => void;
|
|
15
|
+
filter?: Record<string, any>;
|
|
16
|
+
additionalFilter?: Record<string, any>;
|
|
17
|
+
text?: string;
|
|
18
|
+
entry?: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
parentCollectionName,
|
|
23
|
+
collectionName,
|
|
24
|
+
fieldName,
|
|
25
|
+
value = $bindable(),
|
|
26
|
+
onSelect,
|
|
27
|
+
filter = {},
|
|
28
|
+
additionalFilter = {},
|
|
29
|
+
text,
|
|
30
|
+
entry,
|
|
31
|
+
...restProps
|
|
32
|
+
}: LocalProps = $props();
|
|
33
|
+
|
|
34
|
+
let openDrawer = $state(false);
|
|
35
|
+
|
|
36
|
+
async function handleButtonClick() {
|
|
37
|
+
try {
|
|
38
|
+
const eventResult = await emitEvent(
|
|
39
|
+
"studio.collections.preForeignKeySelect",
|
|
40
|
+
{
|
|
41
|
+
parentCollectionName,
|
|
42
|
+
collectionName,
|
|
43
|
+
fieldName,
|
|
44
|
+
entry,
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
if (eventResult.filter) {
|
|
48
|
+
additionalFilter = eventResult.filter;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
openDrawer = true;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function onSelectHandler(entry: any) {
|
|
58
|
+
const primaryFieldName = getCollectionPrimaryField(collectionName);
|
|
59
|
+
const localValue: any = {
|
|
60
|
+
id: entry.id,
|
|
61
|
+
};
|
|
62
|
+
if (primaryFieldName) {
|
|
63
|
+
const primaryFieldValue = entry[primaryFieldName];
|
|
64
|
+
localValue[primaryFieldName] = primaryFieldValue;
|
|
65
|
+
}
|
|
66
|
+
value = localValue;
|
|
67
|
+
|
|
68
|
+
// calling the onSelect callback function
|
|
69
|
+
if (onSelect) {
|
|
70
|
+
onSelect(entry);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// closing the drawer
|
|
74
|
+
openDrawer = false;
|
|
75
|
+
}
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<!-- THE SELECT BUTTON -->
|
|
79
|
+
<Button onclick={handleButtonClick} {...restProps}>
|
|
80
|
+
{#if restProps.children}
|
|
81
|
+
{@render restProps.children()}
|
|
82
|
+
{:else}
|
|
83
|
+
<Link size="13" />
|
|
84
|
+
{#if text}
|
|
85
|
+
{text}
|
|
86
|
+
{:else}
|
|
87
|
+
Select record
|
|
88
|
+
{/if}
|
|
89
|
+
{/if}
|
|
90
|
+
</Button>
|
|
91
|
+
|
|
92
|
+
<!-- THE SELECT DRAWER -->
|
|
93
|
+
{#if openDrawer}
|
|
94
|
+
<Drawer onHide={async () => { openDrawer = false }}>
|
|
95
|
+
<div class="flex h-12 items-center gap-4 border-b px-4">
|
|
96
|
+
<Button
|
|
97
|
+
variant="outline"
|
|
98
|
+
onclick={() => (openDrawer = false)}
|
|
99
|
+
class=" h-8 w-8 rounded-full text-xs font-normal"
|
|
100
|
+
Icon={ArrowLeft}
|
|
101
|
+
></Button>
|
|
102
|
+
<div class="flex items-center gap-2">
|
|
103
|
+
<div class="text-sm">Select record from</div>
|
|
104
|
+
<span
|
|
105
|
+
class="rounded-md border bg-muted px-2 py-0.5 text-sm"
|
|
106
|
+
>
|
|
107
|
+
{collectionName}
|
|
108
|
+
</span>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="flex-1 overflow-y-auto bg-muted">
|
|
112
|
+
<DataTable
|
|
113
|
+
{collectionName}
|
|
114
|
+
tableProps={{
|
|
115
|
+
showCheckboxes: false,
|
|
116
|
+
select: {
|
|
117
|
+
onSelect: onSelectHandler,
|
|
118
|
+
},
|
|
119
|
+
}}
|
|
120
|
+
filter={{
|
|
121
|
+
$and: [filter, additionalFilter],
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
</div>
|
|
125
|
+
</Drawer>
|
|
126
|
+
{/if}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { toast } from "svelte-sonner";
|
|
3
|
+
import Button from "./ui/button/button.svelte";
|
|
4
|
+
import { ctx } from "$lib/store.svelte";
|
|
5
|
+
import { Input } from "$lib/components/ui/input";
|
|
6
|
+
|
|
7
|
+
let formData = {
|
|
8
|
+
server: "",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
async function handleClick(e: Event) {
|
|
12
|
+
if (!formData.server) {
|
|
13
|
+
toast.error("Please fill the server url");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
await fetch(formData.server);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
toast.error(`Couldn't connect to the (${formData.server}) server`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
localStorage.setItem("lobb_url", formData.server);
|
|
23
|
+
ctx.lobbUrl = formData.server;
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
class="fixed left-0 top-0 flex h-screen w-screen items-center justify-center bg-muted"
|
|
29
|
+
>
|
|
30
|
+
<div class="flex w-full max-w-100 flex-col gap-6 p-6">
|
|
31
|
+
<div>
|
|
32
|
+
<div class="text-4xl">Welcome back</div>
|
|
33
|
+
<div>Sign in to your account</div>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="flex flex-col gap-6 rounded-md border bg-white p-6">
|
|
36
|
+
<div class="flex flex-col gap-2">
|
|
37
|
+
<div>
|
|
38
|
+
<div class="mb-1 text-sm font-medium">Server</div>
|
|
39
|
+
<Input
|
|
40
|
+
bind:value={formData.server}
|
|
41
|
+
placeholder="http://example.lobb.com"
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
<Button onclick={handleClick}>Save & Connect</Button>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export interface SidebarProperties {
|
|
3
|
+
collapsed: boolean;
|
|
4
|
+
}
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { setContext, type Snippet } from "svelte";
|
|
9
|
+
|
|
10
|
+
import { mediaQueries } from "$lib/utils";
|
|
11
|
+
import Skeleton from "../ui/skeleton/skeleton.svelte";
|
|
12
|
+
import { Search } from "lucide-svelte";
|
|
13
|
+
import SidebarElements, {
|
|
14
|
+
type SideBarData,
|
|
15
|
+
type SideBarElement,
|
|
16
|
+
type SidebarElementsProps,
|
|
17
|
+
} from "./sidebarElements.svelte";
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
title: string;
|
|
21
|
+
data: SideBarData | null;
|
|
22
|
+
sidebarElementsProps?: Partial<SidebarElementsProps>;
|
|
23
|
+
showSearch?: boolean;
|
|
24
|
+
children: Snippet<[]>;
|
|
25
|
+
belowSearch?: Snippet;
|
|
26
|
+
elementRightSide?: Snippet<[SideBarElement]>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
title,
|
|
31
|
+
data,
|
|
32
|
+
sidebarElementsProps,
|
|
33
|
+
showSearch = true,
|
|
34
|
+
children,
|
|
35
|
+
belowSearch,
|
|
36
|
+
elementRightSide,
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
|
|
39
|
+
let visibleData = $derived(data ? [...data] : null);
|
|
40
|
+
const sidebarProperties: SidebarProperties = $state({
|
|
41
|
+
collapsed: false,
|
|
42
|
+
});
|
|
43
|
+
setContext("sidebarProperties", sidebarProperties);
|
|
44
|
+
|
|
45
|
+
$effect(() => {
|
|
46
|
+
if (mediaQueries.lg.current) {
|
|
47
|
+
sidebarProperties.collapsed = false;
|
|
48
|
+
} else {
|
|
49
|
+
sidebarProperties.collapsed = true;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
let searchTerm = $state("");
|
|
54
|
+
|
|
55
|
+
const sidebarWidth = 275;
|
|
56
|
+
let sidebarContainerHeight = $state(0);
|
|
57
|
+
let sidebarContainerWidth = $state(0);
|
|
58
|
+
let sidebarHeaderHeight = $state(0);
|
|
59
|
+
let sidebarBodyHeight = $derived(
|
|
60
|
+
sidebarContainerHeight - sidebarHeaderHeight,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
function handleSearch() {
|
|
64
|
+
if (data) {
|
|
65
|
+
visibleData = filterSidebarData(data, searchTerm.toLowerCase());
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function filterSidebarData(items: SideBarData, term: string): SideBarData {
|
|
70
|
+
return items.filter((item) => item.name.includes(term));
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<div
|
|
75
|
+
class="flex h-full transition-[grid-template-columns]"
|
|
76
|
+
style="
|
|
77
|
+
display: grid;
|
|
78
|
+
grid-template-columns: {sidebarProperties.collapsed ? 0 : sidebarWidth}px 1fr;
|
|
79
|
+
"
|
|
80
|
+
bind:clientHeight={sidebarContainerHeight}
|
|
81
|
+
bind:clientWidth={sidebarContainerWidth}
|
|
82
|
+
>
|
|
83
|
+
<div
|
|
84
|
+
class="
|
|
85
|
+
bg-background border-r overflow-hidden
|
|
86
|
+
"
|
|
87
|
+
style="
|
|
88
|
+
{sidebarProperties.collapsed ? 'border-right-width: 0px; padding: 0px;' : ''}
|
|
89
|
+
height: {sidebarContainerHeight}px;
|
|
90
|
+
"
|
|
91
|
+
>
|
|
92
|
+
{#if visibleData !== null}
|
|
93
|
+
<div bind:clientHeight={sidebarHeaderHeight} class="p-2 pb-0!">
|
|
94
|
+
<div
|
|
95
|
+
class="relative flex justify-between items-center p-2 font-medium"
|
|
96
|
+
>
|
|
97
|
+
{title}
|
|
98
|
+
</div>
|
|
99
|
+
{#if showSearch}
|
|
100
|
+
<div class="p-2">
|
|
101
|
+
<div
|
|
102
|
+
class="flex items-center px-4 py-1 text-muted-foreground bg-soft border rounded-md"
|
|
103
|
+
>
|
|
104
|
+
<input
|
|
105
|
+
type="text"
|
|
106
|
+
class="w-full bg-transparent text-sm focus:outline-none"
|
|
107
|
+
oninput={handleSearch}
|
|
108
|
+
bind:value={searchTerm}
|
|
109
|
+
placeholder="Search"
|
|
110
|
+
/>
|
|
111
|
+
<Search size="20" />
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
{/if}
|
|
115
|
+
</div>
|
|
116
|
+
<div
|
|
117
|
+
class="
|
|
118
|
+
text-primary p-2 overflow-y-auto overflow-x-clip
|
|
119
|
+
"
|
|
120
|
+
style="max-height: {sidebarBodyHeight}px;"
|
|
121
|
+
>
|
|
122
|
+
{@render belowSearch?.()}
|
|
123
|
+
{#key visibleData}
|
|
124
|
+
<SidebarElements
|
|
125
|
+
bind:data={visibleData}
|
|
126
|
+
{elementRightSide}
|
|
127
|
+
{...sidebarElementsProps}
|
|
128
|
+
/>
|
|
129
|
+
{/key}
|
|
130
|
+
</div>
|
|
131
|
+
{:else}
|
|
132
|
+
<div class="flex flex-col gap-2 p-2">
|
|
133
|
+
<Skeleton class="h-6 w-full" />
|
|
134
|
+
<Skeleton class="h-6 w-full" />
|
|
135
|
+
<Skeleton class="h-6 w-full" />
|
|
136
|
+
<Skeleton class="h-6 w-full" />
|
|
137
|
+
<Skeleton class="h-6 w-full" />
|
|
138
|
+
</div>
|
|
139
|
+
{/if}
|
|
140
|
+
</div>
|
|
141
|
+
<div
|
|
142
|
+
class="overflow-auto h-full"
|
|
143
|
+
style="
|
|
144
|
+
max-height: {sidebarContainerHeight}px;
|
|
145
|
+
"
|
|
146
|
+
>
|
|
147
|
+
{@render children()}
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|