Skip to content

Commit 49d0ff8

Browse files
committed
Merge branch 'main' of github.com:PROCEED-Labs/proceed into fix/caching-related-bugs
2 parents bd086d3 + 4c3970f commit 49d0ff8

33 files changed

Lines changed: 553 additions & 175 deletions

File tree

src/management-system-v2/app/(auth)/signin/page.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { getCurrentUser } from '@/components/auth';
33
import { redirect } from 'next/navigation';
44
import SignIn from './signin';
55
import { generateGuestReferenceToken } from '@/lib/reference-guest-user-token';
6-
import { env } from '@/lib/ms-config/env-vars';
76
import db from '@/lib/data/db';
87
import { connection } from 'next/server';
98
import { Suspense } from 'react';
9+
import { getMSConfig } from '@/lib/ms-config/ms-config';
1010

1111
const dayInMS = 1000 * 60 * 60 * 24;
1212

@@ -60,7 +60,8 @@ const Deferred: React.FC<{}> = async ({}) => {
6060
else userType = isGuest ? ('guest' as const) : ('user' as const);
6161

6262
let logoUrl;
63-
if (env.PROCEED_PUBLIC_IAM_ONLY_ONE_ORGANIZATIONAL_SPACE) {
63+
const config = await getMSConfig();
64+
if (config.PROCEED_PUBLIC_IAM_ONLY_ONE_ORGANIZATIONAL_SPACE) {
6465
const org = await db.space.findFirst({
6566
where: {
6667
isOrganization: true,

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-helpers.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { StoredDeployment } from '@/lib/data/deployment';
22
import { ExtendedInstanceInfo } from '@/lib/data/instance';
33
import { InstanceInfo } from '@/lib/engines/deployment';
4+
import { Version } from '@prisma/client';
45
import { convertISODurationToMiliseconds } from '@proceed/bpmn-helper/src/getters';
56
import type { ElementLike } from 'diagram-js/lib/core/Types';
67

@@ -179,15 +180,15 @@ export function getVersionInstances(instances: ExtendedInstanceInfo[], version?:
179180
return instances.filter((instance) => instance.processVersion === version);
180181
}
181182

182-
export function getLatestDeployment(deployments: StoredDeployment[]) {
183-
return deployments.reduce(
183+
export function getLatestVersion(versions: Version[]) {
184+
return versions.reduce(
184185
(latest, curr) => {
185-
if (!latest || latest.deployTime.getTime() > curr.deployTime.getTime()) {
186+
if (!latest || latest.createdOn.getTime() < curr.createdOn.getTime()) {
186187
return curr;
187188
}
188189
return latest;
189190
},
190-
undefined as undefined | StoredDeployment,
191+
undefined as undefined | Version,
191192
);
192193
}
193194

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { isUserErrorResponse } from '@/lib/user-error';
77
import { getProcessDeployments } from '@/lib/data/deployment';
88

99
async function Deployment({ processId, spaceId }: { processId: string; spaceId: string }) {
10-
const deployments = await getProcessDeployments(spaceId, processId);
10+
const deployments = await getProcessDeployments(spaceId, processId, undefined, true, true);
1111

1212
if (isUserErrorResponse(deployments)) {
1313
return (

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { ColorOptions, colorOptions } from './instance-coloring';
2626
import { RemoveReadOnly, truthyFilter } from '@/lib/typescript-utils';
2727
import type { ElementLike } from 'diagram-js/lib/core/Types';
2828
import { wrapServerCall } from '@/lib/wrap-server-call';
29-
import { getLatestDeployment, getVersionInstances, getYoungestInstance } from './instance-helpers';
29+
import { getLatestVersion, getVersionInstances, getYoungestInstance } from './instance-helpers';
3030

3131
import useColors from './use-colors';
3232
import useTokens from './use-tokens';
@@ -53,8 +53,8 @@ import { useQuery } from '@tanstack/react-query';
5353
import { getProcessDeployments } from '@/lib/data/deployment';
5454
import { isSuccessResponse, isUserErrorResponse, userError } from '@/lib/user-error';
5555
import { getInstance } from '@/lib/data/instance';
56-
import { asyncMap, pick } from '@/lib/helpers/javascriptHelpers';
57-
import { getProcessBPMN } from '@/lib/data/processes';
56+
import { asyncFilter, asyncMap, pick } from '@/lib/helpers/javascriptHelpers';
57+
import { getVersions } from '@/lib/data/processes';
5858
import { enableInstanceCSVExport } from 'FeatureFlags';
5959
import jsonToCsvExport from 'json-to-csv-export';
6060

@@ -80,10 +80,40 @@ export default function ProcessDeploymentView({ processId }: { processId: string
8080
const canvasRef = useRef<BPMNCanvasRef>(null);
8181
const [infoPanelOpen, setInfoPanelOpen] = useState(false);
8282

83+
const isExecutableVersionMap = useRef<Record<string, boolean>>({});
84+
85+
const { data: versions } = useQuery({
86+
queryFn: async () => {
87+
let versions = await getVersions(spaceId, processId);
88+
if (isUserErrorResponse(versions)) return [];
89+
90+
// filter out all versions that are not executable
91+
versions = await asyncFilter(versions, async (version) => {
92+
if (version.id in isExecutableVersionMap.current) {
93+
return isExecutableVersionMap.current[version.id];
94+
}
95+
96+
const bpmnObj = await toBpmnObject(version.bpmn);
97+
const processes = getElementsByTagName(bpmnObj, 'bpmn:Process');
98+
if (!processes.length) return false;
99+
isExecutableVersionMap.current[version.id] = processes[0].isExecutable;
100+
return processes[0].isExecutable;
101+
});
102+
103+
versions.sort((a, b) => {
104+
return b.createdOn.getTime() - a.createdOn.getTime();
105+
});
106+
107+
return versions;
108+
},
109+
queryKey: ['processVersions', spaceId, processId],
110+
refetchInterval: 1000,
111+
});
112+
83113
// get information where the process is deployed and which instances exist
84114
const { data: deployments, refetch: refetchDeployments } = useQuery({
85115
queryFn: async () => {
86-
const deployments = await getProcessDeployments(spaceId, processId);
116+
const deployments = await getProcessDeployments(spaceId, processId, undefined, true, true);
87117
if (isUserErrorResponse(deployments)) return null;
88118
return deployments;
89119
},
@@ -130,8 +160,8 @@ export default function ProcessDeploymentView({ processId }: { processId: string
130160
const { selectedVersion, versionInstances, currentVersion } = useMemo(() => {
131161
let selectedVersion, versionInstances, currentVersion;
132162

133-
if (deployments?.length) {
134-
selectedVersion = deployments.find((d) => d.versionId === selectedVersionId)?.version;
163+
if (versions?.length) {
164+
selectedVersion = versions.find((v) => v.id === selectedVersionId);
135165

136166
// sort instances newest first
137167
const rawInstances = getVersionInstances(knownInstances, selectedVersionId);
@@ -143,21 +173,21 @@ export default function ProcessDeploymentView({ processId }: { processId: string
143173
? versionInstances.find((i) => i.processInstanceId === selectedInstanceId)
144174
: undefined;
145175

146-
let currentVersionId = getLatestDeployment(deployments)!.versionId;
176+
let currentVersionId = getLatestVersion(versions)!.id;
147177
if (selectedInstance) {
148178
currentVersionId = selectedInstance.processVersion;
149179
} else if (selectedVersionId) {
150180
currentVersionId = selectedVersionId;
151181
}
152-
currentVersion = deployments.find((d) => d.versionId === currentVersionId)!.version;
182+
currentVersion = versions.find((v) => v.id === currentVersionId);
153183
}
154184

155185
return {
156186
selectedVersion,
157187
versionInstances,
158188
currentVersion,
159189
};
160-
}, [deployments, knownInstances, selectedVersionId, selectedInstanceId]);
190+
}, [versions, knownInstances, selectedVersionId, selectedInstanceId]);
161191

162192
const { data: currentInstance, refetch: refetchCurrentInstance } = useQuery({
163193
queryKey: ['processDeployments', spaceId, processId, 'instance', selectedInstanceId],
@@ -179,9 +209,7 @@ export default function ProcessDeploymentView({ processId }: { processId: string
179209

180210
const { data: selectedBpmn } = useQuery({
181211
queryFn: async () => {
182-
const bpmn = await getProcessBPMN(processId, spaceId, currentVersion?.id);
183-
if (isUserErrorResponse(bpmn)) return undefined;
184-
return { bpmn };
212+
return { bpmn: currentVersion?.bpmn || '' };
185213
},
186214
queryKey: ['space', spaceId, 'process', processId, 'version', currentVersion?.id || '', 'bpmn'],
187215
});
@@ -320,11 +348,11 @@ export default function ProcessDeploymentView({ processId }: { processId: string
320348
},
321349
]
322350
: []),
323-
...deployments.map(({ version }) => ({
324-
label: version.name,
325-
key: `${version.id}`,
351+
...(versions?.map((v) => ({
352+
key: v.id,
353+
label: v.name,
326354
disabled: false,
327-
})),
355+
})) || []),
328356
],
329357
selectable: true,
330358
onSelect: ({ key }) => {
@@ -375,14 +403,7 @@ export default function ProcessDeploymentView({ processId }: { processId: string
375403
setStartingInstance(true);
376404
await wrapServerCall({
377405
fn: async () => {
378-
const latestDeployment = getLatestDeployment(deployments);
379-
if (!latestDeployment) {
380-
return userError(
381-
'The current process does not seem to be deployed anymore.',
382-
);
383-
}
384-
385-
const { versionId } = latestDeployment;
406+
const { id: versionId } = currentVersion!;
386407

387408
let startForm = await getProcessStartForm(spaceId, processId, versionId);
388409

@@ -454,7 +475,7 @@ export default function ProcessDeploymentView({ processId }: { processId: string
454475
onClick={async () => {
455476
setTogglingActivation(true);
456477
const nextState = !isProcessActivated;
457-
const versionId = getLatestDeployment(deployments)!.versionId;
478+
const versionId = currentVersion!.id;
458479
await wrapServerCall({
459480
fn: () =>
460481
changeDeploymentActivation(processId, spaceId, versionId, nextState),
@@ -644,10 +665,10 @@ export default function ProcessDeploymentView({ processId }: { processId: string
644665
// start the instance with the initial variable values from the start form
645666
await wrapServerCall({
646667
fn: async () => {
647-
const deployment = getLatestDeployment(deployments);
648-
649-
if (!deployment) {
650-
return userError('The current process does not seem to be deployed.');
668+
if (!currentVersion) {
669+
return userError(
670+
'The current process does not seem to have versions to execute.',
671+
);
651672
}
652673

653674
const mappedVariables: Record<string, { value: any }> = {};
@@ -659,8 +680,8 @@ export default function ProcessDeploymentView({ processId }: { processId: string
659680

660681
return startInstance(
661682
spaceId,
662-
deployment.processId,
663-
deployment.version.id,
683+
currentVersion.processId,
684+
currentVersion.id,
664685
mappedVariables,
665686
true,
666687
);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { ReactNode } from 'react';
2+
import { statusToType } from './instance-helpers';
3+
import type { ElementLike } from 'diagram-js/lib/core/Types';
4+
import { ExtendedInstanceInfo } from '@/lib/data/instance';
5+
import {
6+
CheckCircleOutlined,
7+
ClockCircleOutlined,
8+
CloseCircleOutlined,
9+
ExclamationCircleOutlined,
10+
SyncOutlined,
11+
} from '@ant-design/icons';
12+
import { Tag } from 'antd';
13+
14+
export const StatusTag = ({
15+
processId,
16+
element,
17+
instance,
18+
}: {
19+
processId: string;
20+
element?: ElementLike;
21+
instance?: ExtendedInstanceInfo;
22+
}) => {
23+
// Element status
24+
const isRootElement = element && element.type === 'bpmn:Process';
25+
let status = undefined;
26+
if (isRootElement && instance) {
27+
status = instance.instanceState.reduce((overallState, state) => {
28+
return ['ENDED', 'STOPPED'].includes(overallState) ? state : overallState;
29+
});
30+
} else if (element && instance) {
31+
const elementInfo = instance.log.find((l) => l.flowElementId == element.id);
32+
if (elementInfo) {
33+
status = elementInfo.executionState;
34+
} else {
35+
const tokenInfo = instance.tokens.find((l) => l.currentFlowElementId == element.id);
36+
status = tokenInfo ? tokenInfo.currentFlowNodeState : 'WAITING';
37+
}
38+
}
39+
const statusType = status && statusToType(status);
40+
const presets: Record<string, ReactNode> = {
41+
READY: <CheckCircleOutlined />,
42+
COMPLETED: <CheckCircleOutlined />,
43+
RUNNING: <SyncOutlined spin />,
44+
info: <ExclamationCircleOutlined />,
45+
warning: <ExclamationCircleOutlined />,
46+
STOPPED: <CloseCircleOutlined />,
47+
WAITING: <ClockCircleOutlined />,
48+
};
49+
return (
50+
status &&
51+
statusType && (
52+
<Tag
53+
key={status}
54+
color={statusType}
55+
icon={status ? presets[status] : <ClockCircleOutlined />}
56+
>
57+
{status}
58+
</Tag>
59+
)
60+
);
61+
};

src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/deployments-list.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import processListStyles from '@/components/process-icon-list.module.scss';
1111
type InputItem = {
1212
id: string;
1313
name: string;
14-
versions: { id: string; name: string }[];
14+
versions: { id: string; name: string; deployed: boolean }[];
1515
instances: string[];
1616
};
1717
export type DeployedProcessListProcess = ReplaceKeysWithHighlighted<InputItem, 'name'>;
@@ -95,9 +95,13 @@ const DeploymentsList = ({
9595
dataIndex: 'id',
9696
key: 'Meta Data Button',
9797
title: '',
98-
render: () => {
98+
render: (_, record) => {
9999
return (
100-
<Button style={{ float: 'right' }} type="text">
100+
<Button
101+
style={{ float: 'right' }}
102+
type="text"
103+
disabled={record.versions.every((v) => !v.deployed)}
104+
>
101105
<DeleteOutlined color="red" />
102106
</Button>
103107
);
@@ -138,6 +142,7 @@ const DeploymentsList = ({
138142
style={{ float: 'right' }}
139143
type="text"
140144
onClick={() => removeDeployment(record.id)}
145+
disabled={record.versions.every((v) => !v.deployed)}
141146
>
142147
<DeleteOutlined color="red" />
143148
</Button>

0 commit comments

Comments
 (0)