@haiiro/docuflow 0.0.12 → 0.0.15

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.
Files changed (40) hide show
  1. package/README.md +41 -9
  2. package/bin/install.mjs +69 -3
  3. package/manifest.json +114 -18
  4. package/package.json +6 -3
  5. package/public/app/docflow-app.css +2 -0
  6. package/public/app/docflow-app.js +95 -0
  7. package/src/front-components/docflow-documents.front-component.mjs +41 -41
  8. package/src/front-components/docflow-documents.front-component.tsx +49 -32
  9. package/src/front-components/docflow-processes.front-component.mjs +34 -34
  10. package/src/front-components/docflow-processes.front-component.tsx +24 -11
  11. package/src/front-components/docflow-tasks.front-component.mjs +40 -39
  12. package/src/front-components/docflow-tasks.front-component.tsx +19 -14
  13. package/src/front-components/launch-process.front-component.mjs +75 -0
  14. package/src/front-components/launch-process.front-component.tsx +270 -0
  15. package/src/front-components/process-steps.front-component.mjs +26 -26
  16. package/src/front-components/process-steps.front-component.tsx +56 -10
  17. package/src/front-components/task-form.front-component.mjs +45 -44
  18. package/src/front-components/task-form.front-component.tsx +12 -1
  19. package/src/logic-functions/bitrix-app.logic-function.mjs +186 -88
  20. package/src/logic-functions/bitrix-app.logic-function.ts +24 -61
  21. package/src/logic-functions/bitrix-event.logic-function.mjs +22 -1
  22. package/src/logic-functions/bitrix-event.logic-function.ts +2 -2
  23. package/src/logic-functions/bitrix-install.logic-function.mjs +26 -12
  24. package/src/logic-functions/bitrix-install.logic-function.ts +2 -5
  25. package/src/logic-functions/complete-task.logic-function.mjs +22 -1
  26. package/src/logic-functions/complete-task.logic-function.ts +2 -2
  27. package/src/logic-functions/docflow-app-session.logic-function.mjs +60064 -0
  28. package/src/logic-functions/docflow-app-session.logic-function.ts +54 -0
  29. package/src/logic-functions/docflow-app.logic-function.mjs +60149 -0
  30. package/src/logic-functions/docflow-app.logic-function.ts +38 -0
  31. package/src/logic-functions/launch-process.logic-function.mjs +134 -40
  32. package/src/logic-functions/launch-process.logic-function.ts +85 -24
  33. package/src/logic-functions/publish-process.logic-function.mjs +32 -11
  34. package/src/logic-functions/publish-process.logic-function.ts +8 -4
  35. package/src/logic-functions/save-launch-fields.logic-function.mjs +194 -17
  36. package/src/logic-functions/save-launch-fields.logic-function.ts +26 -8
  37. package/src/logic-functions/save-step-settings.logic-function.mjs +24 -2
  38. package/src/logic-functions/save-step-settings.logic-function.ts +2 -2
  39. package/src/logic-functions/save-task-form.logic-function.mjs +22 -1
  40. package/src/logic-functions/save-task-form.logic-function.ts +2 -2
@@ -24,21 +24,33 @@ import {
24
24
  VariableChip,
25
25
  } from 'src/front/ui/components';
26
26
  import { FormFieldsBuilder } from 'src/front/ui/form-fields-builder';
27
+ import { ListSkeleton } from 'src/front/ui/skeleton';
28
+ import { listLaunchObjects } from 'src/shared/api/object-summaries';
27
29
  import { restAnd, restEq } from 'src/shared/api/rest-filter.util';
28
- import { LAUNCH_TRIGGER_NAME, TRIGGER_STEP_ID } from 'src/shared/docflow.constants';
30
+ import { LAUNCH_RECORD_KEY, LAUNCH_TRIGGER_NAME, TRIGGER_STEP_ID } from 'src/shared/docflow.constants';
29
31
  import { type FormField } from 'src/shared/form/form-field.type';
