@haiiro/docuflow 0.0.16 → 0.0.17
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 +8 -2
- package/manifest.json +34 -19
- package/package.json +1 -1
- package/public/app/docflow-app.js +5 -5
- package/src/front-components/docflow-documents.front-component.mjs +1 -1
- package/src/front-components/docflow-processes.front-component.mjs +35 -35
- package/src/front-components/docflow-processes.front-component.tsx +187 -85
- package/src/front-components/docflow-tasks.front-component.mjs +24 -24
- package/src/front-components/launch-process.front-component.mjs +19 -19
- package/src/front-components/launch-process.front-component.tsx +36 -60
- package/src/front-components/process-steps.front-component.mjs +17 -17
- package/src/front-components/task-form.front-component.mjs +10 -10
- package/src/logic-functions/bitrix-app.logic-function.mjs +1 -1
- package/src/logic-functions/complete-task.logic-function.mjs +39 -8
- package/src/logic-functions/docflow-app.logic-function.mjs +1 -1
- package/src/logic-functions/hand-out-form-step.logic-function.mjs +71278 -11217
- package/src/logic-functions/hand-out-form-step.logic-function.ts +1 -1
- package/src/logic-functions/launch-process.logic-function.mjs +269 -33
- package/src/logic-functions/launch-process.logic-function.ts +42 -37
- package/src/logic-functions/on-task-updated.logic-function.mjs +39 -8
- package/src/logic-functions/on-workflow-run-updated.logic-function.mjs +35 -9
- package/src/logic-functions/on-workflow-run-updated.logic-function.ts +6 -3
- package/src/logic-functions/process-catalog.logic-function.mjs +119726 -0
- package/src/logic-functions/process-catalog.logic-function.ts +84 -0
- package/src/logic-functions/publish-process.logic-function.mjs +218 -16
- package/src/logic-functions/publish-process.logic-function.ts +13 -5
- package/src/logic-functions/save-launch-fields.logic-function.mjs +5 -2
- package/src/logic-functions/save-step-settings.logic-function.mjs +5 -2
|
@@ -10,38 +10,24 @@ import {
|
|
|
10
10
|
import { IconPlayerPlay } from 'twenty-ui/icon';
|
|
11
11
|
import { useTheme } from 'twenty-ui/theme';
|
|
12
12
|
|
|
13
|
-
import { callAppRoute, getErrorMessage
|
|
13
|
+
import { callAppRoute, getErrorMessage } from 'src/front/api';
|
|
14
14
|
import { useAsync } from 'src/front/hooks/use-async';
|
|
15
15
|
import { DocflowRoot, Message, pluralize, SectionTitle } from 'src/front/ui/components';
|
|
16
16
|
import { FormFieldInputs } from 'src/front/ui/form-field-inputs';
|
|
17
17
|
import { Button, MenuRow } from 'src/front/ui/kit';
|
|
18
|
-
import {
|
|
19
|
-
import { DOCFLOW_SECTION, LAUNCH_RECORDS_LIMIT } from 'src/shared/docflow.constants';
|
|
18
|
+
import { LAUNCH_RECORDS_LIMIT } from 'src/shared/docflow.constants';
|
|
20
19
|
import { type FormField, type FormValues } from 'src/shared/form/form-field.type';
|
|
21
20
|
import { findMissingRequiredFields } from 'src/shared/form/form-fields.util';
|
|
22
21
|
import { logDocflowError } from 'src/shared/log.util';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
isLaunchTrigger,
|
|
26
|
-
parseLaunchFields,
|
|
27
|
-
parseLaunchObject,
|
|
28
|
-
} from 'src/shared/workflow/launch-step.util';
|
|
22
|
+
import { buildLaunchParameters } from 'src/shared/workflow/launch-step.util';
|
|
23
|
+
import { type CatalogProcess } from 'src/shared/workflow/process-catalog.type';
|
|
29
24
|
import { type WorkflowTrigger } from 'src/shared/workflow/workflow-run.type';
|
|
30
25
|
import { LAUNCH_PROCESS_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from 'src/universal-identifiers';
|
|
31
26
|
|
|
32
|
-
const PROCESSES_LIMIT = 200;
|
|
33
27
|
const RECORD_NOUN: [string, string, string] = ['запись', 'записи', 'записей'];
|
|
34
28
|
|
|
35
|
-
type WorkflowRecord = {
|
|
36
|
-
id: string;
|
|
37
|
-
name?: string | null;
|
|
38
|
-
smbLaunchFields?: unknown;
|
|
39
|
-
smbLaunchObject?: string | null;
|
|
40
|
-
};
|
|
41
|
-
type WorkflowVersionRecord = { id: string; workflowId: string; trigger?: WorkflowTrigger | null };
|
|
42
|
-
|
|
43
29
|
type LaunchableProcess = {
|
|
44
|
-
|
|
30
|
+
workflowId: string;
|
|
45
31
|
name: string;
|
|
46
32
|
launchFields: FormField[];
|
|
47
33
|
// Launched on the selected records, or without a record
|
|
@@ -56,42 +42,32 @@ const isGlobalManualTrigger = (trigger: WorkflowTrigger | null | undefined) => {
|
|
|
56
42
|
};
|
|
57
43
|
|
|
58
44
|
// The published docflow processes this place can launch: on the selected
|
|
59
|
-
// records the ones of their object, and everywhere the ones without a record
|
|
45
|
+
// records the ones of their object, and everywhere the ones without a record
|
|
46
|
+
// (a webhook one, or a manual one offered everywhere).
|
|
60
47
|
const loadLaunchableProcesses = async (objectName: string | undefined): Promise<LaunchableProcess[]> => {
|
|
61
|
-
const {
|
|
62
|
-
|
|
63
|
-
order_by: 'name[AscNullsLast]',
|
|
64
|
-
limit: PROCESSES_LIMIT,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
if (workflows.length === 0) {
|
|
68
|
-
return [];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const { records: versions } = await listRecords<WorkflowVersionRecord>('workflowVersions', {
|
|
72
|
-
filter: restAnd(restEq('status', 'ACTIVE'), restIn('workflowId', workflows.map(({ id }) => id))),
|
|
73
|
-
limit: PROCESSES_LIMIT,
|
|
48
|
+
const { processes: catalog } = await callAppRoute<{ processes: CatalogProcess[] }>('/docflow/processes/catalog', {
|
|
49
|
+
action: 'list',
|
|
74
50
|
});
|
|
75
51
|
|
|
76
|
-
const processes =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
52
|
+
const processes = catalog
|
|
53
|
+
.sort((first, second) => first.name.localeCompare(second.name, 'ru'))
|
|
54
|
+
.flatMap((process): LaunchableProcess[] => {
|
|
55
|
+
const trigger = process.active?.trigger;
|
|
56
|
+
const isLaunchable =
|
|
57
|
+
(trigger?.type === 'WEBHOOK' || isGlobalManualTrigger(trigger)) &&
|
|
58
|
+
(process.launchObject === undefined || process.launchObject === objectName);
|
|
59
|
+
|
|
60
|
+
return isLaunchable
|
|
61
|
+
? [
|
|
62
|
+
{
|
|
63
|
+
workflowId: process.workflowId,
|
|
64
|
+
name: process.name,
|
|
65
|
+
launchFields: trigger?.type === 'WEBHOOK' ? process.launchFields : [],
|
|
66
|
+
isOnRecords: process.launchObject !== undefined,
|
|
67
|
+
},
|
|
68
|
+
]
|
|
69
|
+
: [];
|
|
70
|
+
});
|
|
95
71
|
|
|
96
72
|
// The processes of the record come first
|
|
97
73
|
return [...processes.filter(({ isOnRecords }) => isOnRecords), ...processes.filter(({ isOnRecords }) => !isOnRecords)];
|
|
@@ -127,7 +103,7 @@ const LaunchForm = ({
|
|
|
127
103
|
|
|
128
104
|
try {
|
|
129
105
|
const { workflowRunIds } = await callAppRoute<{ workflowRunIds: string[] }>('/docflow/processes/launch', {
|
|
130
|
-
|
|
106
|
+
workflowId: process.workflowId,
|
|
131
107
|
values: parameters,
|
|
132
108
|
recordIds: launchRecordIds,
|
|
133
109
|
});
|
|
@@ -147,7 +123,7 @@ const LaunchForm = ({
|
|
|
147
123
|
resetNavigationStack: true,
|
|
148
124
|
});
|
|
149
125
|
} catch (error) {
|
|
150
|
-
logDocflowError('launch: failed', error, {
|
|
126
|
+
logDocflowError('launch: failed', error, { workflowId: process.workflowId });
|
|
151
127
|
setErrorMessage(getErrorMessage(error, 'Не удалось запустить процесс'));
|
|
152
128
|
setIsLaunching(false);
|
|
153
129
|
}
|
|
@@ -203,13 +179,13 @@ const LaunchProcess = () => {
|
|
|
203
179
|
const selectedRecordIds = useSelectedRecordIds();
|
|
204
180
|
const selectedObject = useSelectedObjectMetadata();
|
|
205
181
|
const objectName = selectedRecordIds.length > 0 ? selectedObject?.nameSingular : undefined;
|
|
206
|
-
const [
|
|
182
|
+
const [selectedWorkflowId, setSelectedWorkflowId] = useState<string | undefined>();
|
|
207
183
|
const { data: processes, error, loading } = useAsync(
|
|
208
184
|
() => loadLaunchableProcesses(objectName),
|
|
209
185
|
[objectName],
|
|
210
186
|
);
|
|
211
187
|
const onlyProcess = processes?.length === 1 ? processes[0] : undefined;
|
|
212
|
-
const selectedProcess = onlyProcess ?? processes?.find(({
|
|
188
|
+
const selectedProcess = onlyProcess ?? processes?.find(({ workflowId }) => workflowId === selectedWorkflowId);
|
|
213
189
|
|
|
214
190
|
return (
|
|
215
191
|
<DocflowRoot>
|
|
@@ -228,17 +204,17 @@ const LaunchProcess = () => {
|
|
|
228
204
|
)}
|
|
229
205
|
{selectedProcess !== undefined ? (
|
|
230
206
|
<LaunchForm
|
|
231
|
-
key={selectedProcess.
|
|
207
|
+
key={selectedProcess.workflowId}
|
|
232
208
|
process={selectedProcess}
|
|
233
209
|
recordIds={selectedRecordIds}
|
|
234
|
-
onBack={onlyProcess === undefined ? () =>
|
|
210
|
+
onBack={onlyProcess === undefined ? () => setSelectedWorkflowId(undefined) : undefined}
|
|
235
211
|
/>
|
|
236
212
|
) : (
|
|
237
213
|
processes !== undefined &&
|
|
238
214
|
processes.length > 0 && (
|
|
239
215
|
<div style={{ display: 'flex', flexDirection: 'column', gap: theme.spacing[1] }}>
|
|
240
216
|
{processes.map((process, index) => (
|
|
241
|
-
<div key={process.
|
|
217
|
+
<div key={process.workflowId}>
|
|
242
218
|
{objectName !== undefined && index === processes.findIndex(({ isOnRecords }) => isOnRecords === process.isOnRecords) && (
|
|
243
219
|
<SectionTitle>{process.isOnRecords ? 'На выбранной записи' : 'Без записи'}</SectionTitle>
|
|
244
220
|
)}
|
|
@@ -250,7 +226,7 @@ const LaunchProcess = () => {
|
|
|
250
226
|
? `${process.launchFields.length} ${pluralize(process.launchFields.length, ['параметр', 'параметра', 'параметров'])}`
|
|
251
227
|
: undefined
|
|
252
228
|
}
|
|
253
|
-
onClick={() =>
|
|
229
|
+
onClick={() => setSelectedWorkflowId(process.workflowId)}
|
|
254
230
|
/>
|
|
255
231
|
</div>
|
|
256
232
|
))}
|