@ocelescope/alignments 0.0.0-stage → 0.10.3

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,3 +1,9 @@
1
- # Temporary Holding Version
1
+ # @ocelescope/case-centric-alignments
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An [Ocelescope](https://www.ocelescope.org) frontend module for computing and
4
+ viewing case-centric alignments of the current object-centric event log.
5
+
6
+ Select a Petri net (or let Alpha+++ discover one), run the alignment, and
7
+ explore the results as a list of aligned variants or on the net.
8
+
9
+ Requires the `ocelescope-module-case-centric-alignments` backend module.
@@ -0,0 +1,256 @@
1
+ import { useCurrentOcel } from "@ocelescope/core";
2
+ import { PlayIcon } from "lucide-react";
3
+ import "@r4pm/components/styles.css";
4
+ import { Box, Button, Group, LoadingOverlay, SegmentedControl, Stack, Tabs, Text } from "@mantine/core";
5
+ import { ResourceSelect } from "@ocelescope/resources";
6
+ import { AlignmentListViewer, AlignmentNetViewer, ViewerConfigProvider } from "@r4pm/components";
7
+ import { wasmLayout } from "@r4pm/components/rust-layout/wasm";
8
+ import { keepPreviousData, useQuery } from "@tanstack/react-query";
9
+ import { useState } from "react";
10
+ import { customFetch } from "@ocelescope/api-client";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ //#region src/lib/fetcher.ts
13
+ const customFetch$1 = async (config, options) => customFetch(config, options);
14
+ //#endregion
15
+ //#region src/api/caseCentricAlignments.ts
16
+ /**
17
+ * Generated by orval 🍺
18
+ * Do not edit manually.
19
+ * Case-Centric Alignments
20
+ * OpenAPI spec version: 1.0
21
+ */
22
+ const withQueryKey = (query, queryKey) => {
23
+ const result = { queryKey };
24
+ for (const key of Object.keys(query)) {
25
+ if (key === "queryKey") continue;
26
+ Object.defineProperty(result, key, {
27
+ enumerable: true,
28
+ configurable: true,
29
+ get: () => query[key]
30
+ });
31
+ }
32
+ return result;
33
+ };
34
+ /**
35
+ * @summary Get Alignments
36
+ */
37
+ const getAlignments = (ocelId, params, options, signal) => {
38
+ return customFetch$1({
39
+ url: `/api/external/modules/alignments/v1/${ocelId}/alignments`,
40
+ method: "GET",
41
+ params,
42
+ signal
43
+ }, options);
44
+ };
45
+ const getGetAlignmentsQueryKey = (ocelId, params) => {
46
+ return [`/api/external/modules/alignments/v1/${ocelId}/alignments`, ...params ? [params] : []];
47
+ };
48
+ const getGetAlignmentsQueryOptions = (ocelId, params, options) => {
49
+ const { query: queryOptions, request: requestOptions } = options ?? {};
50
+ const queryKey = queryOptions?.queryKey ?? getGetAlignmentsQueryKey(ocelId, params);
51
+ const queryFn = ({ signal }) => getAlignments(ocelId, params, requestOptions, signal);
52
+ return {
53
+ queryKey,
54
+ queryFn,
55
+ enabled: ocelId !== null && ocelId !== void 0,
56
+ staleTime: 3e5,
57
+ ...queryOptions
58
+ };
59
+ };
60
+ /**
61
+ * @summary Get Alignments
62
+ */
63
+ function useGetAlignments(ocelId, params, options, queryClient) {
64
+ const queryOptions = getGetAlignmentsQueryOptions(ocelId, params, options);
65
+ const query = useQuery(queryOptions, queryClient);
66
+ return withQueryKey(query, queryOptions.queryKey);
67
+ }
68
+ /**
69
+ * @summary Get Object Types
70
+ */
71
+ const objectTypes = (ocelId, params, options, signal) => {
72
+ return customFetch$1({
73
+ url: `/api/external/modules/alignments/v1/${ocelId}/objects/types`,
74
+ method: "GET",
75
+ params,
76
+ signal
77
+ }, options);
78
+ };
79
+ const getObjectTypesQueryKey = (ocelId, params) => {
80
+ return [`/api/external/modules/alignments/v1/${ocelId}/objects/types`, ...params ? [params] : []];
81
+ };
82
+ const getObjectTypesQueryOptions = (ocelId, params, options) => {
83
+ const { query: queryOptions, request: requestOptions } = options ?? {};
84
+ const queryKey = queryOptions?.queryKey ?? getObjectTypesQueryKey(ocelId, params);
85
+ const queryFn = ({ signal }) => objectTypes(ocelId, params, requestOptions, signal);
86
+ return {
87
+ queryKey,
88
+ queryFn,
89
+ enabled: ocelId !== null && ocelId !== void 0,
90
+ staleTime: 3e5,
91
+ ...queryOptions
92
+ };
93
+ };
94
+ /**
95
+ * @summary Get Object Types
96
+ */
97
+ function useObjectTypes(ocelId, params, options, queryClient) {
98
+ const queryOptions = getObjectTypesQueryOptions(ocelId, params, options);
99
+ const query = useQuery(queryOptions, queryClient);
100
+ return withQueryKey(query, queryOptions.queryKey);
101
+ }
102
+ //#endregion
103
+ //#region src/components/alignments.tsx
104
+ const runStateStore = /* @__PURE__ */ new Map();
105
+ const initialRunState = {
106
+ selectedResourceId: null,
107
+ submittedResourceId: void 0
108
+ };
109
+ const AlignmentComponent = ({ ocelId, objectType, mode }) => {
110
+ const storeKey = `${ocelId}::${objectType}`;
111
+ const [runState, setRunStateLocal] = useState(() => runStateStore.get(storeKey) ?? initialRunState);
112
+ const setRunState = (next) => {
113
+ runStateStore.set(storeKey, next);
114
+ setRunStateLocal(next);
115
+ };
116
+ const hasRun = runState.submittedResourceId !== void 0;
117
+ const { data, isFetching } = useGetAlignments(ocelId, {
118
+ object_type: objectType,
119
+ resource_id: runState.submittedResourceId ?? null
120
+ }, { query: {
121
+ enabled: hasRun,
122
+ staleTime: Infinity,
123
+ gcTime: Infinity,
124
+ refetchOnWindowFocus: false,
125
+ refetchOnReconnect: false,
126
+ placeholderData: keepPreviousData,
127
+ retry: false
128
+ } });
129
+ const runAlignment = () => {
130
+ setRunState({
131
+ ...runState,
132
+ submittedResourceId: runState.selectedResourceId
133
+ });
134
+ };
135
+ const resourceId = runState.selectedResourceId;
136
+ const setResourceId = (id) => setRunState({
137
+ ...runState,
138
+ selectedResourceId: id
139
+ });
140
+ return /* @__PURE__ */ jsxs(Box, {
141
+ pos: "relative",
142
+ h: "100%",
143
+ style: {
144
+ display: "flex",
145
+ flexDirection: "column",
146
+ minHeight: 0
147
+ },
148
+ children: [
149
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: isFetching }),
150
+ /* @__PURE__ */ jsxs(Group, {
151
+ align: "flex-end",
152
+ gap: "sm",
153
+ children: [/* @__PURE__ */ jsx(ResourceSelect, {
154
+ label: "Model",
155
+ description: "Select Process Model to align against",
156
+ type: "e8a4b93820f2f145136e404a06dceb73e074982534c39d64895eda58ab5b5dc1",
157
+ value: resourceId,
158
+ placeholder: "Auto-Discover with Alpha +++",
159
+ onChange: (newResourceId) => setResourceId(newResourceId),
160
+ style: { flex: 1 }
161
+ }), /* @__PURE__ */ jsx(Button, {
162
+ leftSection: /* @__PURE__ */ jsx(PlayIcon, { size: 16 }),
163
+ onClick: runAlignment,
164
+ children: "Run"
165
+ })]
166
+ }),
167
+ /* @__PURE__ */ jsx(Box, {
168
+ style: {
169
+ flex: 1,
170
+ minHeight: 0,
171
+ overflow: "hidden"
172
+ },
173
+ children: !hasRun ? /* @__PURE__ */ jsx(Text, {
174
+ c: "dimmed",
175
+ ta: "center",
176
+ mt: "xl",
177
+ children: "Select a model (or leave on Auto-Discover) and press Run to compute alignments."
178
+ }) : data && (mode === "list" ? /* @__PURE__ */ jsx(AlignmentListViewer, { data }) : /* @__PURE__ */ jsx(ViewerConfigProvider, {
179
+ value: { layout: wasmLayout },
180
+ children: /* @__PURE__ */ jsx(AlignmentNetViewer, { data })
181
+ }))
182
+ })
183
+ ]
184
+ });
185
+ };
186
+ const Alignment = () => {
187
+ const { id } = useCurrentOcel();
188
+ const { data: objectTypes } = useObjectTypes(id, void 0, { query: { enabled: !!id } });
189
+ const [mode, setMode] = useState("list");
190
+ if (!id || !objectTypes) return /* @__PURE__ */ jsx(LoadingOverlay, { visible: true });
191
+ const [firstObjectType, ...otherObjectTypes] = objectTypes;
192
+ if (!firstObjectType) return null;
193
+ return /* @__PURE__ */ jsx(Fragment, { children: otherObjectTypes.length > 0 ? /* @__PURE__ */ jsx(Tabs, {
194
+ defaultValue: firstObjectType,
195
+ keepMounted: false,
196
+ h: "100%",
197
+ children: /* @__PURE__ */ jsxs(Stack, {
198
+ h: "100%",
199
+ gap: "xs",
200
+ children: [/* @__PURE__ */ jsx(Tabs.List, {
201
+ mb: "sm",
202
+ children: objectTypes.map((objectType) => /* @__PURE__ */ jsx(Tabs.Tab, {
203
+ value: objectType,
204
+ children: objectType
205
+ }, objectType))
206
+ }), /* @__PURE__ */ jsxs(Stack, {
207
+ h: "100%",
208
+ px: "xs",
209
+ children: [/* @__PURE__ */ jsx(SegmentedControl, {
210
+ value: mode,
211
+ onChange: setMode,
212
+ data: [{
213
+ label: "Alignment List",
214
+ value: "list"
215
+ }, {
216
+ label: "Alignment Net",
217
+ value: "net"
218
+ }],
219
+ size: "xs",
220
+ w: 280
221
+ }), objectTypes.map((objectType) => /* @__PURE__ */ jsx(Tabs.Panel, {
222
+ value: objectType,
223
+ flex: 1,
224
+ children: /* @__PURE__ */ jsx(AlignmentComponent, {
225
+ ocelId: id,
226
+ objectType,
227
+ mode
228
+ })
229
+ }, objectType))]
230
+ })]
231
+ })
232
+ }) : /* @__PURE__ */ jsxs(Stack, {
233
+ h: "100%",
234
+ px: "xs",
235
+ pt: "xs",
236
+ children: [/* @__PURE__ */ jsx(SegmentedControl, {
237
+ value: mode,
238
+ onChange: setMode,
239
+ data: [{
240
+ label: "Alignment List",
241
+ value: "list"
242
+ }, {
243
+ label: "Alignment Net",
244
+ value: "net"
245
+ }],
246
+ size: "xs",
247
+ w: 280
248
+ }), /* @__PURE__ */ jsx(AlignmentComponent, {
249
+ ocelId: id,
250
+ objectType: firstObjectType,
251
+ mode
252
+ })]
253
+ }) });
254
+ };
255
+ //#endregion
256
+ export { Alignment as default };
@@ -0,0 +1,5 @@
1
+ //#region src/index.d.ts
2
+ export declare const alignmentspage: import("@ocelescope/core").ModuleRouteDefinition;
3
+ declare const _default: import("@ocelescope/core").ModuleDefinition;
4
+ //#endregion
5
+ export { _default as default };
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ import { defineModule, defineModuleRoute } from "@ocelescope/core";
2
+ import { SquareCenterlineDashedVertical } from "lucide-react";
3
+ import dynamic from "next/dynamic";
4
+ //#region src/routes/alignments.tsx
5
+ const Alignment = dynamic(() => import("./alignments-fj7uNw_A.js"), { ssr: false });
6
+ //#endregion
7
+ //#region src/index.ts
8
+ const alignmentspage = defineModuleRoute({
9
+ component: Alignment,
10
+ label: "case-centric",
11
+ name: "Case Centric",
12
+ requiresOcel: true
13
+ });
14
+ var src_default = defineModule({
15
+ name: "alignments",
16
+ label: "Case-Centric Alignments",
17
+ description: "Case-centric Alignments",
18
+ authors: [{ name: "Uy Sa Huynh" }],
19
+ icon: SquareCenterlineDashedVertical,
20
+ routes: [alignmentspage]
21
+ });
22
+ //#endregion
23
+ export { alignmentspage, src_default as default };
package/package.json CHANGED
@@ -1,6 +1,57 @@
1
1
  {
2
2
  "name": "@ocelescope/alignments",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.10.3",
4
+ "description": "case-centric Alignments",
5
+ "author": "Uy Sa Huynh",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/promi4s/ocelescope-module-alignments"
10
+ },
11
+ "exports": {
12
+ ".": "./dist/index.js",
13
+ "./package.json": "./package.json"
14
+ },
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "peerDependencies": {
21
+ "@ocelescope/api-client": "^0.10.2",
22
+ "@ocelescope/core": "^0.10.2",
23
+ "@ocelescope/resources": "^0.10.2",
24
+ "@tanstack/react-query": "^5.104.2",
25
+ "axios": "^1.20.0",
26
+ "lucide-react": "^1.56.0",
27
+ "next": "16.4.0",
28
+ "react": "^19.3.0",
29
+ "react-dom": "^19.3.0",
30
+ "@r4pm/components": "^0.3.2",
31
+ "@mantine/hooks": "^9.7.2",
32
+ "@mantine/core": "^9.7.2",
33
+ "@xyflow/react": "^12.11.3",
34
+ "@mantine/notifications": "^9.7.2"
35
+ },
36
+ "devDependencies": {
37
+ "@ocelescope/api-client": "^0.10.2",
38
+ "@ocelescope/api-config": "^0.10.2",
39
+ "@ocelescope/core": "^0.10.2",
40
+ "@ocelescope/resources": "^0.10.2",
41
+ "@tanstack/react-query": "^5.104.2",
42
+ "@types/react": "^19.3.0",
43
+ "axios": "^1.20.0",
44
+ "lucide-react": "^1.56.0",
45
+ "next": "16.4.0",
46
+ "orval": "^8.42.0",
47
+ "react": "^19.3.0",
48
+ "tsdown": "^0.23.1",
49
+ "typescript": "^6.0.3"
50
+ },
51
+ "scripts": {
52
+ "generate:api": "uv run ocelescope-backend openapi --module alignments",
53
+ "build": "pnpm run generate:api && orval && tsdown",
54
+ "dev": "tsdown --watch ./src",
55
+ "typecheck": "tsc --noEmit"
56
+ }
6
57
  }