diff --git a/src/engine/universal/core/src/__tests__/engine.test.js b/src/engine/universal/core/src/__tests__/engine.test.js index 37a7e97b8..f8c180897 100644 --- a/src/engine/universal/core/src/__tests__/engine.test.js +++ b/src/engine/universal/core/src/__tests__/engine.test.js @@ -102,8 +102,8 @@ describe('ProceedEngine', () => { it('calls given callbacks for executed process', async () => { distribution.db.getProcessVersion.mockResolvedValueOnce(scriptTaskBPMN); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded, onTokenEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded, onTokenEnded); await sleep(1000); @@ -119,8 +119,8 @@ describe('ProceedEngine', () => { it('contains added information from proceed in token and logs for executed process', async () => { distribution.db.getProcessVersion.mockResolvedValueOnce(scriptTaskBPMN); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded, onTokenEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded, onTokenEnded); await hasEnded; @@ -195,8 +195,8 @@ describe('ProceedEngine', () => { let onEnded1; const hasEnded1 = new Promise((resolve) => (onEnded1 = resolve)); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded1); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded1); expect(engine.instanceIDs.length).toBe(1); await hasEnded1; @@ -205,7 +205,7 @@ describe('ProceedEngine', () => { const hasEnded2 = new Promise((resolve) => (onEnded2 = resolve)); expect(() => { - engine.startProcessVersion(123, {}, onStarted, onEnded2); + engine.startProcessVersion('123', {}, onStarted, onEnded2); }).not.toThrow(); expect(engine.instanceIDs.length).toBe(1); @@ -218,9 +218,9 @@ describe('ProceedEngine', () => { let onEnded1; const hasEnded1 = new Promise((resolve) => (onEnded1 = resolve)); - await engine.deployProcessVersion(0, 123); + await engine.deployProcessVersion('0', '123'); const onStarted1 = jest.fn(); - engine.startProcessVersion(123, {}, onStarted1, onEnded1); + engine.startProcessVersion('123', {}, onStarted1, onEnded1); expect(engine.instanceIDs.length).toBe(1); await hasEnded1; @@ -230,9 +230,9 @@ describe('ProceedEngine', () => { let onEnded2; const hasEnded2 = new Promise((resolve) => (onEnded2 = resolve)); - await engine.deployProcessVersion(0, 456); + await engine.deployProcessVersion('0', '456'); const onStarted2 = jest.fn(); - engine.startProcessVersion(456, {}, onStarted2, onEnded2); + engine.startProcessVersion('456', {}, onStarted2, onEnded2); expect(engine.instanceIDs.length).toBe(1); await hasEnded2; @@ -248,8 +248,8 @@ describe('ProceedEngine', () => { it('calls given network-service in a script task', async () => { distribution.db.getProcessVersion.mockResolvedValueOnce(scriptTaskBPMN); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded); await hasEnded; @@ -260,8 +260,8 @@ describe('ProceedEngine', () => { distribution.db.getProcessVersion.mockResolvedValueOnce(userTaskBPMN); const userTaskID = 'Task_1y4wd2q'; - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded); await sleep(500); @@ -285,8 +285,8 @@ describe('ProceedEngine', () => { it('takes variables input on a userTask', async () => { distribution.db.getProcessVersion.mockResolvedValueOnce(userTaskBPMN); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded); await sleep(500); @@ -317,8 +317,8 @@ describe('ProceedEngine', () => { it('can be stopped through api function', async () => { distribution.db.getProcessVersion.mockResolvedValueOnce(userTaskBPMN); - await engine.deployProcessVersion(0, 123); - engine.startProcessVersion(123, {}, onStarted, onEnded); + await engine.deployProcessVersion('0', '123'); + engine.startProcessVersion('123', {}, onStarted, onEnded); await sleep(500); @@ -345,9 +345,9 @@ describe('ProceedEngine', () => { log: [], }; - await engine.deployProcessVersion(0, 123); + await engine.deployProcessVersion('0', '123'); engine.startProcessVersion( - 123, + '123', {}, instance, () => { diff --git a/src/engine/universal/core/src/__tests__/management.test.js b/src/engine/universal/core/src/__tests__/management.test.js index 9e131b94d..c22c1caa8 100644 --- a/src/engine/universal/core/src/__tests__/management.test.js +++ b/src/engine/universal/core/src/__tests__/management.test.js @@ -151,11 +151,11 @@ describe('Management', () => { jest.spyOn(Engine.prototype, 'deployProcessVersion'); jest.spyOn(Engine.prototype, 'startProcessVersion'); distribution.db.isProcessVersionValid.mockResolvedValue(true); - const instanceId = await management.createInstance(0, 123, {}); + const instanceId = await management.createInstance('0', '123', {}); expect(management.getEngineWithID(instanceId)).toBeInstanceOf(Engine); - expect(Engine.prototype.deployProcessVersion).toHaveBeenCalledWith(0, 123); + expect(Engine.prototype.deployProcessVersion).toHaveBeenCalledWith('0', '123'); expect(Engine.prototype.startProcessVersion).toHaveBeenCalledWith( - 123, + '123', {}, undefined, undefined, @@ -166,9 +166,9 @@ describe('Management', () => { it('reuses an existing ProceedEngine instance when there is one for the given definitionsId to start an instance', async () => { jest.spyOn(Engine.prototype, 'deployProcessVersion'); jest.spyOn(Engine.prototype, 'startProcessVersion'); - const firstInstanceId = await management.createInstance(0, 123, {}); + const firstInstanceId = await management.createInstance('0', '123', {}); - const secondInstanceId = await management.createInstance(0, 123, {}); + const secondInstanceId = await management.createInstance('0', '123', {}); const firstEngine = management.getEngineWithID(firstInstanceId); expect(management.getEngineWithID(firstInstanceId)).toBe( @@ -183,7 +183,7 @@ describe('Management', () => { const instance = { processId: '0', - processVersion: 789, + processVersion: '789', processInstanceId: '0-123', tokens: [ { @@ -213,11 +213,11 @@ describe('Management', () => { }; // try to continue instance which was never started on this engine - const engine = await management.continueInstance(0, instance); + const engine = await management.continueInstance('0', instance); expect(engine).toBeInstanceOf(Engine); - expect(Engine.prototype.deployProcessVersion).toHaveBeenCalledWith(0, 789); + expect(Engine.prototype.deployProcessVersion).toHaveBeenCalledWith('0', '789'); expect(Engine.prototype.startProcessVersion).toHaveBeenCalledWith( - 789, + '789', {}, startingInstanceInfo, expect.any(Function), @@ -252,13 +252,13 @@ describe('Management', () => { }); distribution.db.getProcessVersion.mockReturnValue(testBPMN); distribution.db.isProcessVersionValid.mockResolvedValue(true); - await management.createInstance(0, 123, {}); + await management.createInstance('0', '123', {}); // distribution.db.getProcess.mockResolvedValueOnce(testBPMN); - await management.createInstance(1, 456, {}); + await management.createInstance('1', '456', {}); // distribution.db.getProcess.mockResolvedValueOnce(testBPMN); - await management.createInstance(2, 789, {}); + await management.createInstance('2', '789', {}); await new Promise((resolve) => { setTimeout(() => { @@ -271,9 +271,9 @@ describe('Management', () => { it('remove process engine', async () => { jest.spyOn(Engine.prototype, 'startProcessVersion'); - await management.createInstance(0, 123, {}); - expect(management.getEngineWithDefinitionId(0)).toBeInstanceOf(Engine); - management.removeProcessEngine(0); - expect(management.getEngineWithDefinitionId(0)).toBeUndefined(); + await management.createInstance('0', '123', {}); + expect(management.getEngineWithDefinitionId('0')).toBeInstanceOf(Engine); + management.removeProcessEngine('0'); + expect(management.getEngineWithDefinitionId('0')).toBeUndefined(); }); }); diff --git a/src/engine/universal/core/src/engine/engine.js b/src/engine/universal/core/src/engine/engine.js index 05ecfeb69..65d18838a 100644 --- a/src/engine/universal/core/src/engine/engine.js +++ b/src/engine/universal/core/src/engine/engine.js @@ -405,8 +405,7 @@ class Engine { const instance = this.getInstance(instanceId); const state = instance.getState(); - const processId = state.processId.substring(0, state.processId.lastIndexOf('-')); - const version = state.processId.substring(processId.length + 1); + const version = state.processId.substring(this.definitionId.length + 1); return this._versionBpmnMapping[version]; } @@ -439,9 +438,7 @@ class Engine { const state = instance.getState(); - // FIXME: Doesn't work when version ID is not a number string (e.g. uuid) - const processId = state.processId.substring(0, state.processId.lastIndexOf('-')); - const processVersion = state.processId.substring(processId.length + 1); + const processVersion = state.processId.substring(this.definitionId.length + 1); // map the adaptation log migration entries to show the version info const adaptationLog = state.adaptationLog.map((entry) => { @@ -449,15 +446,15 @@ class Engine { return { type: entry.type, time: entry.time, - sourceVersion: entry.from.substring(processId.length + 1), - targetVersion: entry.to.substring(processId.length + 1), + sourceVersion: entry.from.substring(this.definitionId.length + 1), + targetVersion: entry.to.substring(this.definitionId.length + 1), }; } else { return entry; } }); - const instanceInfo = { ...state, processId, processVersion, adaptationLog }; + const instanceInfo = { ...state, processId: this.definitionId, processVersion, adaptationLog }; if (instance.callingInstance) { instanceInfo.callingInstance = instance.callingInstance; diff --git a/src/engine/universal/core/src/engine/hookCallbacks.js b/src/engine/universal/core/src/engine/hookCallbacks.js index 0662bda92..1c74c15ca 100644 --- a/src/engine/universal/core/src/engine/hookCallbacks.js +++ b/src/engine/universal/core/src/engine/hookCallbacks.js @@ -250,11 +250,11 @@ module.exports = { }); // we are starting a new local instance to continue an instance started on another machine } + engine.instanceIDs.push(newInstance.id); const state = newInstance.getState(); - const processId = state.processId.substring(0, state.processId.lastIndexOf('-')); - const processVersion = state.processId.substring(processId.length + 1); + const processVersion = state.processId.substring(engine.definitionId.length + 1); engine._instanceIdProcessMapping[newInstance.id] = engine._versionProcessMapping[processVersion]; diff --git a/src/engine/universal/ui/src/display-items/tasklist/TaskList-DisplayItem.js b/src/engine/universal/ui/src/display-items/tasklist/TaskList-DisplayItem.js index 36fca4b71..e1b9494db 100644 --- a/src/engine/universal/ui/src/display-items/tasklist/TaskList-DisplayItem.js +++ b/src/engine/universal/ui/src/display-items/tasklist/TaskList-DisplayItem.js @@ -157,7 +157,15 @@ class TaskListTab extends DisplayItem { const entries = data.entries(); let entry = entries.next(); while (!entry.done) { - [, variables[entry.value[0]]] = entry.value; + const [key, value] = entry.value; + if (variables[key]) { + if (!Array.isArray(variables[key])) { + variables[key] = [variables[key]]; + } + variables[key].push(value); + } else { + variables[key] = value; + } entry = entries.next(); } diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/executions/deployments-view.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/executions/deployments-view.tsx index 7e358991e..0dde91305 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/executions/deployments-view.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/executions/deployments-view.tsx @@ -58,11 +58,19 @@ const DeploymentsView = ({ } const v = process.versions - .map((v) => v.id) - .sort() - .at(-1); + .map((v) => ({ id: v.id, creationTime: +v.createdOn })) + .sort((a, b) => { + return b.creationTime - a.creationTime; + }) + .at(0); - await deployProcess(process.id, v as string, space.spaceId, 'dynamic'); + if (!v) { + message.error('There is no version to deploy!'); + + return; + } + + await deployProcess(process.id, v.id, space.spaceId, 'dynamic'); refetchDeployedProcesses(); } catch (e) { message.error("Something wen't wrong"); diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/_sidebar/Toolbox.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/_sidebar/Toolbox.tsx index 27f9c024f..df306542b 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/_sidebar/Toolbox.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/_sidebar/Toolbox.tsx @@ -3,14 +3,23 @@ import { Button as AntButton } from 'antd'; import { ReactNode } from 'react'; import { LuFormInput, LuImage, LuTable, LuText } from 'react-icons/lu'; -import { MdCheckBox, MdRadioButtonChecked, MdTitle } from 'react-icons/md'; +import { MdCheckBox, MdRadioButtonChecked, MdTitle, MdOutlineCheck } from 'react-icons/md'; import { RxGroup } from 'react-icons/rx'; import { useDraggable } from '@dnd-kit/core'; import styles from './index.module.scss'; -import { Text, Container, Input, CheckBoxOrRadioGroup, Column, Table, Image } from '../elements'; +import { + Text, + Container, + Input, + CheckBoxOrRadioGroup, + Column, + Table, + EditImage as Image, + SubmitButton, +} from '../elements'; import { createPortal } from 'react-dom'; @@ -92,6 +101,9 @@ const Toolbox = () => { }> + }> + + ); }; diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/CheckboxOrRadioGroup.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/CheckboxOrRadioGroup.tsx index dacae4c86..1ecc55f79 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/CheckboxOrRadioGroup.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/CheckboxOrRadioGroup.tsx @@ -396,20 +396,13 @@ export const CheckBoxOrRadioGroupSettings = () => { + onChange={(e) => { setProp((props: CheckBoxOrRadioGroupProps) => { - props.variable = val; - }) - } + props.variable = e.target.value; + }); + }} /> } /> diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Image.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Image.tsx index d320ae5e0..16f4147fc 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Image.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Image.tsx @@ -19,7 +19,29 @@ type ImageProps = { width?: number; }; -const Image: UserComponent = ({ src, reloadParam, width }) => { +// How the image should be rendered for use outside of the MS (mainly for use on the engine) +export const ExportImage: UserComponent = ({ src, width }) => { + if (src) { + // transform the url used inside the MS into the one expected on the engine + // cannot use useParams and useEnvironment since this will not be used inside the context in + // which they are defined + const msUrl = src.split('/'); + const filename = msUrl.pop(); + msUrl.pop(); + const definitionId = msUrl.pop(); + + src = `/resources/process/${definitionId}/images/${filename}`; + } + + return ( +
+ +
+ ); +}; + +// the Image component to use in the Editor +export const EditImage: UserComponent = ({ src, reloadParam, width }) => { const { query } = useEditor(); const [showResize, setShowResize] = useState(false); @@ -36,6 +58,7 @@ const Image: UserComponent = ({ src, reloadParam, width }) => { return { isHovered: !!parent && parent.events.hovered }; }); + const { editingEnabled } = useEditor((state) => ({ editingEnabled: state.options.enabled })); const { @@ -43,6 +66,7 @@ const Image: UserComponent = ({ src, reloadParam, width }) => { download: getImageUrl, remove, } = useFileManager({ entityType: EntityType.PROCESS }); + const params = useParams<{ processId: string }>(); const environment = useEnvironment(); @@ -231,7 +255,7 @@ export const ImageSettings = () => { ); }; -Image.craft = { +EditImage.craft = { rules: { canDrag: () => false, }, @@ -257,5 +281,3 @@ Image.craft = { }, }, }; - -export default Image; diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Input.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Input.tsx index 92df3e7dd..befc63271 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Input.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/Input.tsx @@ -1,6 +1,6 @@ import { useEffect, useId, useState } from 'react'; -import { Select } from 'antd'; +import { Select, Input as AntInput } from 'antd'; import { EditOutlined } from '@ant-design/icons'; import { UserComponent, useEditor, useNode } from '@craftjs/core'; @@ -14,6 +14,7 @@ type InputProps = { type?: 'text' | 'number' | 'email'; defaultValue?: string; labelPosition?: 'top' | 'left' | 'none'; + variable?: string; }; const Input: UserComponent = ({ @@ -21,6 +22,7 @@ const Input: UserComponent = ({ type = 'text', defaultValue = '', labelPosition = 'top', + variable, }) => { const { connectors: { connect }, @@ -92,6 +94,7 @@ const Input: UserComponent = ({ id={inputId} type={type} value={defaultValue} + name={variable} onClick={() => { if (!editingEnabled) return; setEditingDefault(true); @@ -112,9 +115,11 @@ export const InputSettings = () => { actions: { setProp }, type, labelPosition, + variable, } = useNode((node) => ({ type: node.data.props.type, labelPosition: node.data.props.labelPosition, + variable: node.data.props.variable, })); const { editingEnabled } = useEditor((state) => ({ editingEnabled: state.options.enabled })); @@ -160,6 +165,19 @@ export const InputSettings = () => { /> } /> + { + setProp((props: InputProps) => { + props.variable = e.target.value; + }); + }} + /> + } + /> ); }; @@ -176,6 +194,7 @@ Input.craft = { label: 'New Input', defaultValue: '', labelPosition: 'top', + variable: undefined, }, }; diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/SubmitButton.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/SubmitButton.tsx index 5ec823dc2..69e72e3ef 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/SubmitButton.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/SubmitButton.tsx @@ -1,29 +1,126 @@ -import { useNode, UserComponent } from '@craftjs/core'; +import { useNode, UserComponent, useEditor } from '@craftjs/core'; + +import { EditOutlined } from '@ant-design/icons'; + +import EditableText from '../_utils/EditableText'; +import React, { useState } from 'react'; +import { Overlay, Setting } from './utils'; + +import cn from 'classnames'; +import { Checkbox, Select } from 'antd'; type SubmitButtonProps = React.PropsWithChildren & { - size?: 'large' | 'middle' | 'small'; - type?: 'primary' | 'default' | 'danger'; + title?: string; + type?: 'primary' | 'default'; + block?: boolean; }; -const SubmitButton: UserComponent = ({ children }) => { +const SubmitButton: UserComponent = ({ + title = '', + type = 'primary', + block = false, +}) => { const { connectors: { connect }, + actions: { setProp }, } = useNode(); + const [textEditing, setTextEditing] = useState(false); + const [hovered, setHovered] = useState(false); + + return ( +
+ +
+ ); +}; + +export const SubmitButtonSettings = () => { + const { + actions: { setProp }, + type, + block, + } = useNode((node) => ({ + type: node.data.props.type, + block: node.data.props.block, + })); + const { editingEnabled } = useEditor((state) => ({ editingEnabled: state.options.enabled })); + return ( - + <> + + setProp((props: SubmitButtonProps) => { + props.type = val; + }) + } + /> + } + /> + { + setProp((props: SubmitButtonProps) => { + props.block = e.target.checked; + }); + }} + /> + } + /> + ); }; SubmitButton.craft = { + props: { + title: 'Submit', + type: 'primary', + block: false, + }, + related: { + settings: SubmitButtonSettings, + }, rules: { canDrag: () => false, }, diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/index.ts b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/index.ts index bdc428fff..33d599bc0 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/index.ts +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/elements/index.ts @@ -1,11 +1,22 @@ import CheckBoxOrRadioGroup from './CheckboxOrRadioGroup'; import Column from './Column'; import Container from './Container'; -import Image from './Image'; +import { EditImage, ExportImage } from './Image'; import Input from './Input'; import Row from './Row'; import SubmitButton from './SubmitButton'; import Table from './Table'; import Text from './Text'; -export { CheckBoxOrRadioGroup, Column, Container, Image, Input, Row, SubmitButton, Table, Text }; +export { + CheckBoxOrRadioGroup, + Column, + Container, + EditImage, + ExportImage, + Input, + Row, + SubmitButton, + Table, + Text, +}; diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/index.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/index.tsx index a116b82e0..7bce49fef 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/index.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/index.tsx @@ -29,7 +29,6 @@ import { DiffResult, deepEquals } from '@/lib/helpers/javascriptHelpers'; import { updateFileDeletableStatus as updateImageRefCounter } from '@/lib/data/file-manager-facade'; import { is as bpmnIs } from 'bpmn-js/lib/util/ModelUtil'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; type BuilderProps = { processId: string; @@ -55,8 +54,6 @@ const EditorModal: React.FC = ({ return { editingEnabled: state.options.enabled }; }); - const queryClient = new QueryClient(); - const environment = useEnvironment(); const [iframeMounted, setIframeMounted] = useState(false); @@ -227,6 +224,7 @@ const UserTaskBuilder: React.FC = ({ processId, open, onClose }) = diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/utils.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/utils.tsx index 1b330e224..57e4d4afa 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/utils.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/processes/[processId]/_user-task-builder/utils.tsx @@ -3,7 +3,6 @@ import React from 'react'; import ReactDOMServer from 'react-dom/server'; import * as Elements from './elements'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const styles = ` body { @@ -107,6 +106,21 @@ body { margin: 3px 3px 6px 0; } +.user-task-form-button { + background-color: #eee; + box-shadow: rgba(0,0,0, 0.02) 0 2px 0 0; + padding: 4px 15px; + border-radius: 6px; + border: 1px solid lightgrey; +} + +.user-task-form-button.primary-button { + box-shadow: rgba(5, 145, 255, 0.1) 0 2px 0 0; + background-color: rgb(22, 119, 255); + color: white; + border-color: rgb(22, 119, 255); +} + .user-task-form-image { width: 100%; display: flex; @@ -148,17 +162,15 @@ p, h1, h2, h3, h4, h5, th, td { `; export function toHtml(json: string) { - const queryClient = new QueryClient(); const markup = ReactDOMServer.renderToStaticMarkup( - - - + , ); @@ -169,9 +181,14 @@ export function toHtml(json: string) { + - ${markup} +
+ ${markup} +
`; @@ -194,7 +211,7 @@ export const iframeDocument = ` .frame-content > div { box-sizing: border-box; - padding: 0 10px; + padding: 0 10px; } .user-task-form-column { @@ -209,6 +226,10 @@ export const iframeDocument = ` position: relative; } + .user-task-form-button { + position: relative; + } + .user-task-form-image > div { position: absolute; background-color: rgba(0, 0, 0, 0.5); @@ -271,6 +292,7 @@ export const iframeDocument = `
+ `; diff --git a/src/management-system-v2/app/api/private/[environmentId]/processes/[processId]/images/[imageFileName]/route.ts b/src/management-system-v2/app/api/private/[environmentId]/processes/[processId]/images/[imageFileName]/route.ts index f573af1e1..0849bfd67 100644 --- a/src/management-system-v2/app/api/private/[environmentId]/processes/[processId]/images/[imageFileName]/route.ts +++ b/src/management-system-v2/app/api/private/[environmentId]/processes/[processId]/images/[imageFileName]/route.ts @@ -12,6 +12,7 @@ import jwt from 'jsonwebtoken'; import { TokenPayload } from '@/lib/sharing/process-sharing'; import { invalidRequest, readImage } from '../../../../image-helpers'; +import { v4 } from 'uuid'; export async function GET( request: NextRequest, @@ -107,9 +108,11 @@ export async function PUT( const readImageResult = await readImage(request); if (readImageResult.error) return readImageResult.error; - await saveProcessImage(processId, imageFileName, readImageResult.buffer); + const newImageFileName = `_image${v4()}.${readImageResult.fileType.ext}`; - return new NextResponse(null, { status: 200, statusText: 'OK' }); + await saveProcessImage(processId, newImageFileName, readImageResult.buffer); + + return new NextResponse(newImageFileName, { status: 201, statusText: 'Created' }); } export async function DELETE( diff --git a/src/management-system-v2/lib/data/file-manager-facade.ts b/src/management-system-v2/lib/data/file-manager-facade.ts index bba36c826..1d0af0214 100644 --- a/src/management-system-v2/lib/data/file-manager-facade.ts +++ b/src/management-system-v2/lib/data/file-manager-facade.ts @@ -13,6 +13,8 @@ import db from '@/lib/data/db'; import { getProcessUserTaskJSON } from './db/process'; import { asyncMap, findKey } from '../helpers/javascriptHelpers'; +const DEPLOYMENT_ENV = process.env.NEXT_PUBLIC_DEPLOYMENT_ENV as 'cloud' | 'local'; + // Allowed content types for files const ALLOWED_CONTENT_TYPES = [ 'image/jpeg', @@ -324,6 +326,8 @@ export async function updateArtifactProcessReference( processId: string, status: boolean, ) { + if (DEPLOYMENT_ENV !== 'cloud') return; + const artifact = await db.artifact.findUnique({ where: { fileName }, }); diff --git a/src/management-system-v2/lib/engines/http-endpoints.ts b/src/management-system-v2/lib/engines/http-endpoints.ts index e2834a377..9913957af 100644 --- a/src/management-system-v2/lib/engines/http-endpoints.ts +++ b/src/management-system-v2/lib/engines/http-endpoints.ts @@ -47,15 +47,15 @@ export function sendUserTaskHTML( }); } -export function sendImage(machine: Machine, definitionId: string, fileName: string, image: Blob) { +export function sendImage(machine: Machine, definitionId: string, fileName: string, image: Buffer) { return fetch( generateRequestUrl(machine, `/resources/process/${definitionId}/images/${fileName}`), { method: 'PUT', headers: { - 'Content-Type': 'image/png image/svg+xml image/jpeg', + 'Content-Type': 'application/json', }, - body: image, + body: JSON.stringify({ type: 'Buffer', data: image }), }, ); } diff --git a/src/management-system-v2/lib/helpers/processVersioning.ts b/src/management-system-v2/lib/helpers/processVersioning.ts index fa55916f3..6b83a837b 100644 --- a/src/management-system-v2/lib/helpers/processVersioning.ts +++ b/src/management-system-v2/lib/helpers/processVersioning.ts @@ -9,14 +9,6 @@ import { setUserTaskData, } from '@proceed/bpmn-helper'; import { asyncForEach } from './javascriptHelpers'; -import { - deleteProcessUserTask, - getProcessUserTaskHtml, - getProcessUserTasksHtml, - getProcessUserTasksJSON, - saveProcessUserTask, - getProcessUserTaskJSON as getUserTaskJSON, -} from '../data/db/process'; //from '../data/legacy/_process'; import { Process } from '../data/process-schema'; import { enableUseDB } from 'FeatureFlags'; @@ -29,13 +21,29 @@ const { diff } = require('bpmn-js-differ'); let getProcessVersionBpmn: TProcessModule['getProcessVersionBpmn']; let updateProcess: TProcessModule['updateProcess']; let getProcessBpmn: TProcessModule['getProcessBpmn']; +let deleteProcessUserTask: TProcessModule['deleteProcessUserTask']; +let getProcessUserTaskHtml: TProcessModule['getProcessUserTaskHtml']; +let getProcessUserTasksHtml: TProcessModule['getProcessUserTasksHtml']; +let getProcessUserTasksJSON: TProcessModule['getProcessUserTasksJSON']; +let saveProcessUserTask: TProcessModule['saveProcessUserTask']; +let getProcessUserTaskJSON: TProcessModule['getProcessUserTaskJSON']; const loadModules = async () => { const moduleImport = await (enableUseDB ? import('@/lib/data/db/process') : import('@/lib/data/legacy/_process')); - ({ getProcessVersionBpmn, updateProcess, getProcessBpmn } = moduleImport); + ({ + getProcessVersionBpmn, + updateProcess, + getProcessBpmn, + deleteProcessUserTask, + getProcessUserTaskHtml, + getProcessUserTasksHtml, + getProcessUserTasksJSON, + saveProcessUserTask, + getProcessUserTaskJSON, + } = moduleImport); }; loadModules().catch(console.error); @@ -172,7 +180,7 @@ export async function versionUserTasks( // store the user task version if it didn't exist before if (!dryRun && !userTaskHtmlAlreadyExisting) { - const userTaskData = await getUserTaskJSON(processInfo.id, fileName); + const userTaskData = await getProcessUserTaskJSON(processInfo.id, fileName); await saveProcessUserTask( processInfo.id, versionFileName, diff --git a/src/management-system-v2/lib/process-export/export-preparation.ts b/src/management-system-v2/lib/process-export/export-preparation.ts index 4e104843e..21b599536 100644 --- a/src/management-system-v2/lib/process-export/export-preparation.ts +++ b/src/management-system-v2/lib/process-export/export-preparation.ts @@ -74,7 +74,7 @@ export type ProcessExportData = { }[]; images: { filename: string; - data: Blob; + data: Buffer; }[]; }; @@ -169,7 +169,7 @@ type ExportMap = { }[]; images: { filename: string; - data: Blob; + data: Buffer; }[]; }; }; @@ -435,7 +435,7 @@ export async function prepareExport( exportData[definitionId].images.push({ filename, - data: new Blob([image]), + data: image, }); } }