@ocelescope/plugin 0.6.0 → 0.8.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 +150 -565
  2. package/package.json +17 -28
package/dist/index.js CHANGED
@@ -1,201 +1,48 @@
1
- import { BarList, FileDropzone, FullScreenUpload, OcelSelect, defineModule, defineModuleRoute, env, getModuleRoute, useInvalidate } from "@ocelescope/core";
2
- import { CheckIcon, Columns2Icon, DatabaseIcon, DownloadIcon, EllipsisVertical, PuzzleIcon, Rows2Icon, Trash2Icon, UploadIcon } from "lucide-react";
1
+ import { FileDropzone, FullScreenUpload, OcelSelect, defineModule, defineModuleRoute, env, getModuleRoute } from "@ocelescope/core";
2
+ import { EllipsisVertical, PuzzleIcon, Trash2Icon, UploadIcon } from "lucide-react";
3
3
  import { useRouter } from "next/router.js";
4
- import { ActionIcon, Anchor, Badge, Box, Breadcrumbs, Button, Card, Center, Container, Divider, Flex, Group, Loader, LoadingOverlay, Menu, Modal, MultiSelect, ScrollArea, Select, SimpleGrid, Splitter, Stack, Switch, Text, ThemeIcon, Title, Tooltip } from "@mantine/core";
5
- import { useDeletePlugin, useDisableDiscoveryMethod, useDownloadPluginResults, useEnableDiscoveryMethod, useEventAttributes, useEventCounts, useEventIds, useGetComputedValues, useGetExtensionMeta, useGetPlugin, useGetPluginMethod, useGetResourceMeta, useListDiscoveryMethods, useObjectAttributes, useObjectCounts, useObjectIds, usePluginResult, usePlugins, useRunPlugin, useSavePluginResults, useUpload } from "@ocelescope/api-base";
6
- import { memo, useCallback, useEffect, useMemo, useState } from "react";
7
- import { ResourceSelect, Visualization } from "@ocelescope/resources";
4
+ import { ActionIcon, Anchor, Badge, Breadcrumbs, Button, Card, Container, Group, LoadingOverlay, Menu, Modal, ScrollArea, SimpleGrid, Splitter, Stack, Text, ThemeIcon, Title } from "@mantine/core";
5
+ import { useDeletePlugin, useGetPlugin, useGetPluginMethod, usePlugins, useRunPlugin, useUpload } from "@ocelescope/api-base";
6
+ import { PluginForm, ResultSection } from "@ocelescope/plugin-components";
7
+ import { useCallback, useMemo, useState } from "react";
8
+ import { ResourceSelect } from "@ocelescope/resources";
8
9
  import { Controller, useForm, useWatch } from "react-hook-form";
9
- import RefParser from "@apidevtools/json-schema-ref-parser";
10
- import validator from "@rjsf/validator-ajv8";
11
- import { unflatten } from "flat";
12
- import traverse from "json-schema-traverse";
13
- import { keepPreviousData } from "@tanstack/react-query";
14
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
- import { useDebouncedValue } from "@mantine/hooks";
16
- import dynamic from "next/dynamic.js";
17
11
  import Link from "next/link.js";
18
12
  import { generateColor } from "@marko19907/string-to-color";