30
32
  import { getFillableFormFields, getFormFieldsError, parseFormFields } from 'src/shared/form/form-fields.util';
31
33
  import { readStepSettings, type StepSettings } from 'src/shared/form/step-settings.util';
32
- import { parseLaunchFields } from 'src/shared/workflow/launch-step.util';
34
+ import { parseLaunchFields, parseLaunchObject } from 'src/shared/workflow/launch-step.util';
33
35
  import { type WorkflowStep } from 'src/shared/workflow/workflow-run.type';
34
36
  import { getFormStepFields, isFormStep } from 'src/shared/workflow/workflow-run.util';
35
37
  import { logDocflow, logDocflowError } from 'src/shared/log.util';
36
38
  import { PROCESS_STEPS_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from 'src/universal-identifiers';
37
39
 
38
40
  const NO_ASSIGNEE = '';
41
+ const NO_LAUNCH_OBJECT = '';
42
+ // Objects of the workflows themselves: a process is not launched on them
43
+ const WORKFLOW_OBJECTS = ['workflow', 'workflowVersion', 'workflowRun', 'workflowAutomatedTrigger'];
39
44
 
40
45
  type DraftVersion = { id: string; steps?: WorkflowStep[] | null };
41
- type ProcessRecord = { id: string; smbLaunchFields?: unknown };
46
+ type ProcessRecord = { id: string; smbLaunchFields?: unknown; smbLaunchObject?: string | null };
47
+ type LaunchObjectOption = { value: string; label: string };
48
+
49
+ const loadLaunchObjectOptions = async (): Promise<LaunchObjectOption[]> =>
50
+ (await listLaunchObjects())
51
+ .filter(({ nameSingular }) => !WORKFLOW_OBJECTS.includes(nameSingular))
52
+ .map(({ nameSingular, labelSingular }) => ({ value: nameSingular, label: labelSingular }))
53
+ .sort((left, right) => left.label.localeCompare(right.label, 'ru'));
42
54
 
43
55
  const sectionStyle = { display: 'flex', flexDirection: 'column' as const };
44
56
 
@@ -64,14 +76,18 @@ const reopenWorkflowEditor = async (workflowId: string) => {
64
76
  const LaunchParametersEditor = ({
65
77
  workflowId,
66
78
  initialFields,
79
+ initialLaunchObject,
67
80
  onSaved,
68
81
  }: {
69
82
  workflowId: string;
70
83
  initialFields: FormField[];
84
+ initialLaunchObject: string | undefined;
71
85
  onSaved: () => void;
72
86
  }) => {
73
87
  const theme = useTheme();
74
88
  const [fields, setFields] = useState(initialFields);
89
+ const [launchObject, setLaunchObject] = useState(initialLaunchObject ?? NO_LAUNCH_OBJECT);
90
+ const { data: objectOptions, error: objectsError } = useAsync(loadLaunchObjectOptions, []);
75
91
  const [isSaving, setIsSaving] = useState(false);
76
92
  const [errorMessage, setErrorMessage] = useState<string | undefined>();
77
93
 
@@ -86,15 +102,19 @@ const LaunchParametersEditor = ({
86
102
 
87
103
  setIsSaving(true);
88
104
  setErrorMessage(undefined);
89
- logDocflow('process: save launch fields', { workflowId, fields });
105
+ logDocflow('process: save launch fields', { workflowId, fields, launchObject });
90
106
 
91
107
  try {
92
- const result = await callAppRoute('/docflow/processes/launch-fields', { workflowId, fields });
108
+ const result = await callAppRoute('/docflow/processes/launch-fields', {
109
+ workflowId,
110
+ fields,
111
+ launchObject: launchObject === NO_LAUNCH_OBJECT ? null : launchObject,
112
+ });
93
113
 
94
114
  logDocflow('process: launch fields saved', result);
95
115
  await enqueueSnackbar({
96
116
  message:
97
- fields.length > 0
117
+ fields.length > 0 || launchObject !== NO_LAUNCH_OBJECT
98
118
  ? `Параметры сохранены: процесс начинается с «${LAUNCH_TRIGGER_NAME}», опубликуйте его`
99
119
  : 'Параметры убраны',
100
120
  variant: 'success',
@@ -113,10 +133,35 @@ const LaunchParametersEditor = ({
113
133
  <section style={{ ...sectionStyle, gap: theme.spacing[2] }} aria-label="Параметры запуска">
114
134
  <SectionTitle>Параметры запуска</SectionTitle>
115
135
  <Message tone="hint">
116
- Что человек заполняет перед запуском. Первым блоком процесса становится «{LAUNCH_TRIGGER_NAME}»:
117
- в следующих шагах значения выбираются как его переменные, например сотрудник — в поле
118
- «Исполнитель». Без параметров процесс начинается с обычного «Запуск вручную».
136
+ Что человек заполняет перед запуском и на какой записи запускает процесс. Первым блоком процесса
137
+ становится «{LAUNCH_TRIGGER_NAME}»: в следующих шагах значения и запись выбираются как его
138
+ переменные, например сотрудник — в поле «Исполнитель». Запускают процесс командой «Запустить
139
+ процесс» в меню (Cmd+K) или на выбранных записях. Без параметров и записи процесс начинается с
140
+ обычного «Запуск вручную».
119
141
  </Message>
142
+ <SelectField
143
+ label="Где запускать"
144
+ value={launchObject}
145
+ disabled={isSaving}
146
+ options={[
147
+ { value: NO_LAUNCH_OBJECT, label: 'Откуда угодно, без записи' },
148
+ // The saved object stays offered while the list loads
149
+ ...(objectOptions ??
150
+ (launchObject !== NO_LAUNCH_OBJECT ? [{ value: launchObject, label: launchObject }] : [])),
151
+ ].map((option) =>
152
+ option.value === NO_LAUNCH_OBJECT ? option : { ...option, label: `На записи: ${option.label}` },
153
+ )}
154
+ onChange={setLaunchObject}
155
+ />
156
+ {objectsError !== undefined && (
157
+ <Message tone="danger">{getErrorMessage(objectsError, 'Не удалось прочитать объекты')}</Message>
158
+ )}
159
+ {launchObject !== NO_LAUNCH_OBJECT && (
160
+ <div style={{ alignItems: 'center', display: 'flex', flexWrap: 'wrap', gap: theme.spacing[2] }}>
161
+ <Message tone="hint">Запись, на которой запустили процесс:</Message>
162
+ <VariableChip>{`{{${TRIGGER_STEP_ID}.${LAUNCH_RECORD_KEY}}}`}</VariableChip>
163
+ </div>
164
+ )}
120
165
  <FormFieldsBuilder
121
166
  fields={fields}
122
167
  onChange={setFields}
@@ -276,7 +321,7 @@ const ProcessSteps = () => {
276
321
  return (
277
322
  <DocflowRoot>
278
323
  <div style={{ display: 'flex', flexDirection: 'column', gap: theme.spacing[6], padding: theme.spacing[3] }}>
279
- {loading && data === undefined && <Message>Загрузка…</Message>}
324
+ {loading && data === undefined && <ListSkeleton rows={4} />}
280
325
  {error !== undefined && (
281
326
  <Message tone="danger">{getErrorMessage(error, 'Не удалось прочитать процесс')}</Message>
282
327
  )}
@@ -285,6 +330,7 @@ const ProcessSteps = () => {
285
330
  key={`${workflowId}:${launchEditorKey}`}
286
331
  workflowId={workflowId}
287
332
  initialFields={parseLaunchFields(data.process.smbLaunchFields)}
333
+ initialLaunchObject={parseLaunchObject(data.process.smbLaunchObject)}
288
334
  onSaved={() => {
289
335
  void reload().then(() => setLaunchEditorKey((current) => current + 1));
290
336
  }}