@haiiro/docuflow 0.0.6 → 0.0.8

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.
@@ -8,14 +8,14 @@ import { callAppRoute, createRecord, getErrorMessage, listRecords } from 'src/fr
8
8
  import { useAsync, useDebouncedValue } from 'src/front/hooks/use-async';
9
9
  import { DataTable, DocflowRoot, Message, SplitView, TextField, Toolbar } from 'src/front/ui/components';
10
10
  import { FormFieldInputs } from 'src/front/ui/form-field-inputs';
11
- import { FormFieldsBuilder } from 'src/front/ui/form-fields-builder';
12
11
  import { restAnd, restEq, restIlike, restIn } from 'src/shared/api/rest-filter.util';
13
- import { DOCFLOW_SECTION, LAUNCH_PARAMETERS_STEP_NAME } from 'src/shared/docflow.constants';
12
+ import { DOCFLOW_SECTION } from 'src/shared/docflow.constants';
14
13
  import { type FormField, type FormValues } from 'src/shared/form/form-field.type';
15
- import { findMissingRequiredFields, getFormFieldsError } from 'src/shared/form/form-fields.util';
14
+ import { findMissingRequiredFields } from 'src/shared/form/form-fields.util';
16
15
  import { logDocflow, logDocflowError } from 'src/shared/log.util';
17
16
  import {
18
17
  buildLaunchParameters,
18
+ isLaunchableTrigger,
19
19
  isLaunchParametersStep,
20
20
  parseLaunchFields,
21
21
  } from 'src/shared/workflow/launch-step.util';
@@ -27,9 +27,7 @@ const SEARCH_DEBOUNCE_MS = 300;
27
27
  const DRAFT_WAIT_ATTEMPTS = 10;
28
28
  const DRAFT_WAIT_MS = 400;
29
29
 
30
- type ProcessKind = 'plain' | 'parameters';
31
-
32
- type Panel = { kind: 'closed' } | { kind: 'process'; workflowVersionId: string } | { kind: 'new' };
30
+ type Panel = { kind: 'closed' } | { kind: 'process'; workflowVersionId: string };
33
31
 
34
32
  type WorkflowRecord = { id: string; name?: string | null; smbLaunchFields?: unknown };