19
- //#region src/components/Form/Fields/custom.tsx
20
- const useSelectOptions = ({ pluginId, methodName, provider, control }) => {
21
- const formValues = useWatch({ control });
22
- const { data } = useGetComputedValues(pluginId, methodName, provider, {
23
- input: formValues.input,
24
- input_ocels: Object.fromEntries(Object.entries(formValues.input_ocels ?? {}).filter(([_, v]) => !!v && v.length >= 0)),
25
- input_resources: Object.fromEntries(Object.entries(formValues.input_resources ?? {}).filter(([_, v]) => !!v && v.length >= 0))
26
- }, { query: {
27
- placeholderData: keepPreviousData,
28
- refetchOnWindowFocus: false,
29
- refetchOnReconnect: false
30
- } });
31
- return { options: data };
32
- };
33
- const getComputedSelect = ({ pluginId, methodName, control }) => ({ computed_select: memo(({ schema, required, formData, onChange, fieldPathId: { path } }) => {
34
- const meta = schema?.["x-ui-meta"];
35
- const SelectComponent = schema.type === "array" ? MultiSelect : Select;
36
- const { options } = useSelectOptions({
37
- pluginId,
38
- methodName,
13
+ //#region src/components/Form/index.tsx
14
+ const compact = (record) => Object.fromEntries(Object.entries(record ?? {}).filter(([, value]) => !!value));
15
+ const ConfigurationSection = ({ control, schema, pluginId, methodName, onSubmit }) => {
16
+ const inputResources = useWatch({
39
17
  control,
40
- provider: meta.provider
41
- });
42
- return /* @__PURE__ */ jsx(SelectComponent, {
43
- label: schema.title,
44
- description: schema.description,
45
- required,
46
- value: formData ?? (schema.type === "array" ? [] : null),
47
- onChange: (value) => onChange(value, path),
48
- data: options
49
- });
50
- }) });
51
- //#endregion
52
- //#region src/components/Form/Fields/ocel.tsx
53
- const AttributeSelector = (query) => ({ isMulti, ocelId, onChange, value, label, required, description }) => {
54
- const { data: attributes = [] } = query(ocelId);
55
- const attributeNames = new Set(attributes.map(({ name }) => name));
56
- return /* @__PURE__ */ jsx(isMulti ? MultiSelect : Select, {
57
- value: value ?? (isMulti ? [] : null),
58
- label,
59
- onChange,
60
- required,
61
- description,
62
- clearable: true,
63
- data: [...attributeNames]
64
- });
65
- };
66
- const TypeSelector = (query) => ({ ocelId, onChange, required, value, isMulti, label, description }) => {
67
- const { data = {} } = query(ocelId);
68
- return /* @__PURE__ */ jsx(isMulti ? MultiSelect : Select, {
69
- value: value ?? (isMulti ? [] : null),
70
- label,
71
- required,
72
- clearable: true,
73
- description,
74
- onChange,
75
- data: Object.keys(data)
76
- });
77
- };
78
- const IdSelect = (query) => ({ ocelId, isMulti, value, ...rest }) => {
79
- const [searchValue, setSearchValue] = useState();
80
- const [debouncedSearch] = useDebouncedValue(searchValue, 300);
81
- const { data: ids } = query(ocelId, { search: debouncedSearch });
82
- return /* @__PURE__ */ jsx(isMulti ? MultiSelect : Select, {
83
- searchable: true,
84
- searchValue,
85
- onSearchChange: (newSearchValue) => setSearchValue(newSearchValue),
86
- data: ids?.response,
87
- value: value ?? (isMulti ? [] : null),
88
- ...rest
89
- });
90
- };
91
- const ocelFieldMap = {
92
- event_type: TypeSelector(useEventCounts),
93
- object_type: TypeSelector(useObjectCounts),
94
- event_attribute: AttributeSelector(useEventAttributes),
95
- object_attribute: AttributeSelector(useObjectAttributes),
96
- event_id: IdSelect(useEventIds),
97
- object_id: IdSelect(useObjectIds)
98
- };
99
- const wrapFieldsWithContext = (control) => {
100
- const wrapped = {};
101
- for (const [name, Field] of Object.entries(ocelFieldMap)) {
102
- const Comp = ({ schema, required, formData, fieldPathId: { path }, onChange }) => {
103
- const ocelRef = schema?.["x-ui-meta"]?.ocel_id;
104
- const isMulti = schema?.type === "array";
105
- const ocelId = useWatch({
106
- control,
107
- name: `input_ocels.${ocelRef}`
108
- });
109
- return /* @__PURE__ */ jsx(Field, {
110
- label: schema?.title,
111
- required,
112
- description: schema?.description,
113
- isMulti,
114
- onChange: (data) => onChange(data, path),
115
- value: formData,
116
- ocelId
117
- });
118
- };
119
- wrapped[name] = memo(Comp);
120
- }
121
- return wrapped;
122
- };
123
- //#endregion
124
- //#region src/components/Form/MantineForm.tsx
125
- const Form = dynamic(() => import("@rjsf/mantine").then((m) => m.Form), { ssr: false });
126
- //#endregion
127
- //#region src/components/Form/PluginForm.tsx
128
- const buildUiSchemaV2 = async ({ schema }) => {
129
- const deref = await RefParser.dereference(schema, { dereference: { circular: "ignore" } });
130
- const uiSchema = {};
131
- traverse(deref, {
132
- allKeys: true,
133
- cb: (subschema, pointer) => {
134
- const pointerComponents = pointer.split("/").slice(1);
135
- if (pointerComponents[0] !== "properties") return;
136
- if (pointerComponents[0] === "properties" && pointerComponents.at(-1) === "x-ui-meta") {
137
- const path = pointerComponents.filter((pathComponent) => !["x-ui-meta", "properties"].includes(pathComponent)).join(".");
138
- uiSchema[path] = { "ui:field": subschema.field_type ?? subschema.type };
139
- }
140
- }
18
+ name: "input_resources"
141
19
  });
142
- return unflatten(uiSchema);
143
- };
144
- const PluginForm = ({ schema, control, pluginId, methodName, onSubmit }) => {
145
- const [uiSchema, setUiSchema] = useState(void 0);
146
- useEffect(() => {
147
- let cancelled = false;
148
- (async () => {
149
- const ui = await buildUiSchemaV2({ schema });
150
- if (!cancelled) setUiSchema(ui);
151
- })();
152
- return () => {
153
- cancelled = true;
154
- };
155
- }, [schema]);
156
- const fields = useMemo(() => wrapFieldsWithContext(control), [control]);
157
- const computedFields = useMemo(() => getComputedSelect({
158
- methodName,
159
- pluginId,
160
- control
161
- }), [
162
- methodName,
163
- pluginId,
164
- control
165
- ]);
166
20
  return /* @__PURE__ */ jsx(Controller, {
167
21
  control,
168
22
  name: "input",
169
- render: ({ field }) => /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Form, {
170
- schema: {
171
- ...schema,
172
- title: ""
173
- },
23
+ render: ({ field }) => /* @__PURE__ */ jsx(PluginForm, {
24
+ pluginId,
25
+ methodName,
26
+ schema,
27
+ inputResources,
174
28
  formData: field.value,
175
- validator,
176
- uiSchema,
177
- fields: {
178
- ...fields,
179
- ...computedFields
180
- },
181
- onChange: (data) => {
182
- field.onChange(data.formData);
183
- },
29
+ onChange: ({ formData }) => field.onChange(formData),
184
30
  onSubmit
185
- }) })
31
+ })
186
32
  });
187
33
  };
