@ocelescope/ocelot 0.0.0 → 0.1.2

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 CHANGED
@@ -1,29 +1,47 @@
1
- # react-components-starter
1
+ # @ocelescope/ocelot
2
2
 
3
- A starter for creating a React component library.
3
+ The **Ocelot** module for [Ocelescope](https://github.com/promi4s/ocelescope).
4
4
 
5
- ## Development
5
+ A tool for exploring object-centric event logs, allowing you to search events and objects and visualize their relationships and attributes.
6
6
 
7
- - Install dependencies:
7
+ It is a frontend module that plugs into the Ocelescope app shell via
8
+ `@ocelescope/core`'s `defineModule`.
8
9
 
9
- ```bash
10
- npm install
11
- ```
10
+ It pairs with the [`ocelescope-module-ocelot`](https://pypi.org/project/ocelescope-module-ocelot/)
11
+ backend module, which provides its API.
12
12
 
13
- - Run the playground:
13
+ ## Installation
14
14
 
15
15
  ```bash
16
- npm run play
16
+ pnpm add @ocelescope/ocelot
17
17
  ```
18
18
 
19
- - Run the unit tests:
19
+ ## Integration
20
20
 
21
- ```bash
22
- npm run test
21
+ Register the module in your `ocelescope.config.ts` by adding its default
22
+ export to the `modules` array:
23
+
24
+ ```ts
25
+ // ocelescope.config.ts
26
+ import type { OcelescopeConfig } from "@ocelescope/core";
27
+ import ocelot from "@ocelescope/ocelot";
28
+
29
+ export default {
30
+ modules: [ocelot],
31
+ } satisfies OcelescopeConfig;
23
32
  ```
24
33
 
25
- - Build the library:
34
+ This module ships its own styles, so also import them once in your app
35
+ entry point (`pages/_app.tsx`):
26
36
 
27
- ```bash
28
- npm run build
37
+ ```tsx
38
+ import "@ocelescope/ocelot/styles.css";
29
39
  ```
40
+
41
+ ## About
42
+
43
+ Part of [Ocelescope](https://github.com/promi4s/ocelescope), a framework for
44
+ working with Object-Centric Event Logs (OCEL) developed at the Chair of Process
45
+ and Data Science (PADS), RWTH Aachen University.
46
+
47
+ 📖 Documentation: <https://www.ocelescope.org>
package/dist/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import * as _ocelescope_core0 from "@ocelescope/core";
2
-
3
1
  //#region src/config.d.ts
4
- declare const _default: _ocelescope_core0.ModuleDefinition;
2
+ declare const _default: import("@ocelescope/core").ModuleDefinition;
5
3
  //#endregion
6
4
  export { _default as default };
package/dist/index.js CHANGED
@@ -1,56 +1,346 @@
1
1
  import { defineModule, defineModuleRoute, useCurrentOcel } from "@ocelescope/core";
2
- import { ActionIcon, Box, Button, Divider, Flex, Group, Input, LoadingOverlay, ScrollArea, SegmentedControl, SimpleGrid, Stack, Table, Tabs, Text } from "@mantine/core";
3
- import { useE2o, useEventAttributes, useEventCounts, useO2o, useObjectAttributes, useObjectCounts, useOcelotPaginatedEvents, useOcelotPaginatedObjects } from "@ocelescope/api-base";
4
- import { keepPreviousData } from "@tanstack/react-query";
5
- import { memo, useCallback, useEffect, useMemo, useState } from "react";
6
- import { DataTable } from "mantine-datatable";
7
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { ActionIcon, Box, Button, Divider, Flex, Group, Input, LoadingOverlay, ScrollArea, SegmentedControl, SimpleGrid, Stack, Table, Tabs, Text, Title } from "@mantine/core";
8
4
  import { useDebouncedState, useScrollIntoView } from "@mantine/hooks";
5
+ import { useE2o, useEventAttributes, useEventCounts, useO2o, useObjectAttributes, useObjectCounts } from "@ocelescope/api-base";
9
6
  import { ChevronLeftIcon, ChevronRightIcon, DownloadIcon, SearchIcon } from "lucide-react";
7
+ import { memo, useCallback, useEffect, useMemo, useState } from "react";
8
+ import { keepPreviousData, useQuery } from "@tanstack/react-query";
9
+ import { customFetch } from "@ocelescope/api-client";
10
+ import { DataTable } from "mantine-datatable";
10
11
  import { BaseEdge, Controls, EdgeLabelRenderer, Handle, MarkerType, Position, ReactFlow, ReactFlowProvider, applyNodeChanges, getSmoothStepPath, getStraightPath, useEdgesState, useInternalNode, useReactFlow } from "@xyflow/react";
11
- import { saveAs } from "file-saver";
12
+ import FileSaver from "file-saver";
12
13
  import { toPng } from "html-to-image";
13
14
  import dagre from "@dagrejs/dagre";
14
15
  import ELK from "elkjs/lib/elk.bundled.js";
15
-
16
- //#region src/components/EntityTable.tsx
17
- const EntityTable = ({ entities, withTimestamp, attributes = [], relations = [], onPageChange, onPageSizeChange, sortStatus, onStartStatusChange }) => {
18
- const columns = useMemo(() => [
19
- {
20
- accessor: "id",
21
- title: "#",
22
- sortable: true
16
+ //#region src/components/OcelotIcon.tsx
17
+ const OcelotIcon = (props) => /* @__PURE__ */ jsxs("svg", {
18
+ xmlns: "http://www.w3.org/2000/svg",
19
+ width: 128,
20
+ height: 128,
21
+ viewBox: "0 0 96 96",
22
+ ...props,
23
+ fill: "currentColor",
24
+ children: [
25
+ /* @__PURE__ */ jsx("title", { children: "Ocelot" }),
26
+ /* @__PURE__ */ jsx("path", { d: "M2.5 8.2c-2.2 5.6-2.3 18-.2 23 .9 2.1 2.7 5.3 4.1 7.1C8.2 40.6 8.6 42 8 43c-2 3.2-1.1 9.1 2.4 14.8 1.9 3.2 4 8.4 4.6 11.7 1.6 8 2.9 9.9 9.4 12.8 3 1.4 7.1 4.2 9.1 6.1l3.6 3.6h21.8l3.6-3.6c2-1.9 6-4.7 8.9-6 3-1.4 5.9-3.1 6.6-3.9.6-.8 2-4.9 3.1-9.1 1.1-4.3 3.3-9.9 4.9-12.4 3.1-4.8 4-10.9 2-14-.6-1-.2-2.4 1.6-4.7 1.4-1.8 3.2-5 4.1-7.1 2.1-5 2-17.4-.2-23C91.8 4.1 91.7 4 87 4c-5.6 0-12 2.1-17.3 5.6-3.9 2.5-3.9 2.5-7.5.7-2.9-1.4-6-1.8-14.2-1.8s-11.3.4-14.2 1.8c-3.6 1.8-3.6 1.8-7.5-.7C21 6.1 14.6 4 9 4c-4.7 0-4.8.1-6.5 4.2zM19 11.1c2.5 1.1 6.1 3.3 8.2 4.9 3.2 2.6 3.8 2.8 4.9 1.4 2.9-3.5 7.3-4.8 15.9-4.8 6.9 0 9.3.4 12.8 2.2 2.3 1.2 4.2 2.7 4.2 3.3 0 .5 1.7-.4 3.8-2 4.3-3.5 11.1-6.7 16.3-7.6 3.6-.7 3.7-.6 4.9 3.1 3 8.9.5 19.7-5.9 25.8l-2.9 2.8 1.9 3.2c2.5 4.2 2.4 6.5-.6 10.7-1.4 1.9-3.3 5.8-4.1 8.6-.9 2.9-1.8 5.3-2.1 5.3-.9 0 .6-8.1 2.8-14.6 1.9-5.6 1.9-6.3.5-9.7-1.6-4-2.7-4.5-4.6-2.2-1 1.2-1 1.8 0 3 1.3 1.6 1.1 3.8-1.5 12.5-.9 3.3-1.4 8.3-1.3 12.5l.3 7-4.9 2.8c-2.7 1.5-5.1 2.5-5.4 2.2-.2-.2.7-1.8 2.2-3.5 2.2-2.7 2.6-4.1 2.6-9.5 0-7.6-.9-10.1-5.5-16.2-4.5-5.8-4.6-8.1-.5-7.5 1.9.3 4.3-.4 6.6-1.7 2-1.2 3.9-1.9 4.2-1.7.5.6 3.1-2.4 3.2-3.5 0-1.1-7.9-3.9-11.1-3.9-7.1 0-11.8 5.6-10.5 12.5.4 1.9 2.3 5.6 4.3 8.2 5.5 7.2 6.6 17.9 2.2 21.9-1.4 1.3-2.6 1.4-5.6.7-3.5-.8-3.8-1.1-4.1-4.8-.3-3.7 0-4.1 2.8-5.2 2.3-.9 3-1.7 3-3.9 0-2.5-.1-2.6-1.7-1.2-2.2 1.8-10.4 1.8-12.6-.1-1.5-1.2-1.7-1-1.7 1.4 0 2.1.7 2.9 3 3.8 2.8 1.1 3.1 1.5 2.8 5.2-.3 3.7-.6 4-4.1 4.8-3.3.8-4.2.6-5.9-1.1-1.7-1.7-2.1-3.2-2-8.8.1-4.3.7-7.4 1.7-8.8 5.1-6.9 7.5-11.3 7.5-13.7C43 38.5 38.5 34 32.1 34 28.9 34 21 36.8 21 37.9c.1 1.1 2.7 4.1 3.2 3.5.3-.2 2.2.5 4.2 1.7 2.3 1.3 4.7 2 6.6 1.7 4.1-.6 4 1.7-.5 7.5-4.6 6.1-5.5 8.6-5.5 16.2 0 5.4.4 6.8 2.6 9.5 1.5 1.7 2.4 3.3 2.2 3.5-.3.3-2.7-.7-5.4-2.2l-4.9-2.8.3-7.7c.2-5.6-.2-9.2-1.8-13.7-2.3-6.9-2.5-9.2-.8-10.9.8-.8.8-1.5-.2-2.7-1.9-2.3-3-1.8-4.6 2.2-1.4 3.4-1.4 4.1.5 9.7 2.2 6.5 3.7 14.6 2.8 14.6-.3 0-1.2-2.4-2.1-5.3-.8-2.8-2.7-6.7-4.1-8.6-3-4.2-3.1-6.5-.6-10.7l1.9-3.2-2.9-2.8C5.5 31.3 3 20.5 6 11.6c1.2-3.7 1.3-3.8 4.9-3.1 2 .4 5.6 1.5 8.1 2.6zm39.2 72.8C60.6 86.3 56.3 88 48 88c-12.3 0-15-4.2-4.2-6.5 5.1-1.1 12.2 0 14.4 2.4z" }),
27
+ /* @__PURE__ */ jsx("path", { d: "M8.6 15.1c-1.3 6.8.1 13.2 4 17.9l2.6 3 2.7-4.2c1.5-2.4 4.3-5.8 6.1-7.7 3.3-3.2 3.3-3.4 1.4-4.8-2.5-1.9-13.6-7.3-15-7.3-.6 0-1.4 1.4-1.8 3.1zm8.9 4.1c3.1 1.4 3.1 2.5.2 6.2-2.8 3.4-4.4 2.9-5.3-1.9-1-5.3.4-6.5 5.1-4.3zM78.5 14.9c-3.3 1.6-6.9 3.6-7.9 4.4-1.9 1.4-1.9 1.6 1.4 4.8 1.8 1.9 4.6 5.3 6.1 7.7l2.7 4.2 2.6-3c2.5-3.1 4.6-8.7 4.6-12.6 0-4-1.2-8.4-2.4-8.4-.6 0-3.8 1.3-7.1 2.9zm5.2 7.2c-.8 6.1-2.3 7-5.3 3.4-1.3-1.7-2.4-3.5-2.4-4.1 0-1.3 3.7-3.2 6.4-3.3 1.6-.1 1.8.4 1.3 4z" })
28
+ ]
29
+ });
30
+ //#endregion
31
+ //#region src/components/EntityCard.tsx
32
+ const EntityCard = ({ name, count, attributeSummaries = [], relationSummaries = [], maw }) => {
33
+ return /* @__PURE__ */ jsxs(Flex, {
34
+ w: "100%",
35
+ bd: "1px solid black",
36
+ bg: "white",
37
+ miw: 200,
38
+ maw,
39
+ mih: 100,
40
+ direction: "column",
41
+ children: [
42
+ /* @__PURE__ */ jsx(Text, {
43
+ fw: 700,
44
+ size: "sm",
45
+ ta: "center",
46
+ py: "4",
47
+ px: "xs",
48
+ style: { wordBreak: "break-word" },
49
+ children: `${name} (${count})`
50
+ }),
51
+ /* @__PURE__ */ jsx(Divider, {
52
+ c: "black",
53
+ size: "md"
54
+ }),
55
+ attributeSummaries.length !== 0 && /* @__PURE__ */ jsxs(Table, {
56
+ withRowBorders: false,
57
+ captionSide: "top",
58
+ layout: "fixed",
59
+ children: [/* @__PURE__ */ jsx(Table.Caption, {
60
+ mb: 0,
61
+ children: "Attributes"
62
+ }), /* @__PURE__ */ jsx(Table.Tbody, { children: attributeSummaries.map((attribute) => /* @__PURE__ */ jsxs(Table.Tr, { children: [/* @__PURE__ */ jsx(Table.Td, {
63
+ style: { wordBreak: "break-word" },
64
+ children: attribute.name
65
+ }), /* @__PURE__ */ jsx(Table.Td, {
66
+ ta: "end",
67
+ style: { wordBreak: "break-word" },
68
+ children: attribute.type
69
+ })] }, attribute.name)) })]
70
+ }),
71
+ relationSummaries.length !== 0 && /* @__PURE__ */ jsxs(Table, {
72
+ withRowBorders: false,
73
+ captionSide: "top",
74
+ layout: "fixed",
75
+ children: [/* @__PURE__ */ jsx(Table.Caption, {
76
+ mb: 0,
77
+ children: "Relations"
78
+ }), /* @__PURE__ */ jsx(Table.Tbody, { children: relationSummaries.map(({ target, qualifier, min_count, max_count }) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
79
+ /* @__PURE__ */ jsx(Table.Td, {
80
+ style: { wordBreak: "break-word" },
81
+ children: target
82
+ }),
83
+ /* @__PURE__ */ jsx(Table.Td, {
84
+ style: { wordBreak: "break-word" },
85
+ children: qualifier ?? "None"
86
+ }),
87
+ /* @__PURE__ */ jsx(Table.Td, {
88
+ ta: "end",
89
+ w: 70,
90
+ style: { whiteSpace: "nowrap" },
91
+ children: min_count < max_count ? `${min_count}-${max_count}` : min_count
92
+ })
93
+ ] }, `${target}-${qualifier}`)) })]
94
+ })
95
+ ]
96
+ });
97
+ };
98
+ //#endregion
99
+ //#region src/components/EntityOverview.tsx
100
+ const EntityOverview = ({ attributes, relations, entityCounts, search = "" }) => {
101
+ const relationMap = useMemo(() => {
102
+ return relations.reduce((relationMap, currentRelation) => {
103
+ if (currentRelation.source in relationMap) relationMap[currentRelation.source]?.push(currentRelation);
104
+ else relationMap[currentRelation.source] = [currentRelation];
105
+ return relationMap;
106
+ }, {});
107
+ }, [relations]);
108
+ return /* @__PURE__ */ jsx(SimpleGrid, {
109
+ cols: {
110
+ base: 1,
111
+ sm: 2,
112
+ md: 4,
113
+ lg: 5
23
114
  },
24
- ...withTimestamp ? [{
25
- accessor: "timestamp",
26
- title: "date",
27
- sortable: true
28
- }] : [],
29
- ...attributes.map(({ attribute }) => ({
30
- accessor: attribute,
31
- sortable: true
32
- })),
33
- ...relations.map(({ qualifier, target }) => ({
34
- accessor: `${qualifier}::${target}`,
35
- title: `${qualifier} (${target})`
36
- }))
37
- ], [
38
- withTimestamp,
39
- attributes,
40
- relations
41
- ]);
115
+ children: useMemo(() => {
116
+ const toSearch = search.toLowerCase();
117
+ return Object.entries(entityCounts).filter(([event, _]) => event.toLowerCase().includes(search.toLowerCase()) || relationMap[event]?.some(({ target, qualifier }) => target.toLowerCase().includes(toSearch) || qualifier.toLowerCase().includes(toSearch)) || attributes?.some(({ name, entity_type }) => event === entity_type && name.toLowerCase().includes(toSearch)));
118
+ }, [
119
+ search,
120
+ relationMap,
121
+ entityCounts,
122
+ attributes
123
+ ]).map(([name, count]) => {
124
+ return /* @__PURE__ */ jsx(EntityCard, {
125
+ count,
126
+ name,
127
+ attributeSummaries: attributes.filter(({ entity_type }) => entity_type === name) ?? [],
128
+ relationSummaries: relationMap[name] ?? []
129
+ }, name);
130
+ })
131
+ });
132
+ };
133
+ //#endregion
134
+ //#region src/routes/eventOverview.tsx
135
+ const EventOverview = () => {
136
+ const { id } = useCurrentOcel();
137
+ const { data: eventsAttributes = [] } = useEventAttributes(id);
138
+ const { data: e2o } = useE2o(id);
139
+ const { data: eventCounts, isLoading: isEventCountsLoading } = useEventCounts(id);
140
+ const [searchValue, setSearchValue] = useDebouncedState("", 200);
141
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoadingOverlay, { visible: isEventCountsLoading }), /* @__PURE__ */ jsxs(Stack, { children: [
142
+ /* @__PURE__ */ jsx(Title, {
143
+ order: 2,
144
+ children: "Event Overview"
145
+ }),
146
+ /* @__PURE__ */ jsx(Text, {
147
+ c: "dimmed",
148
+ size: "sm",
149
+ children: "Get an overview of all event types in this log. Search through them and see how often each type occurs, what attributes it carries, and which objects it has a relation with."
150
+ }),
151
+ /* @__PURE__ */ jsx(Input, {
152
+ leftSection: /* @__PURE__ */ jsx(SearchIcon, {}),
153
+ defaultValue: searchValue,
154
+ onChange: (newSearch) => setSearchValue(newSearch.target.value)
155
+ }),
156
+ eventCounts && /* @__PURE__ */ jsx(EntityOverview, {
157
+ relations: e2o?.response ?? [],
158
+ entityCounts: eventCounts,
159
+ attributes: eventsAttributes,
160
+ search: searchValue
161
+ })
162
+ ] })] });
163
+ };
164
+ var eventOverview_default = defineModuleRoute({
165
+ component: EventOverview,
166
+ label: "Event Overview",
167
+ name: "eventOverview",
168
+ requiresOcel: true
169
+ });
170
+ //#endregion
171
+ //#region src/lib/fetcher.ts
172
+ const customFetch$1 = async (config, options) => customFetch(config, options);
173
+ //#endregion
174
+ //#region src/api/base.ts
175
+ /**
176
+ * Generated by orval v8.19.0 🍺
177
+ * Do not edit manually.
178
+ * Ocelot
179
+ * OpenAPI spec version: 1.0
180
+ */
181
+ const withQueryKey = (query, queryKey) => {
182
+ const result = { queryKey };
183
+ for (const key of Object.keys(query)) {
184
+ if (key === "queryKey") continue;
185
+ Object.defineProperty(result, key, {
186
+ enumerable: true,
187
+ configurable: true,
188
+ get: () => query[key]
189
+ });
190
+ }
191
+ return result;
192
+ };
193
+ /**
194
+ * @summary Get Events
195
+ */
196
+ const paginatedEvents = (ocelId, params, options, signal) => {
197
+ return customFetch$1({
198
+ url: `/api/external/modules/ocelot/v1/${ocelId}/events`,
199
+ method: "GET",
200
+ params,
201
+ signal
202
+ }, options);
203
+ };
204
+ const getPaginatedEventsQueryKey = (ocelId, params) => {
205
+ return [`/api/external/modules/ocelot/v1/${ocelId}/events`, ...params ? [params] : []];
206
+ };
207
+ const getPaginatedEventsQueryOptions = (ocelId, params, options) => {
208
+ const { query: queryOptions, request: requestOptions } = options ?? {};
209
+ const queryKey = queryOptions?.queryKey ?? getPaginatedEventsQueryKey(ocelId, params);
210
+ const queryFn = ({ signal }) => paginatedEvents(ocelId, params, requestOptions, signal);
211
+ return {
212
+ queryKey,
213
+ queryFn,
214
+ enabled: ocelId !== null && ocelId !== void 0,
215
+ staleTime: 3e5,
216
+ ...queryOptions
217
+ };
218
+ };
219
+ /**
220
+ * @summary Get Events
221
+ */
222
+ function usePaginatedEvents(ocelId, params, options, queryClient) {
223
+ const queryOptions = getPaginatedEventsQueryOptions(ocelId, params, options);
224
+ return withQueryKey(useQuery(queryOptions, queryClient), queryOptions.queryKey);
225
+ }
226
+ /**
227
+ * @summary Get Objects
228
+ */
229
+ const paginatedObjects = (ocelId, params, options, signal) => {
230
+ return customFetch$1({
231
+ url: `/api/external/modules/ocelot/v1/${ocelId}/objects`,
232
+ method: "GET",
233
+ params,
234
+ signal
235
+ }, options);
236
+ };
237
+ const getPaginatedObjectsQueryKey = (ocelId, params) => {
238
+ return [`/api/external/modules/ocelot/v1/${ocelId}/objects`, ...params ? [params] : []];
239
+ };
240
+ const getPaginatedObjectsQueryOptions = (ocelId, params, options) => {
241
+ const { query: queryOptions, request: requestOptions } = options ?? {};
242
+ const queryKey = queryOptions?.queryKey ?? getPaginatedObjectsQueryKey(ocelId, params);
243
+ const queryFn = ({ signal }) => paginatedObjects(ocelId, params, requestOptions, signal);
244
+ return {
245
+ queryKey,
246
+ queryFn,
247
+ enabled: ocelId !== null && ocelId !== void 0,
248
+ staleTime: 3e5,
249
+ ...queryOptions
250
+ };
251
+ };
252
+ /**
253
+ * @summary Get Objects
254
+ */
255
+ function usePaginatedObjects(ocelId, params, options, queryClient) {
256
+ const queryOptions = getPaginatedObjectsQueryOptions(ocelId, params, options);
257
+ return withQueryKey(useQuery(queryOptions, queryClient), queryOptions.queryKey);
258
+ }
259
+ /**
260
+ * @summary Get Object Columns
261
+ */
262
+ const objectColumns = (ocelId, params, options, signal) => {
263
+ return customFetch$1({
264
+ url: `/api/external/modules/ocelot/v1/${ocelId}/objects/columns`,
265
+ method: "GET",
266
+ params,
267
+ signal
268
+ }, options);
269
+ };
270
+ const getObjectColumnsQueryKey = (ocelId, params) => {
271
+ return [`/api/external/modules/ocelot/v1/${ocelId}/objects/columns`, ...params ? [params] : []];
272
+ };
273
+ const getObjectColumnsQueryOptions = (ocelId, params, options) => {
274
+ const { query: queryOptions, request: requestOptions } = options ?? {};
275
+ const queryKey = queryOptions?.queryKey ?? getObjectColumnsQueryKey(ocelId, params);
276
+ const queryFn = ({ signal }) => objectColumns(ocelId, params, requestOptions, signal);
277
+ return {
278
+ queryKey,
279
+ queryFn,
280
+ enabled: ocelId !== null && ocelId !== void 0,
281
+ staleTime: 3e5,
282
+ ...queryOptions
283
+ };
284
+ };
285
+ /**
286
+ * @summary Get Object Columns
287
+ */
288
+ function useObjectColumns(ocelId, params, options, queryClient) {
289
+ const queryOptions = getObjectColumnsQueryOptions(ocelId, params, options);
290
+ return withQueryKey(useQuery(queryOptions, queryClient), queryOptions.queryKey);
291
+ }
292
+ /**
293
+ * @summary Get Activity Columns
294
+ */
295
+ const activityColumns = (ocelId, params, options, signal) => {
296
+ return customFetch$1({
297
+ url: `/api/external/modules/ocelot/v1/${ocelId}/events/columns`,
298
+ method: "GET",
299
+ params,
300
+ signal
301
+ }, options);
302
+ };
303
+ const getActivityColumnsQueryKey = (ocelId, params) => {
304
+ return [`/api/external/modules/ocelot/v1/${ocelId}/events/columns`, ...params ? [params] : []];
305
+ };
306
+ const getActivityColumnsQueryOptions = (ocelId, params, options) => {
307
+ const { query: queryOptions, request: requestOptions } = options ?? {};
308
+ const queryKey = queryOptions?.queryKey ?? getActivityColumnsQueryKey(ocelId, params);
309
+ const queryFn = ({ signal }) => activityColumns(ocelId, params, requestOptions, signal);
310
+ return {
311
+ queryKey,
312
+ queryFn,
313
+ enabled: ocelId !== null && ocelId !== void 0,
314
+ staleTime: 3e5,
315
+ ...queryOptions
316
+ };
317
+ };
318
+ /**
319
+ * @summary Get Activity Columns
320
+ */
321
+ function useActivityColumns(ocelId, params, options, queryClient) {
322
+ const queryOptions = getActivityColumnsQueryOptions(ocelId, params, options);
323
+ return withQueryKey(useQuery(queryOptions, queryClient), queryOptions.queryKey);
324
+ }
325
+ //#endregion
326
+ //#region src/components/EntityTable.tsx
327
+ const EntityTable = ({ entities, columns, onPageChange, onPageSizeChange, sortStatus, onStartStatusChange }) => {
42
328
  const records = useMemo(() => entities.items.map((entity) => ({
43
329
  ...entity,
44
330
  ...entity.attributes,
45
331
  ...Object.assign({}, ...Object.entries(entity.relations).map(([qualifierName, entityIds]) => ({ [qualifierName]: entityIds.join(", ") })))
46
332
  })), [entities]);
333
+ const transformedColumns = useMemo(() => columns.map((column) => ({
334
+ ...column,
335
+ sortable: column.type === "attribute"
336
+ })), [columns]);
47
337
  return /* @__PURE__ */ jsx(DataTable, {
48
338
  page: entities.page,
49
339
  totalRecords: entities.total_items,
50
340
  recordsPerPage: entities.page_size,
51
341
  onPageChange,
52
342
  withColumnBorders: true,
53
- columns,
343
+ columns: transformedColumns,
54
344
  records,
55
345
  recordsPerPageOptions: [
56
346
  20,
@@ -65,8 +355,6 @@ const EntityTable = ({ entities, withTimestamp, attributes = [], relations = [],
65
355
  onSortStatusChange: onStartStatusChange
66
356
  });
67
357
  };
68
- var EntityTable_default = EntityTable;
69
-
70
358
  //#endregion
71
359
  //#region src/components/SingleLineTabs/SingleLineTabs.tsx
72
360
  const SingleLineTabs = ({ setCurrentTab, currentTab, tabs }) => {
@@ -79,7 +367,7 @@ const SingleLineTabs = ({ setCurrentTab, currentTab, tabs }) => {
79
367
  setCurrentTab(newTab);
80
368
  scrollIntoView({ alignment: "center" });
81
369
  }, [scrollIntoView, setCurrentTab]);
82
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Flex, {
370
+ return /* @__PURE__ */ jsxs(Flex, {
83
371
  align: "center",
84
372
  justify: "center",
85
373
  children: [
@@ -125,29 +413,20 @@ const SingleLineTabs = ({ setCurrentTab, currentTab, tabs }) => {
125
413
  children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
126
414
  })
127
415
  ]
128
- }) });
416
+ });
129
417
  };
