@ocelescope/core 0.0.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/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # react-components-starter
2
+
3
+ A starter for creating a React component library.
4
+
5
+ ## Development
6
+
7
+ - Install dependencies:
8
+
9
+ ```bash
10
+ npm install
11
+ ```
12
+
13
+ - Run the playground:
14
+
15
+ ```bash
16
+ npm run play
17
+ ```
18
+
19
+ - Run the unit tests:
20
+
21
+ ```bash
22
+ npm run test
23
+ ```
24
+
25
+ - Build the library:
26
+
27
+ ```bash
28
+ npm run build
29
+ ```
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ ._0yGNhG_wrapper{width:100%;margin-bottom:30px;position:relative}._0yGNhG_dropzone{color:var(--mantine-color-bright);border-width:1px;padding-bottom:50px}._0yGNhG_icon{color:light-dark(var(--mantine-color-gray-4),var(--mantine-color-white))}._0yGNhG_control{width:250px;position:absolute;bottom:-20px;left:calc(50% - 125px)}._0yGNhG_description{text-align:center;font-size:var(--mantine-font-size-sm);color:var(--mantine-color-dimmed);margin-top:var(--mantine-spacing-xs)}
@@ -0,0 +1,51 @@
1
+ import * as react0 from "react";
2
+ import { SVGProps } from "react";
3
+ import * as next0 from "next";
4
+ import { GetStaticPaths, GetStaticProps } from "next";
5
+
6
+ //#region src/components/OcelescopeApp.d.ts
7
+ declare const OcelescopeApp: React.FC<any>;
8
+ //#endregion
9
+ //#region src/components/OcelescopeDocument.d.ts
10
+ declare const OcelescopeDocument: React.FC;
11
+ //#endregion
12
+ //#region src/lib/config.d.ts
13
+ type Author = {
14
+ name: string;
15
+ link?: string;
16
+ };
17
+ type ModuleDefinition = {
18
+ name: string;
19
+ label: string;
20
+ authors: Author[];
21
+ description: string;
22
+ routes: ModuleRouteDefinition[];
23
+ icon?: React.ComponentType<SVGProps<SVGSVGElement>>;
24
+ };
25
+ type ModuleRouteDefinition = {
26
+ name: string;
27
+ label: string;
28
+ requiresOcel?: boolean;
29
+ component: React.ComponentType;
30
+ };
31
+ type OcelescopeConfig = {
32
+ homePage?: React.FC;
33
+ modules?: readonly ModuleDefinition[];
34
+ };
35
+ //#endregion
36
+ //#region src/components/ModulePage.d.ts
37
+ type ModulePageProps = {
38
+ moduleProps?: {
39
+ moduleName: string;
40
+ routeName: string;
41
+ };
42
+ };
43
+ declare const createModulesPage: (config: OcelescopeConfig) => {
44
+ getStaticPaths: GetStaticPaths;
45
+ getStaticProps: GetStaticProps<ModulePageProps>;
46
+ ModulePage: react0.FunctionComponent<ModulePageProps> & {
47
+ getInitialProps?(context: next0.NextPageContext): ModulePageProps | Promise<ModulePageProps>;
48
+ };
49
+ };
50
+ //#endregion
51
+ export { ModuleDefinition, ModuleRouteDefinition, OcelescopeApp, OcelescopeConfig, OcelescopeDocument, createModulesPage };
package/dist/index.js ADDED
@@ -0,0 +1,605 @@
1
+ import { ActionIcon, AppShell, Badge, Burger, Button, ColorSchemeScript, Container, Group, LoadingOverlay, MantineProvider, Menu, MenuItem, Modal, Select, Stack, Text, TextInput, ThemeIcon, Title, mantineHtmlProps, useMantineTheme } from "@mantine/core";
2
+ import { HydrationBoundary, QueryClient, QueryClientProvider, useQueryClient } from "@tanstack/react-query";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import { useDisclosure } from "@mantine/hooks";
5
+ import { CheckIcon, ContainerIcon, DownloadIcon, EllipsisVerticalIcon, EyeIcon, PencilIcon, TrashIcon, Upload, UploadIcon, X, XIcon } from "lucide-react";
6
+ import { DataTable } from "mantine-datatable";
7
+ import { Dropzone } from "@mantine/dropzone";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ import { useDeleteOcel, useDeleteResource, useGetDefaultOcel, useGetOcels, useGetResourceMeta, useImportDefaultOcel, useRenameOcel, useRenameResource, useResources, useUpload } from "@ocelescope/api-base";
10
+ import { env, useSessionStore } from "@ocelescope/api-client";
11
+ import { create } from "zustand";
12
+ import { persist } from "zustand/middleware";
13
+ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
14
+ import { Head, Html, Main, NextScript } from "next/document";
15
+ import { ResourceModal } from "@ocelescope/resources";
16
+ import { saveAs } from "file-saver";
17
+ import { parse } from "content-disposition-attachment";
18
+ import dayjs from "dayjs";
19
+ import isBetween from "dayjs/plugin/isBetween";
20
+ import { generateColor } from "@marko19907/string-to-color";
21
+
22
+ import './index.css';
23
+ //#region src/hooks/useInvalidate.ts
24
+ const useInvalidate = () => {
25
+ const queryClient = useQueryClient();
26
+ return async (routeNames) => await queryClient.invalidateQueries({ predicate: (query) => typeof query.queryKey[0] === "string" && routeNames.some((route) => query.queryKey[0].includes(`/${route}`)) });
27
+ };
28
+ var useInvalidate_default = useInvalidate;
29
+
30
+ //#endregion
31
+ //#region src/components/Dropzone/Dropzone.module.css?css_module
32
+ const classes = {
33
+ "control": "_0yGNhG_control",
34
+ "icon": "_0yGNhG_icon",
35
+ "description": "_0yGNhG_description",
36
+ "wrapper": "_0yGNhG_wrapper",
37
+ "dropzone": "_0yGNhG_dropzone"
38
+ };
39
+ var Dropzone_module_default = classes;
40
+ const _control0 = classes["control"];
41
+ const _icon0 = classes["icon"];
42
+ const _description0 = classes["description"];
43
+ const _wrapper0 = classes["wrapper"];
44
+ const _dropzone0 = classes["dropzone"];
45
+
46
+ //#endregion
47
+ //#region src/components/Dropzone/Dropzone.tsx
48
+ const FileDropzone = ({ onUpload, accept, content }) => {
49
+ const theme = useMantineTheme();
50
+ const openRef = useRef(null);
51
+ return /* @__PURE__ */ jsxs("div", {
52
+ className: Dropzone_module_default.wrapper,
53
+ children: [/* @__PURE__ */ jsx(Dropzone, {
54
+ openRef,
55
+ onDrop: onUpload,
56
+ className: Dropzone_module_default.dropzone,
57
+ radius: "md",
58
+ accept: accept ?? {},
59
+ children: /* @__PURE__ */ jsxs("div", {
60
+ style: { pointerEvents: "none" },
61
+ children: [
62
+ /* @__PURE__ */ jsxs(Group, {
63
+ justify: "center",
64
+ children: [
65
+ /* @__PURE__ */ jsx(Dropzone.Accept, { children: /* @__PURE__ */ jsx(DownloadIcon, {
66
+ size: 50,
67
+ color: theme.colors.blue[6]
68
+ }) }),
69
+ /* @__PURE__ */ jsx(Dropzone.Reject, { children: /* @__PURE__ */ jsx(X, {
70
+ size: 50,
71
+ color: theme.colors.red[6]
72
+ }) }),
73
+ /* @__PURE__ */ jsx(Dropzone.Idle, { children: /* @__PURE__ */ jsx(Upload, {
74
+ size: 50,
75
+ className: Dropzone_module_default.icon
76
+ }) })
77
+ ]
78
+ }),
79
+ /* @__PURE__ */ jsxs(Text, {
80
+ ta: "center",
81
+ fw: 700,
82
+ fz: "lg",
83
+ mt: "xl",
84
+ children: [
85
+ content.accept && /* @__PURE__ */ jsx(Dropzone.Accept, { children: content.accept }),
86
+ content.reject && /* @__PURE__ */ jsx(Dropzone.Reject, { children: content.reject }),
87
+ content.idle && /* @__PURE__ */ jsx(Dropzone.Idle, { children: content.idle })
88
+ ]
89
+ }),
90
+ /* @__PURE__ */ jsx(Text, {
91
+ className: Dropzone_module_default.description,
92
+ children: content.description || /* @__PURE__ */ jsx("span", { children: "Drag'n'drop files here to upload." })
93
+ })
94
+ ]
95
+ })
96
+ }), /* @__PURE__ */ jsx(Button, {
97
+ className: Dropzone_module_default.control,
98
+ size: "sm",
99
+ radius: "xl",
100
+ onClick: () => openRef.current?.(),
101
+ children: "Select files"
102
+ })]
103
+ });
104
+ };
105
+ var Dropzone_default = FileDropzone;
106
+
107
+ //#endregion
108
+ //#region src/components/UploadSection/UploadSection.tsx
109
+ const DefaultOcels = ({ onSuccess, setIsPending }) => {
110
+ const { data: ocels = [] } = useGetDefaultOcel({});
111
+ const invalidate = useInvalidate_default();
112
+ const { mutate: uploadDefault } = useImportDefaultOcel({ mutation: {
113
+ onSuccess: async () => {
114
+ await invalidate(["ocels"]);
115
+ onSuccess();
116
+ },
117
+ onMutate: () => setIsPending(true),
118
+ onSettled: () => setIsPending(false)
119
+ } });
120
+ return /* @__PURE__ */ jsx(DataTable, {
121
+ noHeader: true,
122
+ records: ocels,
123
+ idAccessor: "key",
124
+ highlightOnHover: true,
125
+ withRowBorders: false,
126
+ onRowClick: ({ record }) => {
127
+ uploadDefault({ params: { ...record } });
128
+ },
129
+ columns: [
130
+ {
131
+ accessor: "",
132
+ render: () => /* @__PURE__ */ jsx(ThemeIcon, {
133
+ variant: "transparent",
134
+ children: /* @__PURE__ */ jsx(ContainerIcon, {})
135
+ })
136
+ },
137
+ { accessor: "name" },
138
+ {
139
+ accessor: "version",
140
+ textAlign: "right",
141
+ render: ({ version }) => `v${version}`
142
+ }
143
+ ]
144
+ });
145
+ };
146
+ const FileUploadZone = ({ onSuccess, setIsPending }) => {
147
+ const { mutate: upload } = useUpload({ mutation: {
148
+ onSuccess,
149
+ onMutate: () => setIsPending(true),
150
+ onSettled: () => setIsPending(false)
151
+ } });
152
+ return /* @__PURE__ */ jsx(Dropzone_default, {
153
+ content: { description: /* @__PURE__ */ jsx("span", { children: `Drag'n'drop your ${[
154
+ "OCELs",
155
+ "Plugins",
156
+ "Resources"
157
+ ].join(", ")} here to upload.` }) },
158
+ onUpload: async (files) => {
159
+ upload({ data: { files } });
160
+ }
161
+ });
162
+ };
163
+ const UploadSection = ({ onSuccess }) => {
164
+ const [isPending, setIsPending] = useState(false);
165
+ const onUploadSuccess = useCallback(() => {
166
+ setIsPending(false);
167
+ onSuccess?.();
168
+ }, [onSuccess]);
169
+ return /* @__PURE__ */ jsxs(Stack, {
170
+ gap: "xs",
171
+ pos: "relative",
172
+ children: [
173
+ /* @__PURE__ */ jsx(LoadingOverlay, {
174
+ visible: isPending,
175
+ overlayProps: {
176
+ radius: "sm",
177
+ blur: 2
178
+ }
179
+ }),
180
+ /* @__PURE__ */ jsx(FileUploadZone, {
181
+ onSuccess: onUploadSuccess,
182
+ setIsPending
183
+ }),
184
+ /* @__PURE__ */ jsx(DefaultOcels, {
185
+ onSuccess: onUploadSuccess,
186
+ setIsPending
187
+ })
188
+ ]
189
+ });
190
+ };
191
+ var UploadSection_default = UploadSection;
192
+
193
+ //#endregion
194
+ //#region src/components/UploadModal/UploadModal.tsx
195
+ const UploadModal = ({ visible, onClose }) => {
196
+ return /* @__PURE__ */ jsx(Modal, {
197
+ title: /* @__PURE__ */ jsx(Text, {
198
+ size: "h3",
199
+ children: "Upload"
200
+ }),
201
+ opened: visible,
202
+ onClose,
203
+ size: "xl",
204
+ children: /* @__PURE__ */ jsx(UploadSection_default, { onSuccess: onClose })
205
+ });
206
+ };
207
+ var UploadModal_default = UploadModal;
208
+
209
+ //#endregion
210
+ //#region src/store/currentOcelStore.ts
211
+ const useCurrentOcelStore = create()(persist((set) => ({
212
+ ocelId: null,
213
+ setOcel: (id) => set({ ocelId: id }),
214
+ clearOcel: () => set({ ocelId: null })
215
+ }), { name: env.current_ocel_id }));
216
+ var currentOcelStore_default = useCurrentOcelStore;
217
+
218
+ //#endregion
219
+ //#region src/hooks/useCurrentOCEL.ts
220
+ const useCurrentOcel = () => {
221
+ const { data: ocels = [] } = useGetOcels();
222
+ const { ocelId, setOcel, clearOcel } = currentOcelStore_default();
223
+ useEffect(() => {
224
+ if (ocelId && !ocels?.some(({ id }) => id === ocelId)) clearOcel();
225
+ if (!ocelId && ocels[0]) setOcel(ocels[0].id);
226
+ }, [
227
+ clearOcel,
228
+ setOcel,
229
+ ocels,
230
+ ocelId
231
+ ]);
232
+ return {
233
+ id: ocelId,
234
+ setCurrentOcel: setOcel
235
+ };
236
+ };
237
+ var useCurrentOCEL_default = useCurrentOcel;
238
+
239
+ //#endregion
240
+ //#region src/components/OcelSelect/OcelSelect.tsx
241
+ const OcelSelect = ({ extension, ...props }) => {
242
+ const { data } = useGetOcels(extension ? { extension_name: extension } : {});
243
+ const ocels = useMemo(() => data ?? [], [data]);
244
+ return /* @__PURE__ */ jsx(Select, {
245
+ ...props,
246
+ data: ocels.map(({ name, id }) => ({
247
+ value: id,
248
+ label: name
249
+ }))
250
+ });
251
+ };
252
+ const CurrentOcelSelect = () => {
253
+ const { id, setCurrentOcel } = useCurrentOCEL_default();
254
+ return /* @__PURE__ */ jsx(OcelSelect, {
255
+ value: id,
256
+ unselectable: "off",
257
+ onChange: (id$1) => {
258
+ if (id$1) setCurrentOcel(id$1);
259
+ }
260
+ });
261
+ };
262
+
263
+ //#endregion
264
+ //#region src/components/AppShell/AppShell.tsx
265
+ const AppShell$1 = ({ children }) => {
266
+ const [mobileOpened, { toggle: toggleMobile }] = useDisclosure(true);
267
+ const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
268
+ const [isUploadModalVisible, setIsUploadModalVisible] = useState(false);
269
+ return /* @__PURE__ */ jsxs(AppShell, {
270
+ header: { height: 60 },
271
+ navbar: {
272
+ width: 300,
273
+ breakpoint: "sm",
274
+ collapsed: {
275
+ mobile: !mobileOpened,
276
+ desktop: !desktopOpened
277
+ }
278
+ },
279
+ padding: "md",
280
+ children: [
281
+ /* @__PURE__ */ jsx(AppShell.Header, { children: /* @__PURE__ */ jsxs(Group, {
282
+ h: "100%",
283
+ px: "md",
284
+ justify: "space-between",
285
+ children: [/* @__PURE__ */ jsxs(Group, {
286
+ align: "center",
287
+ children: [/* @__PURE__ */ jsx(Burger, {
288
+ opened: mobileOpened,
289
+ onClick: toggleMobile,
290
+ hiddenFrom: "sm",
291
+ size: "sm"
292
+ }), /* @__PURE__ */ jsx(Burger, {
293
+ opened: desktopOpened,
294
+ onClick: toggleDesktop,
295
+ visibleFrom: "sm",
296
+ size: "sm"
297
+ })]
298
+ }), /* @__PURE__ */ jsxs(Group, { children: [
299
+ /* @__PURE__ */ jsx(CurrentOcelSelect, {}),
300
+ /* @__PURE__ */ jsx(Button, {
301
+ leftSection: /* @__PURE__ */ jsx(UploadIcon, { size: 18 }),
302
+ onClick: () => setIsUploadModalVisible(true),
303
+ children: "Upload"
304
+ }),
305
+ /* @__PURE__ */ jsx(UploadModal_default, {
306
+ visible: isUploadModalVisible,
307
+ onClose: () => setIsUploadModalVisible(false)
308
+ })
309
+ ] })]
310
+ }) }),
311
+ /* @__PURE__ */ jsx(AppShell.Navbar, {}),
312
+ /* @__PURE__ */ jsx(AppShell.Main, { children })
313
+ ]
314
+ });
315
+ };
316
+
317
+ //#endregion
318
+ //#region src/components/OcelescopeApp.tsx
319
+ const OcelescopeApp = ({ Component, pageProps }) => {
320
+ const [client] = useState(() => new QueryClient());
321
+ return /* @__PURE__ */ jsxs(QueryClientProvider, {
322
+ client,
323
+ children: [/* @__PURE__ */ jsx(HydrationBoundary, {
324
+ state: pageProps.dehydratedState,
325
+ children: /* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(AppShell$1, { children: /* @__PURE__ */ jsx(Component, {}) }) })
326
+ }), /* @__PURE__ */ jsx(ReactQueryDevtools, {})]
327
+ });
328
+ };
329
+
330
+ //#endregion
331
+ //#region src/components/OcelescopeDocument.tsx
332
+ const OcelescopeDocument = () => {
333
+ return /* @__PURE__ */ jsxs(Html, {
334
+ lang: "en",
335
+ ...mantineHtmlProps,
336
+ children: [/* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx(ColorSchemeScript, { defaultColorScheme: "auto" }) }), /* @__PURE__ */ jsxs("body", { children: [/* @__PURE__ */ jsx(Main, {}), /* @__PURE__ */ jsx(NextScript, {})] })]
337
+ });
338
+ };
339
+
340
+ //#endregion
341
+ //#region src/hooks/useDownload.ts
342
+ const useDownloadFile = () => {
343
+ const { sessionId } = useSessionStore();
344
+ const downloadFile = async (path) => {
345
+ try {
346
+ const response = await fetch(`${env.backend_url}${path}`, {
347
+ method: "GET",
348
+ headers: { [env.session_id]: sessionId ?? "" }
349
+ });
350
+ if (!response.ok) throw new Error("Failed to download file");
351
+ const blob = await response.blob();
352
+ const contentDisposition = parse(response.headers.get("Content-Disposition") ?? "");
353
+ saveAs(blob, contentDisposition.attachment ? contentDisposition.filename : "fileName");
354
+ } catch (err) {
355
+ console.error("Download error:", err);
356
+ }
357
+ };
358
+ return downloadFile;
359
+ };
360
+
361
+ //#endregion
362
+ //#region src/lib/dayjs.ts
363
+ dayjs.extend(isBetween);
364
+ var dayjs_default = dayjs;
365
+ const formatDateTime = (dateString) => dayjs(dateString).format("YYYY-MM-DD HH:mm");
366
+
367
+ //#endregion
368
+ //#region src/components/EntityTable/EntityTable.tsx
369
+ const ocelExtenisions = [
370
+ ".sqlite",
371
+ ".xmlocel",
372
+ ".jsonocel"
373
+ ];
374
+ const EntityTable = () => {
375
+ const { data: ocels = [] } = useGetOcels();
376
+ const { data: resources = [] } = useResources();
377
+ const invalidate = useInvalidate_default();
378
+ const downloadFile = useDownloadFile();
379
+ const { data: resourceMeta = {} } = useGetResourceMeta();
380
+ const { mutate: deleteResource } = useDeleteResource({ mutation: { onSuccess: () => invalidate(["resources"]) } });
381
+ const { mutate: deleteOcel } = useDeleteOcel({ mutation: { onSuccess: () => invalidate(["ocels"]) } });
382
+ const { mutate: renameOcel } = useRenameOcel({ mutation: { onSuccess: () => invalidate(["ocels"]) } });
383
+ const { mutate: renameResource } = useRenameResource({ mutation: { onSuccess: () => invalidate(["resources"]) } });
384
+ const deleteEntity = useCallback((id, entityType) => {
385
+ switch (entityType) {
386
+ case "ocel":
387
+ deleteOcel({ params: { ocel_id: id } });
388
+ break;
389
+ case "resource":
390
+ deleteResource({ resourceId: id });
391
+ break;
392
+ }
393
+ }, [deleteResource, deleteOcel]);
394
+ const renameEntitiy = useCallback((id, entityType, newName) => {
395
+ switch (entityType) {
396
+ case "ocel":
397
+ renameOcel({ params: {
398
+ ocel_id: id,
399
+ new_name: newName
400
+ } });
401
+ break;
402
+ case "resource": renameResource({
403
+ resourceId: id,
404
+ params: { new_name: newName }
405
+ });
406
+ }
407
+ }, [renameOcel, renameResource]);
408
+ const [renamedEntitiy, setRenamedEntitiy] = useState(void 0);
409
+ const [viewedResouce, setViewedResource] = useState();
410
+ const entities = useMemo(() => {
411
+ const ocelEntities = ocels.map(({ name, created_at, id, extensions }) => ({
412
+ id,
413
+ name,
414
+ type: "ocel",
415
+ entityTypes: extensions.map(({ label }) => label),
416
+ createdAt: formatDateTime(created_at),
417
+ downloadFormats: [
418
+ ".xml",
419
+ ".json",
420
+ ".sqlite"
421
+ ]
422
+ }));
423
+ const resourceEntities = resources.map(({ id, name, type, created_at }) => ({
424
+ id,
425
+ name,
426
+ entityTypes: [resourceMeta[type]?.label ?? type],
427
+ type: "resource",
428
+ createdAt: formatDateTime(dayjs_default(created_at).toISOString())
429
+ }));
430
+ return [...ocelEntities, ...resourceEntities];
431
+ }, [
432
+ ocels,
433
+ resources,
434
+ resourceMeta
435
+ ]);
436
+ return /* @__PURE__ */ jsxs(Fragment, { children: [viewedResouce && /* @__PURE__ */ jsx(ResourceModal, {
437
+ id: viewedResouce,
438
+ onClose: () => setViewedResource(void 0)
439
+ }), entities.length ? /* @__PURE__ */ jsx(DataTable, {
440
+ withTableBorder: true,
441
+ borderRadius: "md",
442
+ idAccessor: "id",
443
+ columns: [
444
+ {
445
+ accessor: "name",
446
+ render: ({ id, type, name }) => /* @__PURE__ */ jsx(Fragment, { children: renamedEntitiy?.id === id ? /* @__PURE__ */ jsxs(Group, { children: [/* @__PURE__ */ jsx(TextInput, {
447
+ variant: "unstyled",
448
+ value: renamedEntitiy.value,
449
+ style: { borderBottom: "1px solid #9ca3af" },
450
+ onChange: (e) => {
451
+ setRenamedEntitiy({
452
+ id,
453
+ value: e.target.value
454
+ });
455
+ }
456
+ }), /* @__PURE__ */ jsxs(Group, {
457
+ gap: "xs",
458
+ children: [/* @__PURE__ */ jsx(ActionIcon, {
459
+ color: "green",
460
+ m: 0,
461
+ onClick: () => {
462
+ renameEntitiy(id, type, renamedEntitiy.value);
463
+ setRenamedEntitiy(void 0);
464
+ },
465
+ children: /* @__PURE__ */ jsx(CheckIcon, { size: 16 })
466
+ }), /* @__PURE__ */ jsx(ActionIcon, {
467
+ color: "red",
468
+ m: 0,
469
+ onClick: () => {
470
+ setRenamedEntitiy(void 0);
471
+ },
472
+ children: /* @__PURE__ */ jsx(XIcon, { size: 16 })
473
+ })]
474
+ })] }) : name })
475
+ },
476
+ { accessor: "createdAt" },
477
+ {
478
+ accessor: "entityTypes",
479
+ title: "Type",
480
+ render: ({ type, entityTypes }) => /* @__PURE__ */ jsx(Group, {
481
+ gap: "xs",
482
+ children: [...type === "ocel" ? ["OCEL"] : [], ...entityTypes].map((entityType) => /* @__PURE__ */ jsx(Badge, {
483
+ color: generateColor(entityType),
484
+ children: entityType
485
+ }, entityType))
486
+ })
487
+ },
488
+ {
489
+ accessor: "",
490
+ textAlign: "right",
491
+ width: "0%",
492
+ render: ({ type, id, name }) => /* @__PURE__ */ jsxs(Menu, {
493
+ width: 200,
494
+ position: "left-start",
495
+ children: [/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, {
496
+ variant: "subtle",
497
+ onClick: (e) => e.stopPropagation(),
498
+ children: /* @__PURE__ */ jsx(EllipsisVerticalIcon, { size: 20 })
499
+ }) }), /* @__PURE__ */ jsxs(Menu.Dropdown, {
500
+ onClick: (e) => e.stopPropagation(),
501
+ children: [
502
+ /* @__PURE__ */ jsx(Menu.Item, {
503
+ leftSection: /* @__PURE__ */ jsx(PencilIcon, { size: 16 }),
504
+ onClick: () => setRenamedEntitiy({
505
+ id,
506
+ value: name
507
+ }),
508
+ children: "Rename"
509
+ }),
510
+ type === "resource" && /* @__PURE__ */ jsx(MenuItem, {
511
+ leftSection: /* @__PURE__ */ jsx(EyeIcon, { size: 16 }),
512
+ onClick: () => setViewedResource(id),
513
+ children: "Inspect"
514
+ }),
515
+ type === "ocel" ? /* @__PURE__ */ jsxs(Menu.Sub, {
516
+ position: "right-start",
517
+ children: [/* @__PURE__ */ jsx(Menu.Sub.Target, { children: /* @__PURE__ */ jsx(Menu.Sub.Item, {
518
+ leftSection: /* @__PURE__ */ jsx(DownloadIcon, { size: 16 }),
519
+ children: "Download"
520
+ }) }), /* @__PURE__ */ jsx(Menu.Sub.Dropdown, { children: ocelExtenisions.map((extension) => /* @__PURE__ */ jsx(Menu.Item, {
521
+ onClick: () => downloadFile(`/ocels/download?${new URLSearchParams({
522
+ ocel_id: id,
523
+ ext: extension
524
+ }).toString()}`),
525
+ children: extension
526
+ }, extension)) })]
527
+ }) : /* @__PURE__ */ jsx(Menu.Item, {
528
+ onClick: () => downloadFile(`/resources/resource/${id}/download`),
529
+ leftSection: /* @__PURE__ */ jsx(DownloadIcon, { size: 16 }),
530
+ children: "Download"
531
+ }),
532
+ /* @__PURE__ */ jsx(Menu.Divider, {}),
533
+ /* @__PURE__ */ jsx(Menu.Item, {
534
+ leftSection: /* @__PURE__ */ jsx(TrashIcon, {
535
+ size: 16,
536
+ color: "red"
537
+ }),
538
+ color: "red",
539
+ fw: "bold",
540
+ onClick: () => deleteEntity(id, type),
541
+ children: "Delete"
542
+ })
543
+ ]
544
+ })]
545
+ })
546
+ }
547
+ ],
548
+ records: entities
549
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Title, {
550
+ size: "h3",
551
+ children: "Upload"
552
+ }), /* @__PURE__ */ jsx(UploadSection_default, {})] })] });
553
+ };
554
+ var EntityTable_default = EntityTable;
555
+
556
+ //#endregion
557
+ //#region src/components/DefaultHomePage/DefaultHomePage.tsx
558
+ const DefaultHomePage = ({ children }) => {
559
+ return /* @__PURE__ */ jsx(Container, {
560
+ h: "100%",
561
+ children: /* @__PURE__ */ jsxs(Stack, {
562
+ gap: "sm",
563
+ h: "100%",
564
+ children: [/* @__PURE__ */ jsx(EntityTable_default, {}), children]
565
+ })
566
+ });
567
+ };
568
+ var DefaultHomePage_default = DefaultHomePage;
569
+
570
+ //#endregion
571
+ //#region src/components/ModulePage.tsx
572
+ const createModulesPage = (config) => {
573
+ const { modules = [], homePage: HomePage = DefaultHomePage_default } = config;
574
+ const getStaticPaths = async () => {
575
+ return {
576
+ paths: [...modules.flatMap(({ name: moduleName, routes }) => routes.map(({ name: routeName }) => ({ params: { slug: [
577
+ "modules",
578
+ moduleName,
579
+ routeName
580
+ ] } }))), { params: { slug: [] } }],
581
+ fallback: false
582
+ };
583
+ };
584
+ const getStaticProps = async ({ params }) => {
585
+ const slugs = params?.slug ?? [];
586
+ const moduleConfig = modules.find(({ name }) => name === slugs[1]);
587
+ const routeName = moduleConfig?.routes.find(({ name }) => name === slugs[2])?.name;
588
+ return moduleConfig && routeName ? { props: { moduleProps: {
589
+ moduleName: moduleConfig.name,
590
+ routeName
591
+ } } } : { props: {} };
592
+ };
593
+ const ModulePage = ({ moduleProps }) => {
594
+ const RouteComponent = modules.find(({ name }) => name === moduleProps?.moduleName)?.routes.find(({ name }) => name === moduleProps?.routeName)?.component;
595
+ return RouteComponent ? /* @__PURE__ */ jsx(RouteComponent, {}) : /* @__PURE__ */ jsx(HomePage, {});
596
+ };
597
+ return {
598
+ getStaticPaths,
599
+ getStaticProps,
600
+ ModulePage
601
+ };
602
+ };
603
+
604
+ //#endregion
605
+ export { OcelescopeApp, OcelescopeDocument, createModulesPage };
@@ -0,0 +1,3 @@
1
+ import "@mantine/core/styles.css";
2
+ import "mantine-datatable/styles.css";
3
+ import "@mantine/dropzone/styles.css";
@@ -0,0 +1,4 @@
1
+ import './index.css';
2
+ import "@mantine/core/styles.css";
3
+ import "mantine-datatable/styles.css";
4
+ import "@mantine/dropzone/styles.css";
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@ocelescope/core",
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "description": "Core React component and style library for Ocelescope (Mantine + React Query).",
6
+ "author": "Görkem-Emre Öztürk <goerkem.oeztuerk@rwth-aachen.de>",
7
+ "license": "MIT",
8
+ "homepage": "https://www.ocelescope.org",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/promi4s/ocelescope.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/promi4s/ocelescope/issues"
15
+ },
16
+ "exports": {
17
+ ".": "./dist/index.js",
18
+ "./package.json": "./package.json",
19
+ "./styles": "./dist/styles/styles.js"
20
+ },
21
+ "main": "./dist/index.js",
22
+ "module": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "peerDependencies": {
31
+ "@mantine/core": "^8.3.14",
32
+ "@mantine/dropzone": "^8.3.14",
33
+ "@mantine/hooks": "^8.3.14",
34
+ "@tanstack/react-query": "^5.90.20",
35
+ "@tanstack/react-query-devtools": "^5.91.3",
36
+ "content-disposition-attachment": "^0.3.1",
37
+ "clsx": "^2.1.1",
38
+ "file-saver": "^2.0.5",
39
+ "lucide-react": "^0.563.0",
40
+ "mantine-datatable": "^8.3.13",
41
+ "next": "^16.1.6",
42
+ "react": "^19.2.0",
43
+ "react-dom": "^19.2.0",
44
+ "zod": "^4.3.6",
45
+ "zustand": "^5.0.11",
46
+ "@marko19907/string-to-color": "^1.0.2",
47
+ "dayjs": "^1.11.19",
48
+ "@ocelescope/api-base": "0.0.0",
49
+ "@ocelescope/api-client": "0.0.0",
50
+ "@ocelescope/resources": "0.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@tsconfig/strictest": "^2.0.8",
54
+ "@types/css-modules": "^1.0.5",
55
+ "@types/file-saver": "^2.0.7",
56
+ "@types/node": "^25.0.3",
57
+ "@types/react": "^19.2.7",
58
+ "@types/react-dom": "^19.2.3",
59
+ "bumpp": "^10.3.2",
60
+ "tsdown": "^0.18.1",
61
+ "typescript": "^5.9.3"
62
+ },
63
+ "scripts": {
64
+ "build": "tsdown",
65
+ "dev": "tsdown --watch ./src"
66
+ }
67
+ }