188
- //#endregion
189
- //#region src/components/Form/index.tsx
190
34
  const PluginInput = ({ pluginId, method, onSuccess }) => {
191
35
  const { mutate: runPlugin } = useRunPlugin({ mutation: { onSuccess } });
192
- const { control, handleSubmit } = useForm({ defaultValues: {
193
- input_ocels: Object.fromEntries(Object.keys(method.input_ocels ?? {}).map((name) => [name, void 0])),
194
- input_resources: Object.fromEntries(Object.keys(method.input_resources ?? {}).map((name) => [name, void 0])),
36
+ const defaultValue = {
37
+ input_resources: Object.fromEntries(method.inputs.map(({ name }) => [name, void 0])),
195
38
  formData: {}
196
- } });
197
- const onSubmit = useCallback(() => handleSubmit((data) => runPlugin({
198
- data,
39
+ };
40
+ const { control, handleSubmit } = useForm({ defaultValues: defaultValue });
41
+ const onSubmit = useCallback(() => handleSubmit(({ input_resources, input }) => runPlugin({
42
+ data: {
43
+ input_resources: compact(input_resources),
44
+ input
45
+ },
199
46
  methodName: method.name,
200
47
  pluginId
201
48
  }))(), [
@@ -206,46 +53,40 @@ const PluginInput = ({ pluginId, method, onSuccess }) => {
206
53
  ]);
207
54
  return /* @__PURE__ */ jsxs(Stack, {
208
55
  gap: "md",
209
- children: [
210
- Object.entries(method.input_ocels ?? {}).map(([name, { label, description, extension }]) => /* @__PURE__ */ jsx(Controller, {
211
- control,
212
- name: `input_ocels.${name}`,
213
- rules: { required: "Please select a value" },
214
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(OcelSelect, {
215
- label,
216
- required: true,
217
- extension: extension ?? void 0,
218
- description,
219
- error: fieldState.error?.message,
220
- onChange: field.onChange,
221
- value: field.value
222
- })
223
- }, name)),
224
- Object.entries(method.input_resources ?? {}).map(([name, [resource_type, { label, description }]]) => /* @__PURE__ */ jsx(Controller, {
225
- control,
226
- name: `input_resources.${name}`,
227
- rules: { required: "Please select a value" },
228
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(ResourceSelect, {
229
- label,
230
- required: true,
231
- type: resource_type,
232
- description,
233
- onChange: field.onChange,
234
- error: fieldState.error?.message,
235
- value: field.value
236
- })
237
- }, name)),
238
- method.input_schema ? /* @__PURE__ */ jsx(PluginForm, {
239
- pluginId,
240
- methodName: method.name,
241
- schema: method.input_schema,
242
- control,
243
- onSubmit
244
- }) : /* @__PURE__ */ jsx(Button, {
245
- onClick: onSubmit,
246
- children: "Submit"
56
+ children: [method.inputs.map((io) => /* @__PURE__ */ jsx(Controller, {
57
+ control,
58
+ name: `input_resources.${io.name}`,
59
+ rules: !io.is_optional ? { required: "Please select a value" } : {},
60
+ render: ({ field, fieldState }) => io.type === "ocel" ? /* @__PURE__ */ jsx(OcelSelect, {
61
+ label: io.label,
62
+ clearable: io.is_optional,
63
+ required: !io.is_optional,
64
+ description: io.description,
65
+ searchable: true,
66
+ error: fieldState.error?.message,
67
+ onChange: field.onChange,
68
+ value: field.value
69
+ }) : /* @__PURE__ */ jsx(ResourceSelect, {
70
+ clearable: io.is_optional,
71
+ label: io.label,
72
+ required: !io.is_optional,
73
+ type: io.schema_id,
74
+ description: io.description,
75
+ onChange: field.onChange,
76
+ error: fieldState.error?.message,
77
+ value: field.value,
78
+ searchable: true
247
79
  })
248
- ]
80
+ }, io.name)), method.configuration_schema ? /* @__PURE__ */ jsx(ConfigurationSection, {
81
+ control,
82
+ pluginId,
83
+ methodName: method.name,
84
+ schema: method.configuration_schema,
85
+ onSubmit
86
+ }) : /* @__PURE__ */ jsx(Button, {
87
+ onClick: onSubmit,
88
+ children: "Submit"
89
+ })]
249
90
  });
250
91
  };
251
92
  //#endregion
@@ -272,7 +113,7 @@ const PluginBreadcrumbs = () => {
272
113
  pluginId: plugin?.id,
273
114
  methodName: void 0
274
115
  } },
275
- children: plugin?.meta.label
116
+ children: plugin?.label
276
117
  }),
277
118
  pluginMethod && /* @__PURE__ */ jsx(Anchor, {
278
119
  component: Link,
@@ -286,186 +127,6 @@ const PluginBreadcrumbs = () => {
286
127
  ] });
287
128
  };
288
129
  //#endregion
289
- //#region src/components/ResultSection/ResultSection.tsx
290
- const ResourceView = ({ resource }) => {
291
- return /* @__PURE__ */ jsx(Visualization, { visualization: resource.visualization });
292
- };
293
- const OCELView = ({ ocel }) => {
294
- return /* @__PURE__ */ jsxs(Stack, {
295
- gap: "md",
296
- children: [/* @__PURE__ */ jsx(BarList, {
297
- data: ocel.activity_count,
298
- labelHeader: "Activity"
299
- }), /* @__PURE__ */ jsx(BarList, {
300
- data: ocel.object_count,
301
- labelHeader: "Object type"
302
- })]
303
- });
304
- };
305
- const entityTypeOf = (output) => output.type === "ocel" ? "ocel" : output.resource_type || "resource";
306
- const ResultLabel = ({ label, entityType, bold }) => /* @__PURE__ */ jsxs(Group, {
307
- gap: "xs",
308
- wrap: "nowrap",
309
- children: [/* @__PURE__ */ jsx(Text, {
310
- fw: bold ? 600 : void 0,
311
- truncate: true,
312
- children: label
313
- }), /* @__PURE__ */ jsx(Badge, {
314
- size: "sm",
315
- color: generateColor(entityType),
316
- children: entityType
317
- })]
318
- });
319
- const ResultSection = ({ pluginId, methodName, taskId }) => {
320
- const { data: pluginSummary } = usePluginResult(pluginId, methodName, taskId, { query: { refetchInterval: ({ state }) => {
321
- if (state.data == null) return 1e3;
322
- return false;
323
- } } });
324
- const [selected, setSelected] = useState([0]);
325
- const [orientation, setOrientation] = useState("vertical");
326
- const { mutate: saveResults, isPending: isSaving, isSuccess: isSaved, reset: resetSave } = useSavePluginResults();
327
- const { mutate: downloadResults, isPending: isDownloading } = useDownloadPluginResults({ request: { responseType: "blob" } });
328
- const options = useMemo(() => (pluginSummary ?? []).map((output) => {
329
- return {
330
- value: output.result_index,
331
- label: entityTypeOf(output),
332
- entityType: output.type
333
- };
334
- }), [pluginSummary]);
335
- if (!pluginSummary) return /* @__PURE__ */ jsx(Center, {
336
- h: "100%",
337
- children: /* @__PURE__ */ jsxs(Stack, {
338
- align: "center",
339
- gap: "sm",
340
- children: [/* @__PURE__ */ jsx(Loader, {}), /* @__PURE__ */ jsx(Text, {
341
- c: "dimmed",
342
- children: "Running…"
343
- })]
344
- })
345
- });
346
- if (pluginSummary.length === 0) return /* @__PURE__ */ jsx(Center, {
347
- h: "100%",
348
- children: /* @__PURE__ */ jsx(Text, {
349
- c: "dimmed",
350
- children: "This run produced no results."
351
- })
352
- });
353
- const handleSelectionChange = (value) => {
354
- setSelected(value);
355
- resetSave();
356
- };
357
- const handleDownload = () => {
358
- downloadResults({
359
- pluginId,
360
- methodName,
361
- taskId,
362
- data: { indices: selected }
363
- }, { onSuccess: (data) => {
364
- const url = URL.createObjectURL(data);
365
- const anchor = document.createElement("a");
366
- anchor.href = url;
367
- anchor.download = `${methodName}_results.zip`;
368
- anchor.click();
369
- URL.revokeObjectURL(url);
370
- } });
371
- };
372
- const handleSaveToSession = () => {
373
- saveResults({
374
- pluginId,
375
- methodName,
376
- taskId,
377
- data: { indices: selected }
378
- });
379
- };
380
- return /* @__PURE__ */ jsxs(Stack, {
381
- gap: 0,
382
- h: "100%",
383
- children: [/* @__PURE__ */ jsxs(Group, {
384
- px: "sm",
385
- py: "xs",
386
- wrap: "nowrap",
387
- style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
388
- children: [options.length > 1 ? /* @__PURE__ */ jsx(MultiSelect, {
389
- flex: 1,
390
- data: options,
391
- onChange: handleSelectionChange,
392
- value: selected,
393
- placeholder: "Select results to display",
394
- searchable: true,
395
- clearable: true,
396
- comboboxProps: { withinPortal: true },
397
- renderOption: ({ option }) => {
398
- const output = pluginSummary[Number(option.value)];
399
- return /* @__PURE__ */ jsx(ResultLabel, {
400
- label: option.label,
401
- entityType: output ? entityTypeOf(output) : option.label
402
- });
403
- }
404
- }) : options[0] && /* @__PURE__ */ jsx(ResultLabel, {
405
- label: options[0].label,
406
- entityType: options[0].entityType,
407
- bold: true
408
- }), /* @__PURE__ */ jsxs(Group, {
409
- gap: "xs",
410
- ml: "auto",
411
- wrap: "nowrap",
412
- children: [
413
- selected.length > 1 && /* @__PURE__ */ jsx(Tooltip, {
414
- label: orientation === "vertical" ? "Show side by side" : "Stack vertically",
415
- children: /* @__PURE__ */ jsx(ActionIcon, {
416
- variant: "default",
417
- size: "lg",
418
- onClick: () => setOrientation((prev) => prev === "vertical" ? "horizontal" : "vertical"),
419
- children: orientation === "vertical" ? /* @__PURE__ */ jsx(Columns2Icon, { size: 16 }) : /* @__PURE__ */ jsx(Rows2Icon, { size: 16 })
420
- })
421
- }),
422
- /* @__PURE__ */ jsx(Button, {
423
- variant: "default",
424
- leftSection: /* @__PURE__ */ jsx(DownloadIcon, { size: 16 }),
425
- onClick: handleDownload,
426
- loading: isDownloading,
427
- disabled: selected.length === 0,
428
- children: "Download"
429
- }),
430
- /* @__PURE__ */ jsx(Button, {
431
- variant: "light",
432
- color: isSaved ? "green" : void 0,
433
- leftSection: isSaved ? /* @__PURE__ */ jsx(CheckIcon, { size: 16 }) : /* @__PURE__ */ jsx(DatabaseIcon, { size: 16 }),
434
- onClick: handleSaveToSession,
435
- loading: isSaving,
436
- disabled: selected.length === 0,
437
- children: isSaved ? "Saved" : "Save to session"
438
- })
439
- ]
440
- })]
441
- }), selected.length === 0 ? /* @__PURE__ */ jsx(Center, {
442
- style: { flex: 1 },
443
- children: /* @__PURE__ */ jsx(Text, {
444
- c: "dimmed",
445
- children: "Select one or more results to display."
446
- })
447
- }) : /* @__PURE__ */ jsx(Splitter, {
448
- orientation,
449
- lineSize: 4,
450
- handleColor: "var(--mantine-color-default-border)",
451
- style: {
452
- flex: 1,
453
- minHeight: 0
454
- },
455
- children: pluginSummary?.filter(({ result_index }) => selected.includes(result_index)).map((output, index) => /* @__PURE__ */ jsx(Splitter.Pane, {
456
- defaultSize: 100 / selected.length,
457
- min: "15%",
458
- children: /* @__PURE__ */ jsx(Box, {
459
- h: "100%",
460
- p: "xs",
461
- pos: "relative",
462
- children: output.type === "ocel" ? /* @__PURE__ */ jsx(OCELView, { ocel: output }) : /* @__PURE__ */ jsx(ResourceView, { resource: output })
463
- })
464
- }, index))
465
- }, `${orientation}:${selected.join(",")}`)]
466
- });
467
- };
468
- //#endregion
469
130
  //#region src/pages/MethodPage.tsx
470
131
  const COLLAPSED_SIZES = [0, 100];
471
132
  const SPLIT_SIZES = [75, 25];
@@ -478,78 +139,53 @@ const MethodPage = ({ pluginId, methodName }) => {
478
139
  setCurrentTask(taskId);
479
140
  setSizes((prev) => prev[0] === 0 ? SPLIT_SIZES : prev);
480
141
  };
481
- return /* @__PURE__ */ jsx(Flex, {
482
- direction: "column",
142
+ return /* @__PURE__ */ jsxs(Splitter, {
143
+ sizes,
144
+ onSizeChange: setSizes,
145
+ lineSize: 4,
146
+ handleColor: "var(--mantine-color-default-border)",
483
147
  h: "100%",
484
- children: /* @__PURE__ */ jsxs(Splitter, {
485
- sizes,
486
- onSizeChange: setSizes,
487
- lineSize: 4,
488
- handleColor: "var(--mantine-color-default-border)",
489
- px: "xs",
490
- style: {
491
- flex: 1,
492
- minHeight: 0
493
- },
494
- children: [/* @__PURE__ */ jsx(Splitter.Pane, {
495
- defaultSize: 0,
496
- min: "20%",
497
- collapsible: true,
498
- children: /* @__PURE__ */ jsx(Box, {
499
- h: "100%",
500
- pos: "relative",
501
- style: { overflow: "hidden" },
502
- children: currentTask ? /* @__PURE__ */ jsx(ResultSection, {
503
- pluginId,
504
- methodName,
505
- taskId: currentTask
506
- }) : /* @__PURE__ */ jsx(Center, {
507
- h: "100%",
508
- p: "md",
509
- children: /* @__PURE__ */ jsx(Text, {
148
+ children: [/* @__PURE__ */ jsx(Splitter.Pane, {
149
+ defaultSize: 0,
150
+ min: "20%",
151
+ collapsible: true,
152
+ children: /* @__PURE__ */ jsx(ResultSection, { taskId: currentTask })
153
+ }), /* @__PURE__ */ jsx(Splitter.Pane, {
154
+ defaultSize: 100,
155
+ min: "20%",
156
+ collapsible: true,
157
+ children: /* @__PURE__ */ jsx(ScrollArea, {
158
+ h: "100%",
159
+ type: "auto",
160
+ children: /* @__PURE__ */ jsxs(Stack, {
161
+ gap: "sm",
162
+ p: "md",
163
+ maw: 640,
164
+ mx: "auto",
165
+ w: "100%",
166
+ children: [
167
+ /* @__PURE__ */ jsx(Group, {
168
+ justify: "center",
169
+ children: /* @__PURE__ */ jsx(PluginBreadcrumbs, {})
170
+ }),
171
+ /* @__PURE__ */ jsx(Title, {
172
+ ta: "center",
173
+ children: pluginMethod.label ?? methodName
174
+ }),
175
+ pluginMethod.description && /* @__PURE__ */ jsx(Text, {
510
176
  c: "dimmed",
511
177
  ta: "center",
512
- children: "Run the method to see its results here."
178
+ children: pluginMethod.description
179
+ }),
180
+ /* @__PURE__ */ jsx(PluginInput, {
181
+ onSuccess: handleSuccess,
182
+ pluginId,
183
+ method: pluginMethod
513
184
  })
514
- })
515
- })
516
- }), /* @__PURE__ */ jsx(Splitter.Pane, {
517
- defaultSize: 100,
518
- min: "20%",
519
- collapsible: true,
520
- children: /* @__PURE__ */ jsx(ScrollArea, {
521
- h: "100%",
522
- type: "auto",
523
- children: /* @__PURE__ */ jsxs(Stack, {
524
- gap: "sm",
525
- p: "md",
526
- maw: 640,
527
- mx: "auto",
528
- w: "100%",
529
- children: [
530
- /* @__PURE__ */ jsx(Group, {
531
- justify: "center",
532
- children: /* @__PURE__ */ jsx(PluginBreadcrumbs, {})
533
- }),
534
- /* @__PURE__ */ jsx(Title, {
535
- ta: "center",
536
- children: pluginMethod.label ?? methodName
537
- }),
538
- pluginMethod.description && /* @__PURE__ */ jsx(Text, {
539
- c: "dimmed",
540
- ta: "center",
541
- children: pluginMethod.description
542
- }),
543
- /* @__PURE__ */ jsx(PluginInput, {
544
- onSuccess: handleSuccess,
545
- pluginId,
546
- method: pluginMethod
547
- })
548
- ]
549
- })
185
+ ]
550
186
  })
551
- })]
552
- })
187
+ })
188
+ })]
553
189
  });
554
190
  };
555
191
  //#endregion
@@ -614,111 +250,58 @@ const GenericCard = ({ menuItems, title, description, link, tags, version }) =>
614
250
  //#region src/pages/PluginPage.tsx
615
251
  const MethodCard = ({ method }) => {
616
252
  const { query } = useRouter();
617
- const { data: resourceMeta = {} } = useGetResourceMeta();
618
- const { data: extensionMeta = {} } = useGetExtensionMeta();
619
- const tags = useMemo(() => {
620
- const extensions = Object.values(method.input_ocels ?? {}).map(({ extension }) => extension ? extensionMeta[extension]?.label : void 0);
621
- const inputResources = Object.values(method.input_resources ?? {}).map(([resourceName]) => resourceMeta[resourceName]?.label ?? resourceName);
622
- const resultNames = (method.results ?? []).filter((result) => result.type === "resource").map((result) => resourceMeta[result.resource_type]?.label ?? result.resource_type);
623
- return Array.from(/* @__PURE__ */ new Set([
624
- ...inputResources,
625
- ...resultNames,
626
- ...extensions
627
- ])).filter((tag) => !!tag);
628
- }, [
629
- resourceMeta,
630
- extensionMeta,
631
- method
632
- ]);
253
+ const tags = Array.from(new Set([...method.inputs, ...method.outputs].map((io) => io.type === "ocel" ? "OCEL" : io.resource_label)));
633
254
  return /* @__PURE__ */ jsx(GenericCard, {
634
255
  title: method.label ?? method.name,
635
256
  description: method.description ?? "",
636
- tags,
637
257
  link: {
638
258
  href: { query: {
639
259
  ...query,
640
260
  methodName: method.name
641
261
  } },
642
262
  children: "Run Method"
643
- }
263
+ },
264
+ tags
644
265
  });
645
266
  };
646
267
  const PluginPage = ({ pluginId }) => {
647
268
  const { data: plugin } = useGetPlugin(pluginId);
648
- const { data: allMethods = [] } = useListDiscoveryMethods();
649
- const invalidate = useInvalidate();
650
- const onSuccess = () => invalidate(["discoveryMethods"]);
651
- const { mutate: disableMethod } = useDisableDiscoveryMethod({ mutation: { onSuccess } });
652
- const { mutate: enableMethod } = useEnableDiscoveryMethod({ mutation: { onSuccess } });
653
- const discoveryMethods = useMemo(() => allMethods.flatMap((meta) => meta.variants.filter((v) => v.pluginId === pluginId).map((v) => ({
654
- name: meta.name,
655
- variant: v
656
- }))), [allMethods, pluginId]);
657
- return /* @__PURE__ */ jsx(Container, {
269
+ return /* @__PURE__ */ jsxs(Container, {
658
270
  fluid: true,
659
- children: /* @__PURE__ */ jsxs(Stack, { children: [
660
- /* @__PURE__ */ jsxs(Stack, {
661
- gap: 0,
662
- align: "center",
663
- children: [
664
- /* @__PURE__ */ jsx(PluginBreadcrumbs, {}),
665
- /* @__PURE__ */ jsxs(Title, {
666
- mt: "xs",
667
- children: [" ", plugin?.meta.label]
668
- }),
669
- /* @__PURE__ */ jsx(Text, {
670
- c: "dimmed",
671
- children: plugin?.meta.description
672
- })
673
- ]
674
- }),
675
- /* @__PURE__ */ jsx(SimpleGrid, {
676
- cols: {
677
- base: 1,
678
- sm: 2,
679
- lg: 4
680
- },
681
- spacing: {
682
- base: 10,
683
- sm: "xl"
684
- },
685
- verticalSpacing: {
686
- base: "md",
687
- sm: "xl"
688
- },
689
- children: plugin?.methods.map((method) => /* @__PURE__ */ jsx(MethodCard, {
690
- method,
691
- pluginId: plugin.id
692
- }, method.name))
693
- }),
694
- discoveryMethods.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Divider, {}), /* @__PURE__ */ jsxs(Stack, {
695
- gap: "xs",
696
- children: [/* @__PURE__ */ jsx(Title, {
697
- order: 4,
698
- children: "Discovery Methods"
699
- }), discoveryMethods.map(({ name, variant }) => /* @__PURE__ */ jsxs(Group, {
700
- justify: "space-between",
701
- children: [/* @__PURE__ */ jsxs(Stack, {
702
- gap: 0,
703
- children: [/* @__PURE__ */ jsx(Text, {
704
- fw: 500,
705
- children: name
706
- }), variant.description && /* @__PURE__ */ jsx(Text, {
707
- size: "sm",
708
- c: "dimmed",
709
- children: variant.description
710
- })]
711
- }), /* @__PURE__ */ jsx(Switch, {
712
- label: "Active in Discovery",
713
- checked: variant.enabled ?? true,
714
- onChange: (e) => {
715
- if (e.currentTarget.checked) enableMethod({ methodId: variant.methodId });
716
- else disableMethod({ methodId: variant.methodId });
717
- }
718
- })]
719
- }, variant.methodId))]
720
- })] })
721
- ] })
271
+ p: "md",
272
+ children: [/* @__PURE__ */ jsxs(Stack, {
273
+ gap: 0,
274
+ align: "center",
275
+ children: [
276
+ /* @__PURE__ */ jsx(PluginBreadcrumbs, {}),
277
+ /* @__PURE__ */ jsxs(Title, {
278
+ mt: "xs",
279
+ children: [" ", plugin?.label]
280
+ }),
281
+ /* @__PURE__ */ jsx(Text, {
282
+ c: "dimmed",
283
+ children: plugin?.description
284
+ })
285
+ ]
286
+ }), /* @__PURE__ */ jsx(SimpleGrid, {
287
+ cols: {
288
+ base: 1,
289
+ sm: 2,
290
+ lg: 4
291
+ },
292
+ spacing: {
293
+ base: 10,
294
+ sm: "xl"
295
+ },
296
+ verticalSpacing: {
297
+ base: "md",
298
+ sm: "xl"
299
+ },
300
+ children: plugin?.methods.map((method) => /* @__PURE__ */ jsx(MethodCard, {
301
+ method,
302
+ pluginId: plugin.id
303
+ }, method.name))
304
+ })]
722
305
  });
723
306
  };
724
307
  //#endregion
@@ -734,7 +317,7 @@ const PluginUploadSection = ({ onSuccess }) => {
734
317
  //#endregion
735
318
  //#region src/components/PluginCard/PluginCard.tsx
736
319
  const PluginCard = ({ plugin }) => {
737
- const { description, label, version } = plugin.meta;
320
+ const { description, label, version } = plugin;
738
321
  const { mutate: deletePlugin } = useDeletePlugin();
739
322
  return /* @__PURE__ */ jsx(GenericCard, {
740
323
  title: label,
@@ -808,6 +391,7 @@ const PluginsOverview = () => {
808
391
  const { data: plugins } = usePlugins();
809
392
  return /* @__PURE__ */ jsxs(Stack, {
810
393
  gap: "md",
394
+ p: "md",
811
395
  children: [/* @__PURE__ */ jsxs("div", {
812
396
  style: { maxWidth: 720 },
813
397
  children: [/* @__PURE__ */ jsx(Title, {
@@ -880,6 +464,11 @@ const PluginRoute = () => {
880
464
  }
881
465
  return /* @__PURE__ */ jsx(PluginsOverview, {});
882
466
  };
467
+ var pages_default = defineModuleRoute({
468
+ name: "plugins",
469
+ label: "Plugins",
470
+ component: PluginRoute
471
+ });
883
472
  //#endregion
884
473
  //#region src/index.ts
885
474
  var src_default = defineModule({
@@ -887,11 +476,7 @@ var src_default = defineModule({
887
476
  description: "Run process mining plugins inside ocelescope",
888
477
  label: "Plugins",
889
478
  authors: [{ name: "Öztürk, Görkem-Emre" }],
890
- routes: [defineModuleRoute({
891
- name: "plugins",
892
- label: "Plugins",
893
- component: PluginRoute
894
- })],
479
+ routes: [pages_default],
895
480
  icon: PuzzleIcon
896
481
  });
897
482
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ocelescope/plugin",
3
3
  "type": "module",
4
- "version": "0.6.0",
4
+ "version": "0.8.0",
5
5
  "description": "A module for inspections of OCELs",
6
6
  "author": "Görkem-Emre Öztürk <goerkem.oeztuerk@rwth-aachen.de>",
7
7
  "license": "MIT",
@@ -27,40 +27,29 @@
27
27
  "access": "public"
28
28
  },
29
29
  "peerDependencies": {
30
- "@apidevtools/json-schema-ref-parser": "^15.5.0",
31
- "@mantine/carousel": "^9.4.2",
32
- "@mantine/core": "^9.4.2",
33
- "@mantine/hooks": "^9.4.2",
30
+ "@mantine/carousel": "^9.5.1",
31
+ "@mantine/core": "^9.5.1",
32
+ "@mantine/hooks": "^9.5.1",
34
33
  "@marko19907/string-to-color": "^1.0.2",
35
- "@rjsf/core": "^6.7.0",
36
- "@rjsf/mantine": "^6.7.0",
37
- "@rjsf/utils": "^6.7.0",
38
- "@rjsf/validator-ajv8": "^6.7.0",
39
- "@tanstack/react-query": "^5.90.21",
34
+ "@ocelescope/api-base": "^0.8.0",
35
+ "@ocelescope/core": "^0.8.0",
36
+ "@ocelescope/plugin-components": "^0.8.0",
37
+ "@ocelescope/resources": "^0.8.0",
40
38
  "embla-carousel": "^8.6.0",
41
39
  "embla-carousel-react": "^8.6.0",
42
- "flat": "^6.0.1",
43
- "json-schema-traverse": "^1.0.0",
44
40
  "lucide-react": "^1.0.0",
45
- "next": "^16.2.10",
46
- "react": "^19.2.7",
47
- "react-dom": "^19.2.7",
48
- "react-hook-form": "^7.71.2",
49
- "@ocelescope/api-base": "^0.6.0",
50
- "@ocelescope/resources": "^0.6.0",
51
- "@ocelescope/core": "^0.6.0"
41
+ "next": "16.3.2",
42
+ "react": "^19.3.0",
43
+ "react-dom": "^19.3.0",
44
+ "react-hook-form": "^7.71.2"
52
45
  },
53
46
  "devDependencies": {
54
- "@apidevtools/json-schema-ref-parser": "^15.5.0",
55
- "@rjsf/mantine": "^6.7.0",
56
47
  "@types/file-saver": "^2.0.7",
57
- "@types/node": "^26.1.1",
58
- "@types/react": "^19.2.17",
59
- "@types/react-dom": "^19.2.3",
60
- "flat": "^6.0.1",
61
- "json-schema-traverse": "^1.0.0",
62
- "tsdown": "^0.22.12",
63
- "typescript": "^5.9.3"
48
+ "@types/node": "^26.6.1",
49
+ "@types/react": "^19.3.0",
50
+ "@types/react-dom": "^19.3.0",
51
+ "tsdown": "^0.23.0",
52
+ "typescript": "^6.0.3"
64
53
  },
65
54
  "scripts": {
66
55
  "build": "tsdown",