Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StoredDeployment } from '@/lib/data/deployment';
import { ExtendedInstanceInfo } from '@/lib/data/instance';
import { InstanceInfo } from '@/lib/engines/deployment';
import { Version } from '@prisma/client';
import { convertISODurationToMiliseconds } from '@proceed/bpmn-helper/src/getters';
import type { ElementLike } from 'diagram-js/lib/core/Types';

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

export function getLatestDeployment(deployments: StoredDeployment[]) {
return deployments.reduce(
export function getLatestVersion(versions: Version[]) {
return versions.reduce(
(latest, curr) => {
if (!latest || latest.deployTime.getTime() > curr.deployTime.getTime()) {
if (!latest || latest.createdOn.getTime() < curr.createdOn.getTime()) {
return curr;
}
return latest;
},
undefined as undefined | StoredDeployment,
undefined as undefined | Version,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { isUserErrorResponse } from '@/lib/user-error';
import { getProcessDeployments } from '@/lib/data/deployment';

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

if (isUserErrorResponse(deployments)) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { ColorOptions, colorOptions } from './instance-coloring';
import { RemoveReadOnly, truthyFilter } from '@/lib/typescript-utils';
import type { ElementLike } from 'diagram-js/lib/core/Types';
import { wrapServerCall } from '@/lib/wrap-server-call';
import { getLatestDeployment, getVersionInstances, getYoungestInstance } from './instance-helpers';
import { getLatestVersion, getVersionInstances, getYoungestInstance } from './instance-helpers';

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

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

const isExecutableVersionMap = useRef<Record<string, boolean>>({});

const { data: versions } = useQuery({
queryFn: async () => {
let versions = await getVersions(spaceId, processId);
if (isUserErrorResponse(versions)) return [];

// filter out all versions that are not executable
versions = await asyncFilter(versions, async (version) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honest I am not sure whether I am right or not, or how much effort will it need to implement my suggestion. But fetching all version from db after every 1 second and then parsing it to BpmnObject seems very heavy and expensive (consider we have 7 versions of a large process).

so if I am not wrong then my suggestion is may be we can cash the result of each parse on first load and reuse it on every next refetch. because versions are immutable anyway and not gonna change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a simple caching implementation so each version will have its "executable" property calculated only once

if (version.id in isExecutableVersionMap.current) {
return isExecutableVersionMap.current[version.id];
}

const bpmnObj = await toBpmnObject(version.bpmn);
const processes = getElementsByTagName(bpmnObj, 'bpmn:Process');
if (!processes.length) return false;
isExecutableVersionMap.current[version.id] = processes[0].isExecutable;
return processes[0].isExecutable;
});

versions.sort((a, b) => {
return b.createdOn.getTime() - a.createdOn.getTime();
});

return versions;
},
queryKey: ['processVersions', spaceId, processId],
refetchInterval: 1000,
});

// get information where the process is deployed and which instances exist
const { data: deployments, refetch: refetchDeployments } = useQuery({
queryFn: async () => {
const deployments = await getProcessDeployments(spaceId, processId);
const deployments = await getProcessDeployments(spaceId, processId, undefined, true, true);
if (isUserErrorResponse(deployments)) return null;
return deployments;
},
Expand Down Expand Up @@ -130,8 +160,8 @@ export default function ProcessDeploymentView({ processId }: { processId: string
const { selectedVersion, versionInstances, currentVersion } = useMemo(() => {
let selectedVersion, versionInstances, currentVersion;

if (deployments?.length) {
selectedVersion = deployments.find((d) => d.versionId === selectedVersionId)?.version;
if (versions?.length) {
selectedVersion = versions.find((v) => v.id === selectedVersionId);

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

let currentVersionId = getLatestDeployment(deployments)!.versionId;
let currentVersionId = getLatestVersion(versions)!.id;
if (selectedInstance) {
currentVersionId = selectedInstance.processVersion;
} else if (selectedVersionId) {
currentVersionId = selectedVersionId;
}
currentVersion = deployments.find((d) => d.versionId === currentVersionId)!.version;
currentVersion = versions.find((v) => v.id === currentVersionId);
}

return {
selectedVersion,
versionInstances,
currentVersion,
};
}, [deployments, knownInstances, selectedVersionId, selectedInstanceId]);
}, [versions, knownInstances, selectedVersionId, selectedInstanceId]);

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

const { data: selectedBpmn } = useQuery({
queryFn: async () => {
const bpmn = await getProcessBPMN(processId, spaceId, currentVersion?.id);
if (isUserErrorResponse(bpmn)) return undefined;
return { bpmn };
return { bpmn: currentVersion?.bpmn || '' };
},
queryKey: ['space', spaceId, 'process', processId, 'version', currentVersion?.id || '', 'bpmn'],
});
Expand Down Expand Up @@ -315,11 +343,11 @@ export default function ProcessDeploymentView({ processId }: { processId: string
},
]
: []),
...deployments.map(({ version }) => ({
label: version.name,
key: `${version.id}`,
...(versions?.map((v) => ({
key: v.id,
label: v.name,
disabled: false,
})),
})) || []),
],
selectable: true,
onSelect: ({ key }) => {
Expand Down Expand Up @@ -370,14 +398,7 @@ export default function ProcessDeploymentView({ processId }: { processId: string
setStartingInstance(true);
await wrapServerCall({
fn: async () => {
const latestDeployment = getLatestDeployment(deployments);
if (!latestDeployment) {
return userError(
'The current process does not seem to be deployed anymore.',
);
}

const { versionId } = latestDeployment;
const { id: versionId } = currentVersion!;

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

Expand Down Expand Up @@ -451,7 +472,7 @@ export default function ProcessDeploymentView({ processId }: { processId: string
onClick={async () => {
setTogglingActivation(true);
const nextState = !isProcessActivated;
const versionId = getLatestDeployment(deployments)!.versionId;
const versionId = currentVersion!.id;
await wrapServerCall({
fn: () =>
changeDeploymentActivation(processId, spaceId, versionId, nextState),
Expand Down Expand Up @@ -641,10 +662,10 @@ export default function ProcessDeploymentView({ processId }: { processId: string
// start the instance with the initial variable values from the start form
await wrapServerCall({
fn: async () => {
const deployment = getLatestDeployment(deployments);

if (!deployment) {
return userError('The current process does not seem to be deployed.');
if (!currentVersion) {
return userError(
'The current process does not seem to have versions to execute.',
);
}

const mappedVariables: Record<string, { value: any }> = {};
Expand All @@ -656,8 +677,8 @@ export default function ProcessDeploymentView({ processId }: { processId: string

return startInstance(
spaceId,
deployment.processId,
deployment.version.id,
currentVersion.processId,
currentVersion.id,
mappedVariables,
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import processListStyles from '@/components/process-icon-list.module.scss';
type InputItem = {
id: string;
name: string;
versions: { id: string; name: string }[];
versions: { id: string; name: string; deployed: boolean }[];
instances: string[];
};
export type DeployedProcessListProcess = ReplaceKeysWithHighlighted<InputItem, 'name'>;
Expand Down Expand Up @@ -95,9 +95,13 @@ const DeploymentsList = ({
dataIndex: 'id',
key: 'Meta Data Button',
title: '',
render: () => {
render: (_, record) => {
return (
<Button style={{ float: 'right' }} type="text">
<Button
style={{ float: 'right' }}
type="text"
disabled={record.versions.every((v) => !v.deployed)}
>
<DeleteOutlined color="red" />
</Button>
);
Expand Down Expand Up @@ -138,6 +142,7 @@ const DeploymentsList = ({
style={{ float: 'right' }}
type="text"
onClick={() => removeDeployment(record.id)}
disabled={record.versions.every((v) => !v.deployed)}
>
<DeleteOutlined color="red" />
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import { App, Button } from 'antd';
import { useEffect, useState, useTransition } from 'react';
import { App, Button, Checkbox, Space, Spin, Tooltip, Typography } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { useCallback, useEffect, useState, useTransition } from 'react';
import DeploymentsModal from './deployments-modal';
import Bar from '@/components/bar';
import useFuzySearch from '@/lib/useFuzySearch';
Expand All @@ -10,7 +11,7 @@ import { Folder } from '@/lib/data/folder-schema';
import { Process, ProcessMetadata } from '@/lib/data/process-schema';
import { useEnvironment } from '@/components/auth-can';
import { processUnchangedFromBasedOnVersion } from '@/lib/data/processes';
import { useRouter } from 'next/navigation';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import {
deployProcess as serverDeployProcess,
removeDeployment as serverRemoveDeployment,
Expand All @@ -34,12 +35,13 @@ const DeploymentsView = ({
deployedProcesses: {
id: string;
name: string;
versions: { id: string; name: string }[];
versions: { id: string; name: string; deployed: boolean }[];
instances: string[];
}[];
}) => {
const [modalIsOpen, setModalIsOpen] = useState(false);
const app = App.useApp();
const pathname = usePathname();
const space = useEnvironment();
const router = useRouter();
const queryClient = useQueryClient();
Expand All @@ -51,6 +53,25 @@ const DeploymentsView = ({
transformData: (matches) => matches.map((match) => match.item),
});

const [togglingShowArchived, startTogglingShowArchived] = useTransition();
const query = useSearchParams();
// Get a new searchParams string by merging the current
// searchParams with a provided key/value pair
// see: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams
const createQueryString = useCallback(
(name: string, value: string) => {
const params = new URLSearchParams(query.toString());
if (!value) {
params.delete(name);
} else {
params.set(name, value);
}

return params.toString();
},
[query],
);

const [checkingProcessVersion, startCheckingProcessVersion] = useTransition();
function deployProcess(
process: Pick<Process, 'id' | 'versions'>,
Expand Down Expand Up @@ -125,15 +146,23 @@ const DeploymentsView = ({
setInitialLoading(false);
}, []);

const loading = initialLoading || checkingProcessVersion || removingDeployment;
const loading =
initialLoading || checkingProcessVersion || removingDeployment || togglingShowArchived;

const tableProps: { loading: boolean; pagination?: false } = { loading };

if (initialLoading) tableProps.pagination = false;

return (
<div>
<div style={{ marginBottom: '0.5rem' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'baseline',
marginBottom: '0.5rem',
}}
>
<Button
type="primary"
onClick={() => {
Expand All @@ -143,6 +172,29 @@ const DeploymentsView = ({
>
Deploy Process
</Button>

<Space>
{togglingShowArchived ? (
<Spin size="small" />
) : (
<Checkbox
checked={query.get('archived') == 'true'}
onChange={(el) =>
startTogglingShowArchived(() => {
router.push(
pathname + '?' + createQueryString('archived', el.target.checked ? 'true' : ''),
);
})
}
/>
)}
<Typography.Text>
Show Past Executions{' '}
<Tooltip title="This option displays all processes that have already been executed in the past, even if a process has already been deleted from the Management System.">
<QuestionCircleOutlined />
</Tooltip>
</Typography.Text>
</Space>
</div>

<Bar
Expand Down
Loading
Loading