35
33
  type WorkflowVersionRecord = {
@@ -74,7 +72,7 @@ const loadProcesses = async (searchQuery: string): Promise<DocflowProcess[]> =>
74
72
  return workflows.flatMap((workflow) => {
75
73
  const version = versions.find((candidate) => candidate.workflowId === workflow.id);
76
74
 
77
- if (version === undefined || version.trigger?.type !== 'MANUAL') {
75
+ if (version === undefined || !isLaunchableTrigger(version.trigger)) {
78
76
  return [];
79
77
  }
80
78
 
@@ -178,40 +176,26 @@ const waitForDraft = async (workflowId: string) => {
178
176
  }
179
177
  };
180
178
 
181
- const NewProcessForm = () => {
179
+ const DocflowProcesses = () => {
182
180
  const theme = useTheme();
183
- const [name, setName] = useState('');
184
- const [kind, setKind] = useState<ProcessKind>('parameters');
185
- const [fields, setFields] = useState<FormField[]>([]);
181
+ const [searchInput, setSearchInput] = useState('');
182
+ const searchQuery = useDebouncedValue(searchInput, SEARCH_DEBOUNCE_MS);
183
+ const [panel, setPanel] = useState<Panel>({ kind: 'closed' });
186
184
  const [isCreating, setIsCreating] = useState(false);
187
- const [errorMessage, setErrorMessage] = useState<string | undefined>();
185
+ const { data: processes, loading, error } = useAsync(() => loadProcesses(searchQuery), [searchQuery]);
186
+ const selectedVersionId = panel.kind === 'process' ? panel.workflowVersionId : undefined;
187
+ const selectedProcess = processes?.find((process) => process.workflowVersionId === selectedVersionId);
188
188
 
189
- // Created in the docflow section with a manual trigger; "with parameters"
190
- // also gets the "Launch with parameters" step right after the trigger, its
191
- // fields being variables for every later step. Then the standard editor.
189
+ // As "Создать" of the standard list: a process with a manual trigger in the
190
+ // docflow section, opened in the editor. Launch parameters are set later
191
+ // with the process's "Параметры запуска" command.
192
192
  const handleCreate = async () => {
193
- const launchFields = kind === 'parameters' ? fields : [];
194
- const fieldsError = getFormFieldsError(launchFields);
195
-
196
- if (kind === 'parameters' && launchFields.length === 0) {
197
- setErrorMessage('Добавьте хотя бы одно поле или выберите обычный процесс');
198
-
199
- return;
200
- }
201
-
202
- if (fieldsError !== undefined) {
203
- setErrorMessage(fieldsError);
204
-
205
- return;
206
- }
207
-
208
193
  setIsCreating(true);
209
- setErrorMessage(undefined);
210
- logDocflow('process: create', { kind, fieldCount: launchFields.length });
194
+ logDocflow('process: create');
211
195
 
212
196
  try {
213
197
  const workflow = await createRecord<WorkflowRecord>('workflows', {
214
- name: name.trim() || 'Новый процесс',
198
+ name: 'Новый процесс',
215
199
  smbSection: DOCFLOW_SECTION,
216
200
  });
217
201
 
@@ -220,77 +204,29 @@ const NewProcessForm = () => {
220
204
  }
221
205
 
222
206
  await waitForDraft(workflow.id);
223
- await callAppRoute('/docflow/processes/launch-fields', {
224
- workflowId: workflow.id,
225
- fields: launchFields,
226
- });
207
+ await callAppRoute('/docflow/processes/launch-fields', { workflowId: workflow.id, fields: [] });
227
208
  await navigate(AppPath.RecordShowPage, {
228
209
  objectNameSingular: 'workflow',
229
210
  objectRecordId: workflow.id,
230
211
  });
231
212
  } catch (createError) {
232
213
  logDocflowError('process: create failed', createError);
233
- setErrorMessage(getErrorMessage(createError, 'Не удалось создать процесс'));
214
+ await enqueueSnackbar({
215
+ message: getErrorMessage(createError, 'Не удалось создать процесс'),
216
+ variant: 'error',
217
+ });
234
218
  } finally {
235
219
  setIsCreating(false);
236
220
  }
237
221
  };
238
222
 
239
- const kindButton = (value: ProcessKind, label: string) => (
240
- <Button
241
- variant={kind === value ? 'solid' : 'outline'}
242
- size="sm"
243
- disabled={isCreating}
244
- onClick={() => setKind(value)}
245
- >
246
- {label}
247
- </Button>
248
- );
249
-
250
- return (
251
- <div style={{ display: 'flex', flexDirection: 'column', gap: theme.spacing[3] }}>
252
- <TextField label="Название" placeholder="Новый процесс" value={name} onChange={setName} />
253
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: theme.spacing[2] }}>
254
- {kindButton('parameters', LAUNCH_PARAMETERS_STEP_NAME)}
255
- {kindButton('plain', 'Обычный процесс')}
256
- </div>
257
- {kind === 'parameters' ? (
258
- <>
259
- <Message tone="hint">
260
- Поля, которые человек заполняет перед запуском. В процессе появится шаг «
261
- {LAUNCH_PARAMETERS_STEP_NAME}», и следующие шаги берут значения из его переменных.
262
- </Message>
263
- <FormFieldsBuilder fields={fields} onChange={setFields} disabled={isCreating} />
264
- </>
265
- ) : (
266
- <Message tone="hint">Ручной запуск без параметров. Шаги добавляются в редакторе.</Message>
267
- )}
268
- {errorMessage !== undefined && <Message tone="danger">{errorMessage}</Message>}
269
- <Button variant="solid" size="md" fullWidth loading={isCreating} onClick={() => void handleCreate()}>
270
- Создать и открыть редактор
271
- </Button>
272
- </div>
273
- );
274
- };
275
-
276
- const DocflowProcesses = () => {
277
- const theme = useTheme();
278
- const [searchInput, setSearchInput] = useState('');
279
- const searchQuery = useDebouncedValue(searchInput, SEARCH_DEBOUNCE_MS);
280
- const [panel, setPanel] = useState<Panel>({ kind: 'closed' });
281
- const { data: processes, loading, error } = useAsync(() => loadProcesses(searchQuery), [searchQuery]);
282
- const selectedVersionId = panel.kind === 'process' ? panel.workflowVersionId : undefined;
283
- const selectedProcess = processes?.find((process) => process.workflowVersionId === selectedVersionId);
284
-
285
223
  return (
286
224
  <DocflowRoot>
287
225
  <SplitView
288
- panelTitle={panel.kind === 'new' ? 'Новый процесс' : selectedProcess?.name}
226
+ panelTitle={selectedProcess?.name}
289
227
  onClosePanel={() => setPanel({ kind: 'closed' })}
290
228
  panel={
291
- panel.kind === 'new' ? (
292
- <NewProcessForm />
293
- ) : selectedProcess !== undefined ? (
229
+ selectedProcess !== undefined ? (
294
230
  <ProcessLaunchForm
295
231
  key={selectedProcess.workflowVersionId}
296
232
  process={selectedProcess}
@@ -310,7 +246,7 @@ const DocflowProcesses = () => {
310
246
  />
311
247
  </div>
312
248
  <div style={{ marginLeft: 'auto' }}>
313
- <Button variant="solid" size="sm" onClick={() => setPanel({ kind: 'new' })}>
249
+ <Button variant="solid" size="sm" loading={isCreating} onClick={() => void handleCreate()}>
314
250
  Создать
315
251
  </Button>
316
252
  </div>
@@ -323,7 +259,7 @@ const DocflowProcesses = () => {
323
259
  {loading && processes === undefined && <Message>Загрузка…</Message>}
324
260
  {!loading && error === undefined && processes?.length === 0 && (
325
261
  <Message>
326
- Процессов для запуска нет. Здесь видны опубликованные процессы с ручным запуском и разделом «Документооборот». Параметры запуска задаются командой процесса «Запуск и задания» (кнопка вверху карточки процесса).
262
+ Процессов для запуска нет. Здесь видны опубликованные процессы с ручным запуском и разделом «Документооборот». Параметры запуска задаются кнопкой «Параметры запуска» вверху процесса.
327
263
  </Message>
328
264
  )}
329
265
  {processes !== undefined && processes.length > 0 && (