130
- var SingleLineTabs_default = SingleLineTabs;
131
-
132
418
  //#endregion
133
419
  //#region src/components/EntityPage.tsx
134
- const EntityPage = ({ type }) => {
135
- const { id } = useCurrentOcel();
420
+ const EntityPage = ({ ocelId, type, title, description }) => {
136
421
  const areEntitiesEvents = type === "events";
137
- const { data: entityCounts } = (areEntitiesEvents ? useEventCounts : useObjectCounts)({ ocel_id: id });
138
- const { data: attributes } = (areEntitiesEvents ? useEventAttributes : useObjectAttributes)({ ocel_id: id });
139
- const [currentTab, setCurrentTab] = useState("");
422
+ const { data: entityCounts } = (areEntitiesEvents ? useEventCounts : useObjectCounts)(ocelId);
423
+ const [currentTab, setCurrentTab] = useState(null);
140
424
  const [page, setPage] = useState(1);
141
425
  const [sort, setSort] = useState(void 0);
142
426
  const [pageSize, setPageSize] = useState(20);
143
427
  const entityNames = useMemo(() => Object.keys(entityCounts ?? {}), [entityCounts]);
144
- const { data: unfilteredRelations = [] } = (areEntitiesEvents ? useE2o : useO2o)({ ocel_id: id });
145
- const relations = useMemo(() => {
146
- return unfilteredRelations.filter(({ source }) => source === currentTab);
147
- }, [unfilteredRelations, currentTab]);
148
- const { data: entities } = (areEntitiesEvents ? useOcelotPaginatedEvents : useOcelotPaginatedObjects)({
149
- ocel_id: id,
150
- type: currentTab,
428
+ const { data: entities } = (areEntitiesEvents ? usePaginatedEvents : usePaginatedObjects)(ocelId, {
429
+ type: currentTab ?? "",
151
430
  page_size: pageSize,
152
431
  page,
153
432
  ...sort && {
@@ -155,9 +434,11 @@ const EntityPage = ({ type }) => {
155
434
  ascending: sort.direction === "asc"
156
435
  }
157
436
  }, { query: {
437
+ enabled: !!currentTab,
158
438
  placeholderData: keepPreviousData,
159
439
  staleTime: 5e3
160
440
  } });
441
+ const { data } = (areEntitiesEvents ? useActivityColumns : useObjectColumns)(ocelId, { type_name: currentTab ?? "" }, { query: { enabled: !!currentTab } });
161
442
  useEffect(() => {
162
443
  if (!currentTab && entityNames.length > 0) setCurrentTab(entityNames[0]);
163
444
  }, [currentTab, entityNames]);
@@ -165,172 +446,58 @@ const EntityPage = ({ type }) => {
165
446
  return /* @__PURE__ */ jsxs(Flex, {
166
447
  direction: "column",
167
448
  h: "100%",
168
- children: [/* @__PURE__ */ jsx(SingleLineTabs_default, {
169
- tabs: Object.entries(entityCounts ?? {}).map(([entityName, count]) => ({
170
- value: entityName,
171
- label: `${entityName} (${count})`
172
- })),
173
- setCurrentTab: (newTab) => {
174
- setCurrentTab(newTab);
175
- setPage(1);
176
- setSort(void 0);
177
- },
178
- currentTab: currentTab ?? entityNames[0]
179
- }), entities && /* @__PURE__ */ jsx(EntityTable_default, {
180
- entities,
181
- attributes: attributes?.[currentTab ?? entityNames[0]],
182
- withTimestamp: type === "events",
183
- onPageChange: (newPage) => setPage(newPage),
184
- onPageSizeChange: (newPageSize) => setPageSize(newPageSize),
185
- relations,
186
- sortStatus: sort,
187
- onStartStatusChange: (sortStatus) => setSort(sortStatus)
188
- })]
189
- });
190
- };
191
- var EntityPage_default = EntityPage;
192
-
193
- //#endregion
194
- //#region src/routes/events.tsx
195
- const EventPage = () => /* @__PURE__ */ jsx(EntityPage_default, { type: "events" });
196
- var events_default = defineModuleRoute({
197
- component: EventPage,
198
- label: "Events",
199
- name: "events",
200
- requiresOcel: true
201
- });
202
-
203
- //#endregion
204
- //#region src/routes/objects.tsx
205
- const ObjectPage = () => /* @__PURE__ */ jsx(EntityPage_default, { type: "objects" });
206
- var objects_default = defineModuleRoute({
207
- component: ObjectPage,
208
- label: "Objects",
209
- name: "objects",
210
- requiresOcel: true
211
- });
212
-
213
- //#endregion
214
- //#region src/components/EntityCard.tsx
215
- const EntityCard = ({ name, count, attributeSummaries = [], relationSummaries = [] }) => {
216
- return /* @__PURE__ */ jsxs(Flex, {
217
- w: "100%",
218
- bd: "1px solid black",
219
- bg: "white",
220
- miw: 200,
221
- mih: 100,
222
- direction: "column",
223
449
  children: [
224
- /* @__PURE__ */ jsx(Text, {
225
- fw: 700,
226
- size: "sm",
227
- ta: "center",
228
- py: "4",
229
- children: `${name} (${count})`
450
+ title && /* @__PURE__ */ jsx(Title, {
451
+ order: 2,
452
+ children: title
230
453
  }),
231
- /* @__PURE__ */ jsx(Divider, {
232
- c: "black",
233
- size: "md"
454
+ description && /* @__PURE__ */ jsx(Text, {
455
+ c: "dimmed",
456
+ size: "sm",
457
+ mb: "xs",
458
+ children: description
234
459
  }),
235
- attributeSummaries.length !== 0 && /* @__PURE__ */ jsxs(Table, {
236
- withRowBorders: false,
237
- captionSide: "top",
238
- style: {
239
- overflow: "hidden",
240
- textOverflow: "ellipsis"
460
+ /* @__PURE__ */ jsx(SingleLineTabs, {
461
+ tabs: Object.entries(entityCounts ?? {}).map(([entityName, count]) => ({
462
+ value: entityName,
463
+ label: `${entityName} (${count})`
464
+ })),
465
+ setCurrentTab: (newTab) => {
466
+ setCurrentTab(newTab);
467
+ setPage(1);
468
+ setSort(void 0);
241
469
  },
242
- children: [/* @__PURE__ */ jsx(Table.Caption, {
243
- mb: 0,
244
- children: "Attributes"
245
- }), /* @__PURE__ */ jsx(Table.Tbody, { children: attributeSummaries.map((attribute) => /* @__PURE__ */ jsxs(Table.Tr, { children: [/* @__PURE__ */ jsxs(Table.Td, { children: [" ", attribute.attribute] }), /* @__PURE__ */ jsx(Table.Td, {
246
- ta: "end",
247
- children: attribute.type
248
- })] }, attribute.attribute)) })]
470
+ currentTab: currentTab ?? entityNames[0] ?? ""
249
471
  }),
250
- relationSummaries.length !== 0 && /* @__PURE__ */ jsxs(Table, {
251
- withRowBorders: false,
252
- captionSide: "top",
253
- style: {
254
- overflow: "hidden",
255
- textOverflow: "ellipsis"
256
- },
257
- children: [/* @__PURE__ */ jsx(Table.Caption, {
258
- mb: 0,
259
- children: "Relations"
260
- }), /* @__PURE__ */ jsx(Table.Tbody, { children: relationSummaries.map(({ target, qualifier, min_count, max_count }) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
261
- /* @__PURE__ */ jsx(Table.Td, { children: target }),
262
- /* @__PURE__ */ jsx(Table.Td, { children: qualifier ?? "None" }),
263
- /* @__PURE__ */ jsx(Table.Td, { children: min_count < max_count ? `${min_count}-${max_count}` : min_count })
264
- ] }, `${target}-${qualifier}`)) })]
472
+ entities && /* @__PURE__ */ jsx(EntityTable, {
473
+ entities,
474
+ columns: data ?? [],
475
+ withTimestamp: type === "events",
476
+ onPageChange: (newPage) => setPage(newPage),
477
+ onPageSizeChange: (newPageSize) => setPageSize(newPageSize),
478
+ sortStatus: sort,
479
+ onStartStatusChange: (sortStatus) => setSort(sortStatus)
265
480
  })
266
481
  ]
267
482
  });
268
483
  };
269
- var EntityCard_default = EntityCard;
270
-
271
- //#endregion
272
- //#region src/components/EntityOverview.tsx
273
- const EntityOverview = ({ attributes, relations, entityCounts, search = "" }) => {
274
- const relationMap = useMemo(() => {
275
- return relations.reduce((relationMap$1, currentRelation) => {
276
- if (currentRelation.source in relationMap$1) relationMap$1[currentRelation.source]?.push(currentRelation);
277
- else relationMap$1[currentRelation.source] = [currentRelation];
278
- return relationMap$1;
279
- }, {});
280
- }, [relations]);
281
- return /* @__PURE__ */ jsx(SimpleGrid, {
282
- cols: {
283
- base: 1,
284
- sm: 2,
285
- md: 4,
286
- lg: 5
287
- },
288
- children: useMemo(() => {
289
- const toSearch = search.toLowerCase();
290
- return Object.entries(entityCounts).filter(([event, _]) => event.toLowerCase().includes(search.toLowerCase()) || relationMap[event]?.some(({ target, qualifier }) => target.toLowerCase().includes(toSearch) || qualifier.toLowerCase().includes(toSearch)) || attributes[event]?.some(({ attribute }) => attribute.toLowerCase().includes(toSearch)));
291
- }, [
292
- search,
293
- relationMap,
294
- entityCounts,
295
- attributes
296
- ]).map(([name, count]) => {
297
- return /* @__PURE__ */ jsx(EntityCard_default, {
298
- count,
299
- name,
300
- attributeSummaries: attributes[name] ?? [],
301
- relationSummaries: relationMap[name] ?? []
302
- }, name);
303
- })
304
- });
305
- };
306
- var EntityOverview_default = EntityOverview;
307
-
308
484
  //#endregion
309
- //#region src/routes/eventOverview.tsx
310
- const EventOverview = () => {
485
+ //#region src/routes/events.tsx
486
+ const EventPage = () => {
311
487
  const { id } = useCurrentOcel();
312
- const { data: eventsAttributes = {} } = useEventAttributes({ ocel_id: id });
313
- const { data: e2o = [] } = useE2o({ ocel_id: id });
314
- const { data: eventCounts, isLoading: isEventCountsLoading } = useEventCounts({ ocel_id: id });
315
- const [searchValue, setSearchValue] = useDebouncedState("", 200);
316
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoadingOverlay, { visible: isEventCountsLoading }), /* @__PURE__ */ jsxs(Stack, { children: [/* @__PURE__ */ jsx(Input, {
317
- leftSection: /* @__PURE__ */ jsx(SearchIcon, {}),
318
- defaultValue: searchValue,
319
- onChange: (newSearch) => setSearchValue(newSearch.target.value)
320
- }), eventCounts && /* @__PURE__ */ jsx(EntityOverview_default, {
321
- relations: e2o,
322
- entityCounts: eventCounts,
323
- attributes: eventsAttributes,
324
- search: searchValue
325
- })] })] });
488
+ return /* @__PURE__ */ jsx(EntityPage, {
489
+ ocelId: id ?? "",
490
+ type: "events",
491
+ title: "Event Inspector",
492
+ description: "Browse the individual events in this log. Pick an event type to see its records in a table, with their attributes and the objects they have a relation with."
493
+ }, id);
326
494
  };
327
- var eventOverview_default = defineModuleRoute({
328
- component: EventOverview,
329
- label: "Event Overview",
330
- name: "eventOverview",
495
+ var events_default = defineModuleRoute({
496
+ component: EventPage,
497
+ label: "Events",
498
+ name: "events",
331
499
  requiresOcel: true
332
500
  });
333
-
334
501
  //#endregion
335
502
  //#region src/components/Graph/util/getEdgeParams.tsx
336
503
  const getRectangleIntersection = (targetNode, sourceNode) => {
@@ -404,7 +571,6 @@ function getEdgeParams(source, target) {
404
571
  targetPos
405
572
  };
406
573
  }
407
-
408
574
  //#endregion
409
575
  //#region src/components/Graph/edges/BaseEdge.tsx
410
576
  const EdgeLabel = ({ transform, label }) => {
@@ -422,7 +588,7 @@ const EdgeLabel = ({ transform, label }) => {
422
588
  children: label
423
589
  });
424
590
  };
425
- const customMarkes = ["url('#double-rect')", "url('#rect')"];
591
+ const customMarkers = ["url('#double-rect')", "url('#rect')"];
426
592
  const BaseEdge$1 = ({ labels = [], markerEnd, path, ...rest }) => {
427
593
  return /* @__PURE__ */ jsxs(Fragment, { children: [
428
594
  /* @__PURE__ */ jsx("svg", {
@@ -521,14 +687,12 @@ const BaseEdge$1 = ({ labels = [], markerEnd, path, ...rest }) => {
521
687
  }),
522
688
  /* @__PURE__ */ jsx(BaseEdge, {
523
689
  path,
524
- markerEnd: customMarkes.includes(markerEnd ?? "") ? markerEnd?.replace("rect", "rect-end") : markerEnd,
690
+ markerEnd: customMarkers.includes(markerEnd ?? "") ? markerEnd?.replace("rect", "rect-end") : markerEnd,
525
691
  ...rest
526
692
  }),
527
693
  /* @__PURE__ */ jsx(EdgeLabelRenderer, { children: labels.map((props, index) => /* @__PURE__ */ jsx(EdgeLabel, { ...props }, index)) })
528
694
  ] });
529
695
  };
530
- var BaseEdge_default = BaseEdge$1;
531
-
532
696
  //#endregion
533
697
  //#region src/components/Graph/edges/FloatingEdge.tsx
534
698
  const FloatingEdge = ({ data, source, target, ...props }) => {
@@ -543,17 +707,15 @@ const FloatingEdge = ({ data, source, target, ...props }) => {
543
707
  targetY: ty
544
708
  });
545
709
  const angle = Math.atan2((sy > ty ? -1 : 1) * offsetY, offsetX) * (180 / Math.PI);
546
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(BaseEdge_default, {
710
+ return /* @__PURE__ */ jsx(BaseEdge$1, {
547
711
  path: edgePath,
548
712
  ...props,
549
713
  labels: data?.mid ? [{
550
714
  transform: `translate(-50% , -50%) translate(${labelX}px, ${labelY}px) rotate(${angle}deg)`,
551
715
  label: data.mid
552
716
  }] : []
553
- }) });
717
+ });
554
718
  };
555
- var FloatingEdge_default = FloatingEdge;
556
-
557
719
  //#endregion
558
720
  //#region src/components/Graph/edges/LoopEdge.tsx
559
721
  const LoopingEdge = ({ data, source, ...props }) => {
@@ -573,7 +735,7 @@ const LoopingEdge = ({ data, source, ...props }) => {
573
735
  targetPosition: Position.Top,
574
736
  offset: (data?.offset ?? 0) * 15
575
737
  });
576
- return /* @__PURE__ */ jsx(BaseEdge_default, {
738
+ return /* @__PURE__ */ jsx(BaseEdge$1, {
577
739
  path: edgePath,
578
740
  ...props,
579
741
  labels: data?.mid ? [{
@@ -582,8 +744,6 @@ const LoopingEdge = ({ data, source, ...props }) => {
582
744
  }] : []
583
745
  });
584
746
  };
585
- var LoopEdge_default = LoopingEdge;
586
-
587
747
  //#endregion
588
748
  //#region src/components/Graph/layout/dagre.ts
589
749
  const useDagreLayout = () => {
@@ -617,7 +777,6 @@ const useDagreLayout = () => {
617
777
  fitView
618
778
  ]) };
619
779
  };
620
-
621
780
  //#endregion
622
781
  //#region src/components/Graph/layout/elk.ts
623
782
  const elk = new ELK();
@@ -635,7 +794,7 @@ const useElkLayout = () => {
635
794
  "elk.edgeRouting": "ORTHOGONAL",
636
795
  "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX"
637
796
  };
638
- return { layout: useCallback(async (options) => {
797
+ return { layout: useCallback(async (_options) => {
639
798
  const nodes = getNodes();
640
799
  const edges = getEdges();
641
800
  const graph = {
@@ -654,7 +813,7 @@ const useElkLayout = () => {
654
813
  id: edge.id,
655
814
  sources: [edge.source],
656
815
  targets: [edge.target],
657
- layoutOptions: edge?.data?.["mid"] ? { "elk.edge.minimalLength": edge.data["mid"].toString() } : void 0
816
+ layoutOptions: edge?.data?.mid ? { "elk.edge.minimalLength": edge.data.mid.toString() } : void 0
658
817
  }))
659
818
  };
660
819
  try {
@@ -685,7 +844,7 @@ const useElkLayout = () => {
685
844
  };
686
845
  }));
687
846
  fitView();
688
- } catch (error) {}
847
+ } catch (_error) {}
689
848
  }, [
690
849
  setEdges,
691
850
  setNodes,
@@ -694,7 +853,6 @@ const useElkLayout = () => {
694
853
  fitView
695
854
  ]) };
696
855
  };
697
-
698
856
  //#endregion
699
857
  //#region src/components/Graph/nodes/CircleNode.tsx
700
858
  const CircleNode = memo(({ data: { color, label, inner, diameter = 50 } }) => {
@@ -737,8 +895,6 @@ const CircleNode = memo(({ data: { color, label, inner, diameter = 50 } }) => {
737
895
  })
738
896
  ] });
739
897
  });
740
- var CircleNode_default = CircleNode;
741
-
742
898
  //#endregion
743
899
  //#region src/components/Graph/nodes/RectangleNode.tsx
744
900
  var RectangleNode_default = memo(({ data: { color, label, inner } }) => {
@@ -780,21 +936,15 @@ var RectangleNode_default = memo(({ data: { color, label, inner } }) => {
780
936
  })
781
937
  ] });
