Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Referenced Process Export (new MS) #128

Merged
merged 41 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
895ae9e
select box styling, table categories button added, functionality tba
winniel24 Aug 23, 2023
ed9f3df
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Aug 23, 2023
400e3dd
select bar layout wip
winniel24 Aug 23, 2023
51e0738
Merge branch 'modeler-toolbar-zustand-exp' of https://github.com/PROC…
MaxiLein Aug 23, 2023
b81caa1
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Aug 24, 2023
a3c477d
added first version of a breadcrumb
MaxiLein Aug 24, 2023
b1a277c
styling wip
winniel24 Aug 24, 2023
f4ca92f
Breadcrumb version and process select
MaxiLein Aug 24, 2023
09765e6
fuzzy search, dropdown for columns, deselect for multirow
MaxiLein Aug 24, 2023
c383cb7
add comment for fuzzy search
MaxiLein Aug 28, 2023
e645f7b
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Aug 28, 2023
9e00506
changed colour breadcrumb, added latest changes to modeler (jj), Menu…
MaxiLein Aug 28, 2023
ee44b66
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Aug 29, 2023
232c295
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Aug 30, 2023
4051761
Adjusted Modeler height, added Preview-Viewer Co-authored-by: winniel…
MaxiLein Aug 31, 2023
b940034
Made previewer height adjustable
MaxiLein Sep 1, 2023
3b8515f
Merge branch 'main' into modeler-toolbar-zustand-exp
MaxiLein Sep 1, 2023
0a3f6a7
Added export of a single process as bpmn, svg or pdf from the process…
jjoderis Sep 7, 2023
698f1d3
Added the process export modal to the processes view in addition to t…
jjoderis Sep 7, 2023
697da26
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/proce…
jjoderis Sep 7, 2023
37fb59f
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/proce…
jjoderis Sep 8, 2023
3bc7865
Ran prettier
jjoderis Sep 8, 2023
3c27e63
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/proce…
jjoderis Oct 3, 2023
0c42950
Removed unnecessary code
jjoderis Oct 3, 2023
c98738d
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/proce…
jjoderis Oct 5, 2023
1801e6f
Added jszip as a dependency
jjoderis Oct 5, 2023
073fd06
Added option to export multiple processes at once
jjoderis Oct 6, 2023
4770307
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/multi…
jjoderis Oct 9, 2023
3dca4be
Added the option to export user task html alongside process bpmn
jjoderis Oct 10, 2023
0066f78
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/proce…
jjoderis Oct 12, 2023
b173ab6
Added an export preparation step to handle situations where a user se…
jjoderis Oct 12, 2023
fb60ff0
Added image export when artefacts are supposed to be exported with th…
jjoderis Oct 12, 2023
46e600a
Consolidated some logic
jjoderis Oct 12, 2023
0bdf146
Added some comments and fixed a broken import
jjoderis Oct 12, 2023
ab202a4
Removed unused code
jjoderis Oct 12, 2023
b6c34e1
Added option to export collapsed subprocesses seperately for svg and …
jjoderis Oct 12, 2023
7ebe960
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/refer…
jjoderis Oct 18, 2023
7018d04
Add the option to export imported processes (the ones referenced in c…
jjoderis Oct 19, 2023
63de34d
Oriented the export type selection in a vertical order instead of a h…
jjoderis Oct 19, 2023
c81d1b3
Merge branch 'main' of github.com:PROCEED-Labs/proceed into ms2/refer…
jjoderis Oct 19, 2023
d7d7741
Improved code clarity with more/better comments and improved function…
jjoderis Oct 19, 2023
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
39 changes: 28 additions & 11 deletions src/management-system-v2/components/process-export.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';

import { Modal, Checkbox, Radio, RadioChangeEvent } from 'antd';
import { Modal, Checkbox, Radio, RadioChangeEvent, Space } from 'antd';
import type { CheckboxValueType } from 'antd/es/checkbox/Group';

import { exportProcesses } from '@/lib/process-export';
Expand All @@ -13,9 +13,18 @@ const exportTypeOptions = [
];

const exportSubOptions = {
bpmn: [{ label: 'Export with Artefacts', value: 'artefacts' }],
pdf: [{ label: 'Export with collapsed subprocesses', value: 'subprocesses' }],
svg: [{ label: 'Export with collapsed subprocesses', value: 'subprocesses' }],
bpmn: [
{ label: 'Export with referenced Processes', value: 'imports' },
{ label: 'Export with Artefacts', value: 'artefacts' },
],
pdf: [
{ label: 'Export with referenced Processes', value: 'imports' },
{ label: 'Export with collapsed subprocesses', value: 'subprocesses' },
],
svg: [
{ label: 'Export with referenced Processes', value: 'imports' },
{ label: 'Export with collapsed subprocesses', value: 'subprocesses' },
],
};

type ProcessExportModalProps = {
Expand All @@ -27,6 +36,7 @@ const ProcessExportModal: React.FC<ProcessExportModalProps> = ({ processes = [],
const [selectedType, setSelectedType] = useState<ProcessExportOptions['type']>();
const [selectedOptions, setSelectedOptions] = useState<CheckboxValueType[]>([]);
const [finishedTypeSelection, setfinishedTypeSelection] = useState(false);
const [isExporting, setIsExporting] = useState(false);

const handleTypeSelectionChange = ({ target: { value } }: RadioChangeEvent) => {
setSelectedType(value);
Expand All @@ -38,7 +48,9 @@ const ProcessExportModal: React.FC<ProcessExportModalProps> = ({ processes = [],

const handleClose = () => {
setSelectedType(undefined);
setSelectedOptions([]);
setfinishedTypeSelection(false);
setIsExporting(false);
onClose();
};

Expand All @@ -52,11 +64,13 @@ const ProcessExportModal: React.FC<ProcessExportModalProps> = ({ processes = [],
}
}

setIsExporting(true);
await exportProcesses(
{
type: selectedType!,
artefacts: selectedOptions.some((el) => el === 'artefacts'),
subprocesses: selectedOptions.some((el) => el === 'subprocesses'),
imports: selectedOptions.some((el) => el === 'imports'),
},
processes,
);
Expand All @@ -69,12 +83,15 @@ const ProcessExportModal: React.FC<ProcessExportModalProps> = ({ processes = [],
: 'Select the file type';

const typeSelection = (
<Radio.Group
options={exportTypeOptions}
onChange={handleTypeSelectionChange}
value={selectedType}
style={{ flexDirection: 'column' }}
/>
<Radio.Group onChange={handleTypeSelectionChange} value={selectedType}>
<Space direction="vertical">
{exportTypeOptions.map(({ label, value }) => (
<Radio value={value} key={value}>
{label}
</Radio>
))}
</Space>
</Radio.Group>
);

const optionSelection = (
Expand All @@ -94,7 +111,7 @@ const ProcessExportModal: React.FC<ProcessExportModalProps> = ({ processes = [],
onOk={handleOk}
onCancel={handleClose}
centered
okButtonProps={{ disabled: !selectedType }}
okButtonProps={{ disabled: !selectedType, loading: isExporting }}
>
{finishedTypeSelection ? optionSelection : typeSelection}
</Modal>
Expand Down
135 changes: 104 additions & 31 deletions src/management-system-v2/lib/process-export/export-preparation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
toBpmnObject,
getElementDI,
getDefinitionsVersionInformation,
getDefinitionsAndProcessIdForEveryCallActivity,
} from '@proceed/bpmn-helper';

/**
Expand All @@ -22,6 +23,7 @@ export type ProcessExportOptions = {
type: 'bpmn' | 'svg' | 'pdf';
artefacts: boolean; // if artefacts like images or user task html should be included in the export
subprocesses: boolean; // if collapsed subprocesses should be exported as well (svg, pdf)
imports: boolean; // if processes referenced by this process should be exported as well
};

/**
Expand All @@ -35,11 +37,14 @@ export type ExportProcessInfo = { definitionId: string; processVersion?: number
export type ProcessExportData = {
definitionId: string;
definitionName: string;
isImport: boolean;
versions: {
[version: string]: {
name?: string;
bpmn: string;
subprocesses: { id: string; name: string }[];
isImport: boolean;
subprocesses: { id: string; name?: string }[];
imports: { definitionId: string; processVersion: string }[];
};
};
userTasks: {
Expand Down Expand Up @@ -106,7 +111,7 @@ function getImagesReferencedByHtml(html: string) {
*
* @param bpmn
*/
async function getCollapsedSubprocessIds(bpmn: string) {
async function getCollapsedSubprocessInfos(bpmn: string) {
const definitions = await toBpmnObject(bpmn);
const subprocesses = getElementsByTagName(definitions, 'bpmn:SubProcess');

Expand All @@ -123,11 +128,14 @@ async function getCollapsedSubprocessIds(bpmn: string) {
type ExportMap = {
[definitionId: string]: {
definitionName: string;
isImport: boolean;
versions: {
[version: string]: {
name?: string;
bpmn: string;
subprocesses: { id: string; name: string }[];
isImport: boolean;
subprocesses: { id: string; name?: string }[];
imports: { definitionId: string; processVersion: string }[];
};
};
userTasks: {
Expand All @@ -141,6 +149,57 @@ type ExportMap = {
};
};

function getVersionName(version?: string | number) {
return version ? `${version}` : 'latest';
}

/**
* Will fetch information for a process (version) from the backend if it is not present in the exportData yet
*
* @param exportData the currently existing process data to export
* @param processInfo the info that identifies the process (version) to fetch
* @param isImport if the data should be marked as (only) required as part of an import if it was not fetched before
*/
async function ensureProcessInfo(
exportData: ExportMap,
{ definitionId, processVersion }: { definitionId: string; processVersion?: string | number },
isImport = false,
) {
if (!exportData[definitionId]) {
const process = await fetchProcess(definitionId);

if (!process) {
throw new Error(
`Failed to get process info (definitionId: ${definitionId}) during process export`,
);
}

exportData[definitionId] = {
definitionName: process.definitionName,
isImport,
versions: {},
userTasks: [],
images: [],
};
}

// prevent (unlikely) situations where a version might be referenced once by number and once by string
const versionName = getVersionName(processVersion);

if (!exportData[definitionId].versions[versionName]) {
const versionBpmn = await getVersionBpmn(definitionId, processVersion);
const versionInformation = await getDefinitionsVersionInformation(versionBpmn);

exportData[definitionId].versions[versionName] = {
name: versionInformation.name,
bpmn: versionBpmn,
isImport,
subprocesses: [],
imports: [],
};
}
}

/**
* Gets the data that is needed to export all the requested processes with the given options
*
Expand All @@ -157,40 +216,54 @@ export async function prepareExport(
}

const exportData: ExportMap = {};
// get the bpmn for all processes and their versions to export
for (const { definitionId, processVersion } of processes) {
const process = await fetchProcess(definitionId);

if (!process) {
throw new Error(
`Failed to get process info (definitionId: ${definitionId}) during process export`,
);
let processVersionsToAdd = processes.map((info) => ({ ...info, isImport: false }));

// keep resolving process (version) information until no new information is required by imports
while (processVersionsToAdd.length) {
let newProcessVersionsToAdd: typeof processVersionsToAdd = [];
// get the bpmn for all processes and their versions to export
for (const { definitionId, processVersion, isImport } of processVersionsToAdd) {
await ensureProcessInfo(exportData, { definitionId, processVersion }, isImport);

// if the option to export referenced processes is selected make sure to fetch their information as well
if (options.imports) {
const versionName = getVersionName(processVersion);
const { bpmn, imports } = exportData[definitionId].versions[versionName];

// check the bpmn for referenced processes
const importInfo = await getDefinitionsAndProcessIdForEveryCallActivity(bpmn, true);

for (const { definitionId: importDefinitionId, version: importVersion } of Object.values(
importInfo,
)) {
// add the import information to the respective version
imports.push({ definitionId: importDefinitionId, processVersion: `${importVersion}` });
const importVersionName = getVersionName(importVersion);
// mark the process (version) as to be added if there is no information for it
if (!exportData[importDefinitionId]?.versions[importVersionName]) {
newProcessVersionsToAdd.push({
definitionId: importDefinitionId,
processVersion: importVersion,
isImport: true,
});
}
}
}
}
processVersionsToAdd = newProcessVersionsToAdd;
}

// prevent (unlikely) situations where a version might be referenced once by number and once by string
const versionName = processVersion ? `${processVersion}` : 'latest';

const versionBpmn = await getVersionBpmn(definitionId, processVersion);
const versionInformation = await getDefinitionsVersionInformation(versionBpmn);

exportData[definitionId] = {
definitionName: process.definitionName,
versions: {
[versionName]: {
name: versionInformation.name,
bpmn: versionBpmn,
subprocesses: [],
},
},
userTasks: [],
images: [],
};

// get additional process information
for (const definitionId of Object.keys(exportData)) {
// get the ids of all collapsed subprocesses so they can be used later during export
if (options.subprocesses) {
for (const [version, { bpmn }] of Object.entries(exportData[definitionId].versions)) {
exportData[definitionId].versions[version].subprocesses =
await getCollapsedSubprocessIds(bpmn);
exportData[definitionId].versions[version].subprocesses = (
await getCollapsedSubprocessInfos(bpmn)
)
// the subprocess info is returned in the reversed order from what we want (we want from the outmost subprocess to the most nested)
.reverse();
}
}

Expand Down
Loading