@ocelescope/discovery 0.7.0 → 0.9.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.
Files changed (2) hide show
  1. package/dist/index.js +106 -479
  2. package/package.json +13 -12
package/dist/index.js CHANGED
@@ -1,495 +1,127 @@
1
1
  import { defineModule, defineModuleRoute, useCurrentOcel } from "@ocelescope/core";
2
- import { BookmarkIcon, ChartNetwork, SettingsIcon } from "lucide-react";
3
- import { ActionIcon, Alert, Box, Card, Center, Divider, Drawer, Input, LoadingOverlay, MultiSelect, NumberInput, Select, Slider, Stack, Text, Tooltip } from "@mantine/core";
4
- import { useLocalStorage } from "@mantine/hooks";
5
- import { useCreateDiscoveryTask, useDiscoveryTask, useEventCounts, useListDiscoveryFilters, useListDiscoveryMethods, useObjectCounts, useSaveDiscovery } from "@ocelescope/api-base";
6
- import { Visualization } from "@ocelescope/resources";
7
- import { memo, useEffect, useMemo, useState } from "react";
8
- import { create } from "zustand";
9
- import { persist } from "zustand/middleware";
10
- import validator from "@rjsf/validator-ajv8";
11
- import dynamic from "next/dynamic.js";
12
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
- //#region src/stores/discoveryStore.ts
14
- const EMPTY = {
15
- selectedMethodId: null,
16
- formDataByMethod: {},
17
- filters: [],
18
- filtersInitialized: false
19
- };
20
- const updateOcel = (state, ocelId, patch) => ({ byOcel: {
21
- ...state.byOcel,
22
- [ocelId]: {
23
- ...state.byOcel[ocelId] ?? EMPTY,
24
- ...patch
25
- }
26
- } });
27
- const useDiscoveryStore = create()(persist((set) => ({
28
- byOcel: {},
29
- setSelectedMethodId: (ocelId, methodId) => set((s) => updateOcel(s, ocelId, { selectedMethodId: methodId })),
30
- setFormData: (ocelId, methodId, data) => set((s) => {
31
- const current = s.byOcel[ocelId] ?? EMPTY;
32
- return updateOcel(s, ocelId, { formDataByMethod: {
33
- ...current.formDataByMethod,
34
- [methodId]: data
35
- } });
36
- }),
37
- setFilters: (ocelId, filters) => set((s) => updateOcel(s, ocelId, { filters })),
38
- initializeFilters: (ocelId, filters) => set((s) => {
39
- if (s.byOcel[ocelId]?.filtersInitialized) return s;
40
- return updateOcel(s, ocelId, {
41
- filters,
42
- filtersInitialized: true
43
- });
44
- })
45
- }), { name: "ocelescope:discovery" }));
46
- const selectOcelFormState = (ocelId) => (s) => s.byOcel[ocelId] ?? EMPTY;
47
- //#endregion
48
- //#region src/utils/discoveryState.ts
49
- const getInitialFormData = (schema) => {
50
- const initial = {};
51
- for (const [name, property] of Object.entries(schema?.properties ?? {})) {
52
- if (property.default !== void 0) {
53
- initial[name] = property.default;
54
- continue;
55
- }
56
- if (property.type === "array") initial[name] = [];
57
- }
58
- return initial;
59
- };
60
- const normalizeFormData = (formData) => Object.fromEntries(Object.entries(formData).filter(([_, value]) => {
61
- if (value === void 0 || value === null || value === "") return false;
62
- if (Array.isArray(value) && value.length === 0) return false;
63
- return true;
64
- }));
65
- //#endregion
66
- //#region src/components/DiscoveryForm.tsx
67
- const Form = dynamic(() => import("@rjsf/mantine").then((m) => m.Form), { ssr: false });
68
- const MantineSliderWidget = ({ value, onChange, schema, label, required }) => {
69
- const min = schema.minimum ?? schema.exclusiveMinimum;
70
- const max = schema.maximum ?? schema.exclusiveMaximum;
71
- const description = schema.description;
72
- return /* @__PURE__ */ jsxs(Fragment, { children: [
73
- /* @__PURE__ */ jsx(Input.Label, {
74
- required,
75
- children: label
76
- }),
77
- description && /* @__PURE__ */ jsx(Input.Description, { children: description }),
78
- /* @__PURE__ */ jsx(NumberInput, {
79
- mt: "5px",
80
- min,
81
- max,
82
- step: 1e-4,
83
- decimalScale: 4,
84
- hideControls: true,
85
- value: typeof value === "number" ? value : schema.default ?? min,
86
- onChange: (v) => typeof v === "number" && onChange(v)
87
- }),
88
- /* @__PURE__ */ jsx(Slider, {
89
- min,
90
- max,
91
- step: 1e-4,
92
- label: (v) => v.toFixed(4),
93
- value: typeof value === "number" ? value : schema.default ?? min,
94
- onChange
95
- })
96
- ] });
97
- };
98
- const WIDGETS = { "mantine-slider": MantineSliderWidget };
99
- const FieldTemplate = ({ children, errors, help, hidden }) => {
100
- if (hidden) return /* @__PURE__ */ jsx("div", {
101
- style: { display: "none" },
102
- children
103
- });
104
- return /* @__PURE__ */ jsxs("div", { children: [
105
- children,
106
- errors,
107
- help
108
- ] });
109
- };
110
- const DescriptionFieldTemplate = ({ id, description }) => description ? /* @__PURE__ */ jsx(Input.Description, {
111
- id,
112
- mt: -8,
113
- mb: 8,
114
- children: description
115
- }) : null;
116
- const TEMPLATES = {
117
- DescriptionFieldTemplate,
118
- FieldTemplate
119
- };
120
- const UI_SCHEMA_BASE = { "ui:submitButtonOptions": { norender: true } };
121
- const buildUiSchema = (schema) => {
122
- const uiSchema = { ...UI_SCHEMA_BASE };
123
- for (const [key, prop] of Object.entries(schema.properties ?? {})) if (prop.fieldType) uiSchema[key] = { "ui:field": prop.fieldType };
124
- else if ((prop.type === "number" || prop.type === "integer") && (prop.minimum !== void 0 || prop.exclusiveMinimum !== void 0) && (prop.maximum !== void 0 || prop.exclusiveMaximum !== void 0)) uiSchema[key] = { "ui:widget": "mantine-slider" };
125
- return uiSchema;
126
- };
127
- const makeOcelFields = (eventTypeOptions, objectTypeOptions) => {
128
- const OcelTypeField = (options) => memo(({ schema, formData, onChange, required, fieldPathId: { path } }) => {
129
- return /* @__PURE__ */ jsx(schema.type === "array" ? MultiSelect : Select, {
130
- label: schema.title,
131
- description: schema.description,
132
- required,
133
- value: formData ?? (schema.type === "array" ? [] : null),
134
- onChange: (v) => onChange(v, path),
135
- data: options,
136
- clearable: true,
137
- searchable: true
138
- });
139
- });
2
+ import { ChartNetwork } from "lucide-react";
3
+ import { Box, LoadingOverlay, ScrollArea, Select, Stack, Text } from "@mantine/core";
4
+ import { useDebouncedValue } from "@mantine/hooks";
5
+ import { usePlugins, useRunPlugin } from "@ocelescope/api-base";
6
+ import { PluginDashboard, PluginForm } from "@ocelescope/plugin-components";
7
+ import { useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/hooks/useDiscoveryMethods.tsx
10
+ const useDiscoveryMethods = () => {
11
+ const { data: plugins, isLoading } = usePlugins({ include_base: true });
12
+ const discoveryGroups = useMemo(() => {
13
+ return (plugins ?? []).map(({ methods, ...plugin }) => ({
14
+ ...plugin,
15
+ methods: methods.filter(({ inputs, outputs }) => inputs.length === 1 && outputs.length === 1 && inputs[0]?.type === "ocel" && outputs[0]?.type === "resource").map(({ outputs, inputs, ...rest }) => ({
16
+ ...rest,
17
+ id: `${plugin.id}:${rest.name}`,
18
+ input: inputs[0],
19
+ pluginId: plugin.id,
20
+ output: outputs[0]
21
+ }))
22
+ }));
23
+ }, [plugins]);
140
24
  return {
141
- event_type: OcelTypeField(eventTypeOptions),
142
- object_type: OcelTypeField(objectTypeOptions)
143
- };
144
- };
145
- const DiscoveryForm = ({ schema, formData, onChange, eventTypeOptions, objectTypeOptions }) => {
146
- const uiSchema = useMemo(() => buildUiSchema(schema), [schema]);
147
- const fields = useMemo(() => makeOcelFields(eventTypeOptions, objectTypeOptions), [eventTypeOptions, objectTypeOptions]);
148
- return /* @__PURE__ */ jsx(Form, {
149
- schema: {
150
- ...schema,
151
- title: ""
152
- },
153
- formData,
154
- validator,
155
- uiSchema,
156
- fields,
157
- widgets: WIDGETS,
158
- templates: TEMPLATES,
159
- onChange: (data) => onChange(data.formData ?? {})
160
- });
161
- };
162
- //#endregion
163
- //#region src/components/DiscoveryFiltersSection.tsx
164
- const DiscoveryFiltersSection = ({ availableFilters, filters, onFiltersChange, eventTypeOptions, objectTypeOptions }) => {
165
- const handleChange = (filterName, data) => {
166
- if (filters.some((f) => f.name === filterName)) onFiltersChange(filters.map((f) => f.name === filterName ? {
167
- ...f,
168
- payload: data
169
- } : f));
170
- else onFiltersChange([...filters, {
171
- name: filterName,
172
- payload: data
173
- }]);
25
+ discoveryGroups,
26
+ discoveryMethods: useMemo(() => discoveryGroups.flatMap(({ methods }) => methods), [discoveryGroups]),
27
+ isLoading
174
28
  };
175
- return /* @__PURE__ */ jsxs(Stack, {
176
- gap: "xs",
177
- children: [/* @__PURE__ */ jsx(Text, {
178
- fw: 500,
179
- children: "Filters"
180
- }), availableFilters.map((filterSchema) => {
181
- const schema = filterSchema.json_schema;
182
- const payload = filters.find((f) => f.name === filterSchema.name)?.payload ?? {};
183
- return /* @__PURE__ */ jsxs(Card, {
184
- withBorder: true,
185
- padding: "sm",
186
- radius: "sm",
187
- children: [/* @__PURE__ */ jsx(Text, {
188
- size: "sm",
189
- fw: 500,
190
- mb: "xs",
191
- children: filterSchema.name
192
- }), /* @__PURE__ */ jsx(DiscoveryForm, {
193
- schema,
194
- formData: payload,
195
- onChange: (data) => handleChange(filterSchema.name, data),
196
- eventTypeOptions,
197
- objectTypeOptions
198
- })]
199
- }, filterSchema.name);
200
- })]
201
- });
202
- };
203
- //#endregion
204
- //#region src/components/DiscoverySettingsContent.tsx
205
- const DiscoverySettingsContent = ({ methods, selectedMethodId, setSelectedMethodId, selectedMethod, selectedSchema, activeFormData, setActiveFormData, eventCounts, objectCounts, errorMessage, availableFilters, filters, setFilters }) => {
206
- const selectedVariants = selectedMethod?.variants ?? [];
207
- return /* @__PURE__ */ jsxs(Stack, {
208
- gap: "xl",
209
- children: [
210
- /* @__PURE__ */ jsxs(Stack, {
211
- gap: "xs",
212
- children: [
213
- /* @__PURE__ */ jsx(Select, {
214
- label: "Discovery Method",
215
- value: selectedMethod?.name ?? null,
216
- onChange: (name) => {
217
- setSelectedMethodId(methods.find((m) => m.name === name)?.variants[0]?.methodId ?? null);
218
- },
219
- data: methods.map((m) => ({
220
- value: m.name,
221
- label: m.name
222
- })),
223
- allowDeselect: false
224
- }),
225
- selectedVariants.find((v) => v.methodId === selectedMethodId)?.description && /* @__PURE__ */ jsx(Text, {
226
- size: "sm",
227
- c: "dimmed",
228
- children: selectedVariants.find((v) => v.methodId === selectedMethodId)?.description
229
- }),
230
- selectedVariants.length > 1 && /* @__PURE__ */ jsx(Select, {
231
- label: "Output Format",
232
- value: selectedMethodId,
233
- onChange: setSelectedMethodId,
234
- data: selectedVariants.map((v) => ({
235
- value: v.methodId,
236
- label: v.resourceType
237
- })),
238
- allowDeselect: false
239
- }),
240
- /* @__PURE__ */ jsx(DiscoveryForm, {
241
- schema: selectedSchema,
242
- formData: activeFormData,
243
- onChange: setActiveFormData,
244
- eventTypeOptions: Object.keys(eventCounts),
245
- objectTypeOptions: Object.keys(objectCounts)
246
- })
247
- ]
248
- }),
249
- /* @__PURE__ */ jsx(Divider, {}),
250
- /* @__PURE__ */ jsx(DiscoveryFiltersSection, {
251
- availableFilters,
252
- filters,
253
- onFiltersChange: setFilters,
254
- eventTypeOptions: Object.keys(eventCounts),
255
- objectTypeOptions: Object.keys(objectCounts)
256
- }),
257
- errorMessage && /* @__PURE__ */ jsx(Alert, {
258
- color: "red",
259
- title: "Discovery failed",
260
- children: errorMessage
261
- })
262
- ]
263
- });
264
29
  };
265
30
  //#endregion
266
31
  //#region src/components/DiscoveryPage.tsx
267
- const PANEL_OPEN_KEY = "ocelescope:discovery:panel-open";
268
- const DiscoveryPageContent = ({ ocelId }) => {
269
- const { selectedMethodId, formDataByMethod, filters, filtersInitialized } = useDiscoveryStore(selectOcelFormState(ocelId));
270
- const setSelectedMethodId = useDiscoveryStore((s) => s.setSelectedMethodId);
271
- const setFormData = useDiscoveryStore((s) => s.setFormData);
272
- const setFiltersInStore = useDiscoveryStore((s) => s.setFilters);
273
- const initializeFilters = useDiscoveryStore((s) => s.initializeFilters);
274
- const [taskId, setTaskId] = useState();
275
- const [savedTaskId, setSavedTaskId] = useState();
276
- const [submitError, setSubmitError] = useState();
277
- const [panelOpen, setPanelOpen] = useLocalStorage({
278
- key: PANEL_OPEN_KEY,
279
- defaultValue: true
32
+ const uiSchema = { "ui:submitButtonOptions": { norender: true } };
33
+ const DiscoveryConfiguration = ({ method, ocelId, onSuccess }) => {
34
+ const [input, setInput] = useState({});
35
+ const [debouncedInput] = useDebouncedValue(input, 1e3);
36
+ const ref = useRef(null);
37
+ const { mutate } = useRunPlugin({ mutation: { onSuccess } });
38
+ const run = useEffectEvent((data) => {
39
+ if (method.configuration_schema && ref.current?.validate(data).errors.length !== 0) return;
40
+ mutate({
41
+ methodName: method.name,
42
+ pluginId: method.pluginId,
43
+ data: {
44
+ input_resources: { [method.input.name]: ocelId },
45
+ input: data
46
+ }
47
+ });
280
48
  });
281
- const { data: rawMethods = [], isLoading: isMethodsLoading, error: methodsError } = useListDiscoveryMethods();
282
- const methods = useMemo(() => rawMethods.map((m) => ({
283
- ...m,
284
- variants: m.variants.filter((v) => v.enabled)
285
- })).filter((m) => m.variants.length), [rawMethods]);
286
- const { data: availableFilters = [] } = useListDiscoveryFilters();
287
- const { data: eventCounts = {} } = useEventCounts(ocelId, void 0, { query: { enabled: true } });
288
- const { data: objectCounts = {} } = useObjectCounts(ocelId, void 0, { query: { enabled: true } });
289
- useEffect(() => {
290
- if (filtersInitialized || availableFilters.length === 0) return;
291
- initializeFilters(ocelId, availableFilters.map((f) => ({
292
- name: f.name,
293
- payload: getInitialFormData(f.json_schema)
294
- })));
295
- }, [
296
- filtersInitialized,
297
- availableFilters,
298
- ocelId,
299
- initializeFilters
300
- ]);
301
- useEffect(() => {
302
- if (!selectedMethodId || isMethodsLoading) return;
303
- if (!methods.flatMap((m) => m.variants.map((v) => v.methodId)).includes(selectedMethodId)) setSelectedMethodId(ocelId, null);
304
- }, [
305
- methods,
306
- selectedMethodId,
307
- isMethodsLoading,
308
- ocelId,
309
- setSelectedMethodId
310
- ]);
311
49
  useEffect(() => {
312
- if (selectedMethodId || methods.length === 0) return;
313
- setSelectedMethodId(ocelId, methods.flatMap((m) => m.variants).find((v) => v.resourceType === "DirectlyFollowsGraph")?.methodId ?? methods[0]?.variants[0]?.methodId ?? null);
314
- }, [
315
- methods,
316
- selectedMethodId,
317
- ocelId,
318
- setSelectedMethodId
319
- ]);
320
- const selectedMethod = useMemo(() => methods.find((m) => m.variants.some((v) => v.methodId === selectedMethodId)) ?? null, [methods, selectedMethodId]);
321
- const selectedSchema = useMemo(() => selectedMethod?.variants.find((v) => v.methodId === selectedMethodId) ?? null, [selectedMethod, selectedMethodId])?.inputSchema ?? {};
322
- useEffect(() => {
323
- if (!selectedMethodId || !selectedMethod) return;
324
- if (formDataByMethod[selectedMethodId]) return;
325
- setFormData(ocelId, selectedMethodId, getInitialFormData(selectedSchema));
326
- }, [
327
- selectedMethod,
328
- selectedMethodId,
329
- selectedSchema,
330
- formDataByMethod,
331
- ocelId,
332
- setFormData
333
- ]);
334
- const activeFormData = selectedMethodId ? formDataByMethod[selectedMethodId] ?? {} : {};
335
- const { mutate: runDiscovery, isPending: isSubmittingDiscovery } = useCreateDiscoveryTask({ mutation: {
336
- onSuccess: (newTaskId) => {
337
- setSubmitError(void 0);
338
- setTaskId(newTaskId);
339
- },
340
- onError: (error) => {
341
- setSubmitError(error instanceof Error ? error.message : "Discovery failed");
342
- }
343
- } });
344
- const { data: task, error: taskError } = useDiscoveryTask(taskId ?? "", { query: {
345
- enabled: !!taskId,
346
- refetchInterval: ({ state }) => {
347
- if (state.data?.state === "PENDING" || state.data?.state === "STARTED") return 1e3;
348
- return false;
349
- }
350
- } });
351
- const { mutate: saveDiscovery, isPending: isSaving } = useSaveDiscovery({ mutation: { onSuccess: (_data, { taskId: savedId }) => setSavedTaskId(savedId) } });
352
- const isSaved = !!taskId && savedTaskId === taskId;
353
- const requestPayload = useMemo(() => normalizeFormData(activeFormData), [activeFormData]);
50
+ run(debouncedInput);
51
+ }, [debouncedInput]);
52
+ return method.configuration_schema && /* @__PURE__ */ jsx(ScrollArea, {
53
+ h: "100%",
54
+ offsetScrollbars: true,
55
+ children: /* @__PURE__ */ jsx(PluginForm, {
56
+ methodName: method.name,
57
+ pluginId: method.pluginId,
58
+ schema: method.configuration_schema,
59
+ inputResources: { [method.input.name]: ocelId },
60
+ onChange: ({ formData }) => setInput(formData),
61
+ formData: input,
62
+ ref,
63
+ uiSchema
64
+ })
65
+ });
66
+ };
67
+ const DiscoverySideBar = ({ onSuccess }) => {
68
+ const { discoveryGroups, discoveryMethods, isLoading } = useDiscoveryMethods();
69
+ const { id } = useCurrentOcel();
70
+ const [currentMethod, setCurrentMethod] = useState(void 0);
354
71
  useEffect(() => {
355
- if (!selectedMethodId) return;
356
- const timeoutId = window.setTimeout(() => {
357
- runDiscovery({
358
- ocelId,
359
- data: {
360
- methodId: selectedMethodId,
361
- parameters: requestPayload,
362
- filters
363
- }
364
- });
365
- }, 650);
366
- return () => window.clearTimeout(timeoutId);
367
- }, [
368
- ocelId,
369
- runDiscovery,
370
- useMemo(() => JSON.stringify({
371
- selectedMethodId,
372
- requestPayload,
373
- ocelId,
374
- filters
375
- }), [
376
- ocelId,
377
- requestPayload,
378
- selectedMethodId,
379
- filters
380
- ]),
381
- requestPayload,
382
- selectedMethodId,
383
- filters
384
- ]);
385
- const isDiscovering = isSubmittingDiscovery || task?.state === "PENDING" || task?.state === "STARTED";
386
- const errorMessage = submitError || (methodsError instanceof Error ? methodsError.message : void 0) || (taskError instanceof Error ? taskError.message : void 0) || (task?.state === "FAILURE" ? "The backend discovery task failed." : void 0);
387
- return /* @__PURE__ */ jsxs(Box, {
388
- pos: "relative",
72
+ if (discoveryMethods.length > 0 && !currentMethod) setCurrentMethod(discoveryMethods[0]);
73
+ }, [discoveryMethods]);
74
+ return /* @__PURE__ */ jsxs(Stack, {
75
+ px: "md",
76
+ pt: "xs",
389
77
  h: "100%",
390
- style: { overflow: "hidden" },
391
78
  children: [
392
- task?.state === "SUCCESS" ? /* @__PURE__ */ jsx(Box, {
393
- h: "100%",
394
- p: "sm",
395
- children: /* @__PURE__ */ jsx(Visualization, {
396
- visualization: task.visualization,
397
- menuItems: [{
398
- icon: /* @__PURE__ */ jsx(BookmarkIcon, { style: {
399
- width: 16,
400
- height: 16,
401
- maxWidth: "none",
402
- maxHeight: "none",
403
- stroke: isSaved ? "var(--mantine-color-green-6)" : "currentColor",
404
- fill: isSaved ? "var(--mantine-color-green-6)" : "none"
405
- } }),
406
- label: isSaved ? "Saved" : "Save",
407
- onClick: () => {
408
- if (taskId && !isSaving && taskId !== savedTaskId) saveDiscovery({ taskId });
409
- }
410
- }]
411
- })
412
- }) : /* @__PURE__ */ jsx(Center, {
413
- h: "100%",
414
- children: /* @__PURE__ */ jsx(Text, {
415
- c: "dimmed",
416
- ta: "center",
417
- children: isDiscovering ? "Discovering visualization..." : "The discovery preview will appear here."
418
- })
419
- }),
420
- !panelOpen && /* @__PURE__ */ jsx(Tooltip, {
421
- label: "Open settings",
422
- position: "left",
423
- withArrow: true,
424
- children: /* @__PURE__ */ jsx(ActionIcon, {
425
- variant: "default",
426
- size: "lg",
427
- radius: "md",
428
- onClick: () => setPanelOpen(true),
429
- style: {
430
- position: "absolute",
431
- top: 12,
432
- right: 12,
433
- zIndex: 5
434
- },
435
- children: /* @__PURE__ */ jsx(SettingsIcon, { size: 16 })
436
- })
79
+ /* @__PURE__ */ jsx(Select, {
80
+ label: "Discovery Method",
81
+ searchable: true,
82
+ value: currentMethod?.id,
83
+ onChange: (newMethod) => setCurrentMethod(discoveryMethods.find(({ id }) => id === newMethod)),
84
+ data: discoveryGroups.filter(({ methods }) => methods.length > 0).map(({ label, methods }) => ({
85
+ group: label,
86
+ items: methods.map(({ label, id }) => ({
87
+ value: id,
88
+ label
89
+ }))
90
+ })),
91
+ loading: isLoading
437
92
  }),
438
- /* @__PURE__ */ jsx(LoadingOverlay, {
439
- visible: isMethodsLoading || isDiscovering,
440
- zIndex: 100
93
+ currentMethod && /* @__PURE__ */ jsx(Text, {
94
+ c: "dimmed",
95
+ children: currentMethod.description
441
96
  }),
442
- /* @__PURE__ */ jsx(Drawer, {
443
- opened: panelOpen,
444
- onClose: () => setPanelOpen(false),
445
- position: "right",
446
- title: "Discovery settings",
447
- size: 380,
448
- withOverlay: false,
449
- lockScroll: false,
450
- trapFocus: false,
451
- returnFocus: false,
452
- withinPortal: false,
453
- styles: {
454
- root: {
455
- position: "absolute",
456
- inset: 0,
457
- pointerEvents: "none"
458
- },
459
- inner: {
460
- position: "absolute",
461
- inset: 0,
462
- pointerEvents: "none"
463
- },
464
- content: {
465
- height: "100%",
466
- pointerEvents: "auto"
467
- }
468
- },
469
- children: /* @__PURE__ */ jsx(DiscoverySettingsContent, {
470
- methods,
471
- selectedMethodId,
472
- setSelectedMethodId: (id) => setSelectedMethodId(ocelId, id),
473
- selectedMethod,
474
- selectedSchema,
475
- activeFormData,
476
- setActiveFormData: (data) => selectedMethodId && setFormData(ocelId, selectedMethodId, data),
477
- eventCounts,
478
- objectCounts,
479
- errorMessage,
480
- availableFilters,
481
- filters,
482
- setFilters: (next) => setFiltersInStore(ocelId, next)
483
- })
97
+ /* @__PURE__ */ jsxs(Box, {
98
+ pos: "relative",
99
+ flex: 1,
100
+ mih: 0,
101
+ children: [/* @__PURE__ */ jsx(LoadingOverlay, { visible: isLoading }), currentMethod && id && /* @__PURE__ */ jsx(DiscoveryConfiguration, {
102
+ method: currentMethod,
103
+ ocelId: id,
104
+ onSuccess
105
+ }, `${currentMethod.id}:${id}`)]
484
106
  })
485
107
  ]
486
108
  });
487
109
  };
488
110
  const DiscoveryPage = () => {
489
- const { id: ocelId } = useCurrentOcel();
490
- if (!ocelId) return /* @__PURE__ */ jsx(LoadingOverlay, { visible: true });
491
- return /* @__PURE__ */ jsx(DiscoveryPageContent, { ocelId }, ocelId);
111
+ const [discoveryTask, setDiscoveryTask] = useState(void 0);
112
+ return /* @__PURE__ */ jsx(PluginDashboard, {
113
+ taskId: discoveryTask,
114
+ withHandle: false,
115
+ collapseOnNoTask: false,
116
+ children: /* @__PURE__ */ jsx(DiscoverySideBar, { onSuccess: (discoveryTaskId) => setDiscoveryTask(discoveryTaskId) })
117
+ });
492
118
  };
119
+ var DiscoveryPage_default = defineModuleRoute({
120
+ label: "Discovery",
121
+ name: "discovery",
122
+ component: DiscoveryPage,
123
+ requiresOcel: true
124
+ });
493
125
  //#endregion
494
126
  //#region src/index.ts
495
127
  var src_default = defineModule({
@@ -497,12 +129,7 @@ var src_default = defineModule({
497
129
  description: "A tool for discovering object-centric event logs, allowing you create various plots like OC-DFGs or OC-Petri-Nets.",
498
130
  label: "Model Discovery",
499
131
  authors: [{ name: "Menne, Sebastian" }],
500
- routes: [defineModuleRoute({
501
- component: DiscoveryPage,
502
- label: "Discovery",
503
- name: "discovery",
504
- requiresOcel: true
505
- })],
132
+ routes: [DiscoveryPage_default],
506
133
  icon: ChartNetwork
507
134
  });
508
135
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ocelescope/discovery",
3
3
  "type": "module",
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "description": "A module for discovery of OCELs",
6
6
  "author": "Sebastian Menne <sebastian.menne@rwth-aachen.de>",
7
7
  "license": "MIT",
@@ -30,6 +30,10 @@
30
30
  "@mantine/carousel": "^9.5.1",
31
31
  "@mantine/core": "^9.5.1",
32
32
  "@mantine/hooks": "^9.5.1",
33
+ "@ocelescope/api-base": "^0.9.0",
34
+ "@ocelescope/core": "^0.9.0",
35
+ "@ocelescope/plugin-components": "^0.9.0",
36
+ "@ocelescope/resources": "^0.9.0",
33
37
  "@rjsf/core": "^6.8.0",
34
38
  "@rjsf/mantine": "^6.8.0",
35
39
  "@rjsf/utils": "^6.8.0",
@@ -38,23 +42,20 @@
38
42
  "embla-carousel": "^8.6.0",
39
43
  "embla-carousel-react": "^8.6.0",
40
44
  "lucide-react": "^1.0.0",
41
- "next": "16.3.0",
42
- "react": "^19.2.8",
43
- "react-dom": "^19.2.8",
45
+ "next": "16.3.6",
46
+ "react": "^19.3.0",
47
+ "react-dom": "^19.3.0",
44
48
  "react-hook-form": "^7.71.2",
45
49
  "uniqolor": "^1.1.1",
46
- "zustand": "^5.0.11",
47
- "@ocelescope/api-base": "^0.7.0",
48
- "@ocelescope/core": "^0.7.0",
49
- "@ocelescope/resources": "^0.7.0"
50
+ "zustand": "^5.0.15"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@rjsf/mantine": "^6.8.0",
53
54
  "@types/file-saver": "^2.0.7",
54
- "@types/node": "^26.2.0",
55
- "@types/react": "^19.2.18",
56
- "@types/react-dom": "^19.2.4",
57
- "tsdown": "^0.22.14",
55
+ "@types/node": "^26.6.1",
56
+ "@types/react": "^19.3.0",
57
+ "@types/react-dom": "^19.3.0",
58
+ "tsdown": "^0.23.0",
58
59
  "typescript": "^6.0.3"
59
60
  },
60
61
  "scripts": {