782
938
  });
783
-
784
- //#endregion
785
- //#region src/components/Graph/Graph.module.css?css_module
786
- const classes = { "test": "_79UKFW_test" };
787
- var Graph_module_default = classes;
788
- const _test0 = classes["test"];
789
-
790
939
  //#endregion
791
940
  //#region src/components/Graph/index.tsx
941
+ const { saveAs } = FileSaver;
792
942
  const edgeTypes = {
793
- floating: FloatingEdge_default,
794
- looping: LoopEdge_default
943
+ floating: FloatingEdge,
944
+ looping: LoopingEdge
795
945
  };
796
946
  const nodeTypes = {
797
- circle: CircleNode_default,
947
+ circle: CircleNode,
798
948
  rectangle: RectangleNode_default
799
949
  };
800
950
  const layoutToHook = {
@@ -829,15 +979,35 @@ const InnerFlow = ({ initialNodes, initialEdges, layoutOptions = { type: "dagre"
829
979
  } }
830
980
  };
831
981
  }));
982
+ useEffect(() => {
983
+ setNodes((prev) => {
984
+ const prevById = new Map(prev.map((node) => [node.id, node]));
985
+ return initialNodes.map((node) => {
986
+ const existing = prevById.get(node.id);
987
+ if (existing) return {
988
+ ...existing,
989
+ data: node.data
990
+ };
991
+ return {
992
+ ...node,
993
+ type: node.data.type,
994
+ position: {
995
+ x: 0,
996
+ y: 0
997
+ }
998
+ };
999
+ });
1000
+ });
1001
+ }, [initialNodes]);
832
1002
  const onNodesChange = useCallback((changes) => {
833
1003
  const positionChange = changes.filter((change) => change.type === "position");
834
1004
  if (positionChange.length > 0) {
835
1005
  const movedNodes = positionChange.map((change) => change.id);
836
- setEdges((edges$1) => edges$1.map((edge) => ({
1006
+ setEdges((edges) => edges.map((edge) => ({
837
1007
  ...edge,
838
1008
  data: {
839
1009
  ...edge.data,
840
- position: movedNodes.includes(edge.target) || movedNodes.includes(edge.source) ? void 0 : edge.data?.["position"]
1010
+ position: movedNodes.includes(edge.target) || movedNodes.includes(edge.source) ? void 0 : edge.data?.position
841
1011
  }
842
1012
  })));
843
1013
  }
@@ -853,7 +1023,6 @@ const InnerFlow = ({ initialNodes, initialEdges, layoutOptions = { type: "dagre"
853
1023
  hasMeasuredNodes
854
1024
  ]);
855
1025
  return /* @__PURE__ */ jsx(ReactFlow, {
856
- className: Graph_module_default["test"],
857
1026
  style: { height: "100%" },
858
1027
  nodes,
859
1028
  edges,
@@ -870,9 +1039,8 @@ const InnerFlow = ({ initialNodes, initialEdges, layoutOptions = { type: "dagre"
870
1039
  children: /* @__PURE__ */ jsx(ActionIcon, {
871
1040
  variant: "transparent",
872
1041
  onClick: () => handleDownload("ocelot"),
873
- className: "test",
874
1042
  children: /* @__PURE__ */ jsx(DownloadIcon, {
875
- className: "test",
1043
+ color: "black",
876
1044
  size: 18
877
1045
  })
878
1046
  })
@@ -880,27 +1048,26 @@ const InnerFlow = ({ initialNodes, initialEdges, layoutOptions = { type: "dagre"
880
1048
  });
881
1049
  };
882
1050
  const Graph = (props) => /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(InnerFlow, { ...props }) });
883
- var Graph_default = Graph;
884
-
885
1051
  //#endregion
886
1052
  //#region src/routes/objectOverview.tsx
887
1053
  const ObjectGraph = () => {
888
1054
  const { id: ocelId } = useCurrentOcel();
889
- const { data: o2o } = useO2o({ ocel_id: ocelId });
890
- const { data: objectAttributes } = useObjectAttributes({ ocel_id: ocelId });
891
- const { data: objectCounts } = useObjectCounts({ ocel_id: ocelId });
1055
+ const { data: o2o } = useO2o(ocelId);
1056
+ const { data: objectAttributes = [] } = useObjectAttributes(ocelId);
1057
+ const { data: objectCounts } = useObjectCounts(ocelId);
892
1058
  const [searchValue, setSearchValue] = useDebouncedState("", 200);
893
- const [vizualization, setVizualization] = useState("graph");
1059
+ const [visualization, setVisualization] = useState("graph");
894
1060
  const nodes = useMemo(() => {
895
1061
  if (!objectCounts || !objectAttributes) return [];
896
1062
  return Object.entries(objectCounts).map(([objectName, count]) => ({
897
1063
  id: objectName,
898
1064
  data: {
899
1065
  type: "rectangle",
900
- inner: /* @__PURE__ */ jsx(EntityCard_default, {
1066
+ inner: /* @__PURE__ */ jsx(EntityCard, {
901
1067
  count,
902
1068
  name: objectName,
903
- attributeSummaries: objectAttributes[objectName]
1069
+ maw: 300,
1070
+ attributeSummaries: objectAttributes.filter(({ entity_type }) => entity_type === objectName)
904
1071
  }, objectName)
905
1072
  }
906
1073
  }));
@@ -909,15 +1076,24 @@ const ObjectGraph = () => {
909
1076
  w: "100%",
910
1077
  h: "100%",
911
1078
  children: [
1079
+ /* @__PURE__ */ jsx(Title, {
1080
+ order: 2,
1081
+ children: "Object Overview"
1082
+ }),
1083
+ /* @__PURE__ */ jsx(Text, {
1084
+ c: "dimmed",
1085
+ size: "sm",
1086
+ children: "Get an overview of all object types in this log. Switch between an interactive graph and a card grid to see how many objects of each type exist, what attributes they have, and how they relate to one another."
1087
+ }),
912
1088
  /* @__PURE__ */ jsxs(Group, {
913
1089
  justify: "end",
914
- children: [vizualization === "cards" && /* @__PURE__ */ jsx(Input, {
1090
+ children: [visualization === "cards" && /* @__PURE__ */ jsx(Input, {
915
1091
  leftSection: /* @__PURE__ */ jsx(SearchIcon, {}),
916
1092
  defaultValue: searchValue,
917
1093
  onChange: (newSearch) => setSearchValue(newSearch.target.value)
918
1094
  }), /* @__PURE__ */ jsx(SegmentedControl, {
919
- onChange: (newViz) => setVizualization(newViz),
920
- value: vizualization,
1095
+ onChange: (newViz) => setVisualization(newViz),
1096
+ value: visualization,
921
1097
  data: [{
922
1098
  label: "Graph",
923
1099
  value: "graph"
@@ -927,9 +1103,9 @@ const ObjectGraph = () => {
927
1103
  }]
928
1104
  })]
929
1105
  }),
930
- vizualization === "graph" && o2o && objectAttributes && /* @__PURE__ */ jsx(Graph_default, {
1106
+ visualization === "graph" && o2o && objectAttributes && /* @__PURE__ */ jsx(Graph, {
931
1107
  initialNodes: nodes,
932
- initialEdges: o2o.map(({ source, target, sum, qualifier }) => ({
1108
+ initialEdges: o2o.response.map(({ source, target, sum, qualifier }) => ({
933
1109
  source,
934
1110
  target,
935
1111
  markerEnd: { type: MarkerType.ArrowClosed },
@@ -946,10 +1122,10 @@ const ObjectGraph = () => {
946
1122
  }
947
1123
  }
948
1124
  }, ocelId),
949
- vizualization === "cards" && objectCounts && /* @__PURE__ */ jsx(EntityOverview_default, {
1125
+ visualization === "cards" && objectCounts && /* @__PURE__ */ jsx(EntityOverview, {
950
1126
  entityCounts: objectCounts,
951
- attributes: objectAttributes ?? {},
952
- relations: o2o ?? [],
1127
+ attributes: objectAttributes,
1128
+ relations: o2o?.response ?? [],
953
1129
  search: searchValue
954
1130
  })
955
1131
  ]
@@ -961,43 +1137,36 @@ var objectOverview_default = defineModuleRoute({
961
1137
  name: "objectOverview",
962
1138
  requiresOcel: true
963
1139
  });
964
-
965
1140
  //#endregion
966
- //#region src/components/OcelotIcon.tsx
967
- const OcelotIcon = (props) => /* @__PURE__ */ jsxs("svg", {
968
- xmlns: "http://www.w3.org/2000/svg",
969
- width: 128,
970
- height: 128,
971
- viewBox: "0 0 96 96",
972
- ...props,
973
- fill: "currentColor",
974
- children: [
975
- /* @__PURE__ */ jsx("title", { children: "Ocelot" }),
976
- /* @__PURE__ */ jsx("path", { d: "M2.5 8.2c-2.2 5.6-2.3 18-.2 23 .9 2.1 2.7 5.3 4.1 7.1C8.2 40.6 8.6 42 8 43c-2 3.2-1.1 9.1 2.4 14.8 1.9 3.2 4 8.4 4.6 11.7 1.6 8 2.9 9.9 9.4 12.8 3 1.4 7.1 4.2 9.1 6.1l3.6 3.6h21.8l3.6-3.6c2-1.9 6-4.7 8.9-6 3-1.4 5.9-3.1 6.6-3.9.6-.8 2-4.9 3.1-9.1 1.1-4.3 3.3-9.9 4.9-12.4 3.1-4.8 4-10.9 2-14-.6-1-.2-2.4 1.6-4.7 1.4-1.8 3.2-5 4.1-7.1 2.1-5 2-17.4-.2-23C91.8 4.1 91.7 4 87 4c-5.6 0-12 2.1-17.3 5.6-3.9 2.5-3.9 2.5-7.5.7-2.9-1.4-6-1.8-14.2-1.8s-11.3.4-14.2 1.8c-3.6 1.8-3.6 1.8-7.5-.7C21 6.1 14.6 4 9 4c-4.7 0-4.8.1-6.5 4.2zM19 11.1c2.5 1.1 6.1 3.3 8.2 4.9 3.2 2.6 3.8 2.8 4.9 1.4 2.9-3.5 7.3-4.8 15.9-4.8 6.9 0 9.3.4 12.8 2.2 2.3 1.2 4.2 2.7 4.2 3.3 0 .5 1.7-.4 3.8-2 4.3-3.5 11.1-6.7 16.3-7.6 3.6-.7 3.7-.6 4.9 3.1 3 8.9.5 19.7-5.9 25.8l-2.9 2.8 1.9 3.2c2.5 4.2 2.4 6.5-.6 10.7-1.4 1.9-3.3 5.8-4.1 8.6-.9 2.9-1.8 5.3-2.1 5.3-.9 0 .6-8.1 2.8-14.6 1.9-5.6 1.9-6.3.5-9.7-1.6-4-2.7-4.5-4.6-2.2-1 1.2-1 1.8 0 3 1.3 1.6 1.1 3.8-1.5 12.5-.9 3.3-1.4 8.3-1.3 12.5l.3 7-4.9 2.8c-2.7 1.5-5.1 2.5-5.4 2.2-.2-.2.7-1.8 2.2-3.5 2.2-2.7 2.6-4.1 2.6-9.5 0-7.6-.9-10.1-5.5-16.2-4.5-5.8-4.6-8.1-.5-7.5 1.9.3 4.3-.4 6.6-1.7 2-1.2 3.9-1.9 4.2-1.7.5.6 3.1-2.4 3.2-3.5 0-1.1-7.9-3.9-11.1-3.9-7.1 0-11.8 5.6-10.5 12.5.4 1.9 2.3 5.6 4.3 8.2 5.5 7.2 6.6 17.9 2.2 21.9-1.4 1.3-2.6 1.4-5.6.7-3.5-.8-3.8-1.1-4.1-4.8-.3-3.7 0-4.1 2.8-5.2 2.3-.9 3-1.7 3-3.9 0-2.5-.1-2.6-1.7-1.2-2.2 1.8-10.4 1.8-12.6-.1-1.5-1.2-1.7-1-1.7 1.4 0 2.1.7 2.9 3 3.8 2.8 1.1 3.1 1.5 2.8 5.2-.3 3.7-.6 4-4.1 4.8-3.3.8-4.2.6-5.9-1.1-1.7-1.7-2.1-3.2-2-8.8.1-4.3.7-7.4 1.7-8.8 5.1-6.9 7.5-11.3 7.5-13.7C43 38.5 38.5 34 32.1 34 28.9 34 21 36.8 21 37.9c.1 1.1 2.7 4.1 3.2 3.5.3-.2 2.2.5 4.2 1.7 2.3 1.3 4.7 2 6.6 1.7 4.1-.6 4 1.7-.5 7.5-4.6 6.1-5.5 8.6-5.5 16.2 0 5.4.4 6.8 2.6 9.5 1.5 1.7 2.4 3.3 2.2 3.5-.3.3-2.7-.7-5.4-2.2l-4.9-2.8.3-7.7c.2-5.6-.2-9.2-1.8-13.7-2.3-6.9-2.5-9.2-.8-10.9.8-.8.8-1.5-.2-2.7-1.9-2.3-3-1.8-4.6 2.2-1.4 3.4-1.4 4.1.5 9.7 2.2 6.5 3.7 14.6 2.8 14.6-.3 0-1.2-2.4-2.1-5.3-.8-2.8-2.7-6.7-4.1-8.6-3-4.2-3.1-6.5-.6-10.7l1.9-3.2-2.9-2.8C5.5 31.3 3 20.5 6 11.6c1.2-3.7 1.3-3.8 4.9-3.1 2 .4 5.6 1.5 8.1 2.6zm39.2 72.8C60.6 86.3 56.3 88 48 88c-12.3 0-15-4.2-4.2-6.5 5.1-1.1 12.2 0 14.4 2.4z" }),
977
- /* @__PURE__ */ jsx("path", { d: "M8.6 15.1c-1.3 6.8.1 13.2 4 17.9l2.6 3 2.7-4.2c1.5-2.4 4.3-5.8 6.1-7.7 3.3-3.2 3.3-3.4 1.4-4.8-2.5-1.9-13.6-7.3-15-7.3-.6 0-1.4 1.4-1.8 3.1zm8.9 4.1c3.1 1.4 3.1 2.5.2 6.2-2.8 3.4-4.4 2.9-5.3-1.9-1-5.3.4-6.5 5.1-4.3zM78.5 14.9c-3.3 1.6-6.9 3.6-7.9 4.4-1.9 1.4-1.9 1.6 1.4 4.8 1.8 1.9 4.6 5.3 6.1 7.7l2.7 4.2 2.6-3c2.5-3.1 4.6-8.7 4.6-12.6 0-4-1.2-8.4-2.4-8.4-.6 0-3.8 1.3-7.1 2.9zm5.2 7.2c-.8 6.1-2.3 7-5.3 3.4-1.3-1.7-2.4-3.5-2.4-4.1 0-1.3 3.7-3.2 6.4-3.3 1.6-.1 1.8.4 1.3 4z" })
978
- ]
979
- });
980
- var OcelotIcon_default = OcelotIcon;
981
-
1141
+ //#region src/routes/objects.tsx
1142
+ const ObjectPage = () => {
1143
+ const { id } = useCurrentOcel();
1144
+ return /* @__PURE__ */ jsx(EntityPage, {
1145
+ ocelId: id ?? "",
1146
+ type: "objects",
1147
+ title: "Object Inspector",
1148
+ description: "Browse the individual objects in this log. Pick an object type to see its records in a table, with their attributes and the objects they have a relation with."
1149
+ }, id);
1150
+ };
982
1151
  //#endregion
983
- //#region src/config.ts
984
- var config_default = defineModule({
1152
+ //#region src/index.ts
1153
+ var src_default = defineModule({
985
1154
  name: "ocelot",
986
- description: "A tool for exploring object-centric event logs, allowing yout to search events and objects and visualize their relationships and attributes.",
1155
+ description: "A tool for exploring object-centric event logs, allowing you to search events and objects and visualize their relationships and attributes.",
987
1156
  label: "Ocelot",
988
1157
  authors: [{ name: "Öztürk, Görkem-Emre" }],
989
1158
  routes: [
990
1159
  events_default,
991
- objects_default,
1160
+ defineModuleRoute({
1161
+ component: ObjectPage,
1162
+ label: "Objects",
1163
+ name: "objects",
1164
+ requiresOcel: true
1165
+ }),
992
1166
  eventOverview_default,
993
1167
  objectOverview_default
994
1168
  ],
995
- icon: OcelotIcon_default
1169
+ icon: OcelotIcon
996
1170
  });
997
-
998
- //#endregion
999
- //#region src/index.ts
1000
- var src_default = config_default;
1001
-
1002
1171
  //#endregion
1003
- export { src_default as default };
1172
+ export { src_default as default };
package/dist/style.css ADDED
@@ -0,0 +1,9 @@
1
+ .floating-edges {
2
+ width: 100%;
3
+ height: 100vh;
4
+ margin: 1rem;
5
+ }
6
+
7
+ .react-flow__handle {
8
+ opacity: 0;
9
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ocelescope/ocelot",
3
3
  "type": "module",
4
- "version": "0.0.0",
4
+ "version": "0.1.2",
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",
@@ -16,7 +16,7 @@
16
16
  "exports": {
17
17
  ".": "./dist/index.js",
18
18
  "./package.json": "./package.json",
19
- "./styles": "./dist/styles/styles.js"
19
+ "./styles.css": "./dist/style.css"
20
20
  },
21
21
  "main": "./dist/index.js",
22
22
  "module": "./dist/index.js",
@@ -28,35 +28,42 @@
28
28
  "access": "public"
29
29
  },
30
30
  "peerDependencies": {
31
- "@dagrejs/dagre": "^2.0.4",
32
- "@mantine/core": "^8.3.14",
33
- "@mantine/hooks": "^8.3.14",
31
+ "@dagrejs/dagre": "^3.0.0",
32
+ "@mantine/core": "^9.4.0",
33
+ "@mantine/hooks": "^9.4.0",
34
+ "@ocelescope/api-base": "^0.1.0",
35
+ "@ocelescope/core": "^0.1.2",
34
36
  "@tanstack/react-query": "^5.90.21",
35
37
  "@xyflow/react": "^12.10.1",
38
+ "dayjs": "^1.11.19",
39
+ "elkjs": "^0.11.0",
36
40
  "file-saver": "^2.0.5",
37
- "html-to-image": "^1.11.13",
38
- "lucide-react": "^0.563.0",
39
- "mantine-datatable": "^8.3.13",
41
+ "html-to-image": "1.11.13",
42
+ "lucide-react": "^1.0.0",
43
+ "mantine-datatable": "^9.3.1",
40
44
  "react": "^19.2.0",
41
45
  "react-dom": "^19.2.0",
42
- "@ocelescope/core": "0.0.0",
43
- "@ocelescope/api-base": "0.0.0"
46
+ "recharts": "^3.2.1",
47
+ "axios": "^1.18.0",
48
+ "@ocelescope/api-client": "^0.1.0"
44
49
  },
45
50
  "devDependencies": {
51
+ "@tsdown/css": "^0.22.0",
52
+ "@types/css-modules": "^1.0.5",
46
53
  "@tsconfig/strictest": "^2.0.8",
47
54
  "@types/file-saver": "^2.0.7",
48
55
  "@types/node": "^25.0.3",
49
56
  "@types/react": "^19.2.7",
50
57
  "@types/react-dom": "^19.2.3",
51
- "tsdown": "^0.18.1",
52
- "typescript": "^5.9.3"
53
- },
54
- "dependencies": {
55
- "elkjs": "^0.11.0"
58
+ "@ocelescope/api-config": "^0.1.0",
59
+ "tsdown": "^0.22.0",
60
+ "typescript": "^5.9.3",
61
+ "orval": "^8.5.2"
56
62
  },
57
63
  "scripts": {
58
- "build": "tsdown",
59
- "dev": "tsdown --watch",
60
- "typecheck": "tsc --noEmit"
64
+ "dev": "tsdown --watch ./src",
65
+ "typecheck": "tsc --noEmit",
66
+ "build": "pnpm generate:api && orval && tsdown",
67
+ "generate:api": "uv run ocelescope-backend openapi --module ocelot"
61
68
  }
62
69
  }
package/dist/index.css DELETED
@@ -1 +0,0 @@
1
- ._79UKFW_test{color:#00f;background-color:red}
@@ -1 +0,0 @@
1
- .test{color:red;background-color:red}.floating-edges{width:100%;height:100vh;margin:1rem}.react-flow__handle{opacity:0}
@@ -1 +0,0 @@
1
- import "@xyflow/react/dist/style.css";
@@ -1 +0,0 @@
1
- import "@xyflow/react/dist/style.css";