@nocobase/client 0.7.0-alpha.80 → 0.7.0-alpha.83

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 (95) hide show
  1. package/es/acl/ACLProvider.js +10 -15
  2. package/es/antd-config-provider/index.js +7 -4
  3. package/es/api-client/APIClient.d.ts +2 -30
  4. package/es/api-client/APIClient.js +30 -158
  5. package/es/api-client/hooks/useResource.d.ts +1 -1
  6. package/es/block-provider/hooks/index.d.ts +3 -0
  7. package/es/block-provider/hooks/index.js +233 -168
  8. package/es/collection-manager/Configuration/AddFieldAction.js +27 -9
  9. package/es/collection-manager/Configuration/EditFieldAction.js +25 -8
  10. package/es/collection-manager/hooks/useCollection.d.ts +1 -1
  11. package/es/i18n/i18n.js +3 -3
  12. package/es/locale/en_US.d.ts +10 -0
  13. package/es/locale/en_US.js +11 -1
  14. package/es/locale/index.d.ts +44 -0
  15. package/es/locale/zh_CN.d.ts +34 -0
  16. package/es/locale/zh_CN.js +35 -1
  17. package/es/schema-component/antd/action/Action.Designer.js +33 -13
  18. package/es/schema-component/antd/action/utils.d.ts +2 -0
  19. package/es/schema-component/antd/action/utils.js +60 -0
  20. package/es/schema-component/antd/date-picker/util.d.ts +2 -1
  21. package/es/schema-component/antd/date-picker/util.js +4 -2
  22. package/es/schema-initializer/buttons/FormActionInitializers.d.ts +84 -0
  23. package/es/schema-initializer/buttons/FormActionInitializers.js +63 -0
  24. package/es/schema-initializer/buttons/ReadPrettyFormActionInitializers.d.ts +26 -0
  25. package/es/schema-initializer/buttons/ReadPrettyFormActionInitializers.js +21 -0
  26. package/es/schema-initializer/buttons/TableActionColumnInitializers.js +21 -0
  27. package/es/schema-settings/SchemaSettings.js +48 -16
  28. package/es/user/CurrentUser.js +1 -1
  29. package/es/user/LanguageSettings.js +4 -3
  30. package/es/user/SigninPage.js +3 -14
  31. package/es/user/SwitchRole.js +2 -26
  32. package/es/workflow/triggers/collection.js +1 -0
  33. package/es/workflow/triggers/index.js +2 -0
  34. package/es/workflow/triggers/schedule.d.ts +25 -0
  35. package/es/workflow/triggers/schedule.js +531 -0
  36. package/lib/acl/ACLProvider.js +9 -15
  37. package/lib/antd-config-provider/index.js +6 -3
  38. package/lib/api-client/APIClient.d.ts +2 -30
  39. package/lib/api-client/APIClient.js +26 -160
  40. package/lib/api-client/hooks/useResource.d.ts +1 -1
  41. package/lib/block-provider/hooks/index.d.ts +3 -0
  42. package/lib/block-provider/hooks/index.js +238 -169
  43. package/lib/collection-manager/Configuration/AddFieldAction.js +27 -9
  44. package/lib/collection-manager/Configuration/EditFieldAction.js +25 -8
  45. package/lib/collection-manager/hooks/useCollection.d.ts +1 -1
  46. package/lib/i18n/i18n.js +3 -3
  47. package/lib/locale/en_US.d.ts +10 -0
  48. package/lib/locale/en_US.js +11 -1
  49. package/lib/locale/index.d.ts +44 -0
  50. package/lib/locale/zh_CN.d.ts +34 -0
  51. package/lib/locale/zh_CN.js +35 -1
  52. package/lib/schema-component/antd/action/Action.Designer.js +34 -13
  53. package/lib/schema-component/antd/action/utils.d.ts +2 -0
  54. package/lib/schema-component/antd/action/utils.js +67 -0
  55. package/lib/schema-component/antd/date-picker/util.d.ts +2 -1
  56. package/lib/schema-component/antd/date-picker/util.js +6 -1
  57. package/lib/schema-initializer/buttons/FormActionInitializers.d.ts +84 -0
  58. package/lib/schema-initializer/buttons/FormActionInitializers.js +63 -0
  59. package/lib/schema-initializer/buttons/ReadPrettyFormActionInitializers.d.ts +26 -0
  60. package/lib/schema-initializer/buttons/ReadPrettyFormActionInitializers.js +21 -0
  61. package/lib/schema-initializer/buttons/TableActionColumnInitializers.js +21 -0
  62. package/lib/schema-settings/SchemaSettings.js +49 -16
  63. package/lib/user/CurrentUser.js +1 -1
  64. package/lib/user/LanguageSettings.js +4 -3
  65. package/lib/user/SigninPage.js +3 -14
  66. package/lib/user/SwitchRole.js +2 -27
  67. package/lib/workflow/triggers/collection.js +1 -0
  68. package/lib/workflow/triggers/index.js +3 -0
  69. package/lib/workflow/triggers/schedule.d.ts +25 -0
  70. package/lib/workflow/triggers/schedule.js +554 -0
  71. package/package.json +4 -3
  72. package/src/acl/ACLProvider.tsx +4 -5
  73. package/src/antd-config-provider/index.tsx +4 -2
  74. package/src/api-client/APIClient.ts +2 -120
  75. package/src/block-provider/hooks/index.ts +106 -69
  76. package/src/collection-manager/Configuration/AddFieldAction.tsx +18 -0
  77. package/src/collection-manager/Configuration/EditFieldAction.tsx +19 -0
  78. package/src/i18n/i18n.ts +3 -3
  79. package/src/locale/en_US.ts +11 -1
  80. package/src/locale/zh_CN.ts +39 -1
  81. package/src/schema-component/antd/action/Action.Designer.tsx +33 -1
  82. package/src/schema-component/antd/action/utils.ts +68 -0
  83. package/src/schema-component/antd/date-picker/util.ts +4 -3
  84. package/src/schema-initializer/SchemaInitializer.tsx +2 -2
  85. package/src/schema-initializer/buttons/FormActionInitializers.tsx +66 -0
  86. package/src/schema-initializer/buttons/ReadPrettyFormActionInitializers.tsx +22 -0
  87. package/src/schema-initializer/buttons/TableActionColumnInitializers.tsx +22 -0
  88. package/src/schema-settings/SchemaSettings.tsx +40 -29
  89. package/src/user/CurrentUser.tsx +1 -1
  90. package/src/user/LanguageSettings.tsx +1 -0
  91. package/src/user/SigninPage.tsx +2 -7
  92. package/src/user/SwitchRole.tsx +2 -6
  93. package/src/workflow/triggers/collection.tsx +1 -1
  94. package/src/workflow/triggers/index.tsx +2 -0
  95. package/src/workflow/triggers/schedule.tsx +422 -0
@@ -0,0 +1,422 @@
1
+ import React, { useState } from 'react';
2
+ import { InputNumber, Select } from 'antd';
3
+ import { observer, useForm, useFormEffects } from '@formily/react';
4
+
5
+ import { useCollectionDataSource, useCollectionManager } from '../../collection-manager';
6
+ import { SchemaComponent, useCompile, DatePicker } from '../../schema-component';
7
+
8
+ import { useFlowContext } from '../WorkflowCanvas';
9
+ import { BaseTypeSet } from '../calculators';
10
+ import { collection } from '../schemas/collection';
11
+ import { useTranslation } from 'react-i18next';
12
+ import { onFieldValueChange } from '@formily/core';
13
+ import { css } from '@emotion/css';
14
+
15
+ const DateFieldsSelect: React.FC<any> = observer((props) => {
16
+ const compile = useCompile();
17
+ const { getCollectionFields } = useCollectionManager();
18
+ const { values } = useForm();
19
+ const fields = getCollectionFields(values?.config?.collection);
20
+
21
+ return (
22
+ <Select {...props}>
23
+ {fields
24
+ .filter(field => (
25
+ !field.hidden
26
+ && (field.uiSchema ? field.type === 'date' : false)
27
+ ))
28
+ .map(field => (
29
+ <Select.Option key={field.name} value={field.name}>{compile(field.uiSchema?.title)}</Select.Option>
30
+ ))}
31
+ </Select>
32
+ );
33
+ });
34
+
35
+ const OnField = ({ value, onChange }) => {
36
+ const { t } = useTranslation();
37
+ const [dir, setDir] = useState(value.offset ? value.offset / Math.abs(value.offset) : 0);
38
+
39
+ return (
40
+ <fieldset className={css`
41
+ display: flex;
42
+ gap: .5em;
43
+ `}>
44
+ <DateFieldsSelect value={value.field} onChange={field => onChange({ ...value, field })} />
45
+ {value.field
46
+ ? (
47
+ <Select value={dir} onChange={(v) => {
48
+ setDir(v);
49
+ onChange({ ...value, offset: Math.abs(value.offset) * v });
50
+ }}>
51
+ <Select.Option value={0}>{t('Exactly at')}</Select.Option>
52
+ <Select.Option value={-1}>{t('Before')}</Select.Option>
53
+ <Select.Option value={1}>{t('After')}</Select.Option>
54
+ </Select>
55
+ )
56
+ : null}
57
+ {dir
58
+ ? (
59
+ <>
60
+ <InputNumber value={Math.abs(value.offset)} onChange={(v) => onChange({ ...value, offset: v * dir })}/>
61
+ <Select value={value.unit || 86400000} onChange={unit => onChange({ ...value, unit })}>
62
+ <Select.Option value={86400000}>{t('Days')}</Select.Option>
63
+ <Select.Option value={3600000}>{t('Hours')}</Select.Option>
64
+ <Select.Option value={60000}>{t('Minutes')}</Select.Option>
65
+ <Select.Option value={1000}>{t('Seconds')}</Select.Option>
66
+ </Select>
67
+ </>
68
+ )
69
+ : null}
70
+ </fieldset>
71
+ );
72
+ }
73
+
74
+ function EndsByField({ value, onChange }) {
75
+ const { t } = useTranslation();
76
+ const [type, setType] = useState(typeof value === 'object' && !(value instanceof Date) ? 'field' : 'date');
77
+ return (
78
+ <fieldset className={css`
79
+ display: flex;
80
+ gap: .5em;
81
+ `}>
82
+ <Select value={type} onChange={t => {
83
+ onChange(t === 'field' ? {} : null);
84
+ setType(t);
85
+ }}>
86
+ <Select.Option value={'field'}>{t('By field')}</Select.Option>
87
+ <Select.Option value={'date'}>{t('By custom date')}</Select.Option>
88
+ </Select>
89
+ {type === 'field'
90
+ ? (
91
+ <OnField value={value} onChange={onChange} />
92
+ )
93
+ : (
94
+ <DatePicker showTime value={value} onChange={onChange} />
95
+ )
96
+ }
97
+ </fieldset>
98
+ );
99
+ }
100
+
101
+ function parseCronRule(cron: string) {
102
+ if (!cron) {
103
+ return {
104
+ mode: 0
105
+ }
106
+ }
107
+ const rules = cron.split(/\s+/).slice(1).map(v => v.split('/'));
108
+ let index = rules.findIndex(rule => rule[0] === '*');
109
+ if (index === -1) {
110
+ return {
111
+ mode: 0
112
+ }
113
+ }
114
+ // fix days of week
115
+ if (index === 3 && rules[4][0] === '*') {
116
+ index = 4;
117
+ }
118
+ return {
119
+ mode: index + 1,
120
+ step: rules[index][1] ?? 1
121
+ };
122
+ }
123
+
124
+ const CronUnits = [
125
+ { value: 1, option: 'By minute', unitText: 'Minutes' },
126
+ { value: 2, option: 'By hour', unitText: 'Hours' },
127
+ { value: 3, option: 'By date', unitText: 'Days', conflict: true, startFrom: 1 },
128
+ { value: 4, option: 'By month', unitText: 'Months', startFrom: 1 },
129
+ { value: 5, option: 'By day of week', unitText: 'Days', conflict: true },
130
+ ];
131
+
132
+ function getChangedCron({ mode, step }) {
133
+ const m = mode - 1;
134
+ const left = [0, ...Array(m).fill(null).map((_, i) => {
135
+ if (CronUnits[m].conflict && CronUnits[i].conflict) {
136
+ return '?';
137
+ }
138
+ return i === 3 ? '*' : CronUnits[i].startFrom ?? 0;
139
+ })].join(' ');
140
+ const right = Array(5 - mode).fill(null).map((_, i) => {
141
+ if (CronUnits[m].conflict && CronUnits[mode + i].conflict || mode === 4) {
142
+ return '?';
143
+ }
144
+ return '*';
145
+ }).join(' ');
146
+ return `${left} ${!step || step == 1 ? '*' : `*/${step}`}${right ? ` ${right}` : ''}`;
147
+ }
148
+
149
+ const CronField = ({ value = '', onChange }) => {
150
+ const { t } = useTranslation();
151
+ const cron = parseCronRule(value);
152
+ const unit = CronUnits[cron.mode - 1];
153
+ return (
154
+ <fieldset className={css`
155
+ display: flex;
156
+ gap: .5em;
157
+ `}>
158
+ <Select
159
+ value={cron.mode}
160
+ onChange={v => onChange(v ? getChangedCron({ step: cron.step, mode: v }) : '')}
161
+ >
162
+ <Select.Option value={0}>{t('No repeat')}</Select.Option>
163
+ {CronUnits.map(item => (
164
+ <Select.Option key={item.value} value={item.value}>{t(item.option)}</Select.Option>
165
+ ))}
166
+ </Select>
167
+ {cron.mode
168
+ ? (
169
+ <InputNumber
170
+ value={cron.step}
171
+ onChange={v => onChange(getChangedCron({ step: v, mode: cron.mode }))}
172
+ min={1}
173
+ addonBefore={t('Every')}
174
+ addonAfter={t(unit.unitText)}
175
+ />
176
+ )
177
+ : null}
178
+ </fieldset>
179
+ );
180
+ }
181
+
182
+ const ModeFieldsets = {
183
+ 0: {
184
+ startsOn: {
185
+ type: 'datetime',
186
+ name: 'startsOn',
187
+ title: '{{t("Starts on")}}',
188
+ 'x-decorator': 'FormItem',
189
+ 'x-component': 'DatePicker',
190
+ 'x-component-props': {
191
+ showTime: true
192
+ },
193
+ required: true
194
+ },
195
+ cron: {
196
+ type: 'string',
197
+ name: 'cron',
198
+ title: '{{t("Repeat mode")}}',
199
+ 'x-decorator': 'FormItem',
200
+ 'x-component': 'CronField',
201
+ 'x-reactions': [
202
+ {
203
+ target: 'config.endsOn',
204
+ fulfill: {
205
+ state: {
206
+ visible: '{{!!$self.value}}',
207
+ },
208
+ }
209
+ },
210
+ {
211
+ target: 'config.limit',
212
+ fulfill: {
213
+ state: {
214
+ visible: '{{!!$self.value}}',
215
+ },
216
+ }
217
+ }
218
+ ]
219
+ },
220
+ endsOn: {
221
+ type: 'datetime',
222
+ name: 'endsOn',
223
+ title: '{{t("Ends on")}}',
224
+ 'x-decorator': 'FormItem',
225
+ 'x-component': 'DatePicker',
226
+ 'x-component-props': {
227
+ showTime: true
228
+ }
229
+ },
230
+ limit: {
231
+ type: 'number',
232
+ name: 'limit',
233
+ title: '{{t("Repeat limit")}}',
234
+ 'x-decorator': 'FormItem',
235
+ 'x-component': 'InputNumber',
236
+ 'x-component-props': {
237
+ placeholder: '{{t("No limit")}}',
238
+ min: 0
239
+ }
240
+ }
241
+ },
242
+ 1: {
243
+ collection: {
244
+ ...collection,
245
+ 'x-reactions': [
246
+ ...collection['x-reactions'],
247
+ {
248
+ // only full path works
249
+ target: 'config.startsOn',
250
+ fulfill: {
251
+ state: {
252
+ visible: '{{!!$self.value}}',
253
+ },
254
+ }
255
+ }
256
+ ]
257
+ },
258
+ startsOn: {
259
+ type: 'object',
260
+ title: '{{t("Starts on")}}',
261
+ 'x-decorator': 'FormItem',
262
+ 'x-component': 'OnField',
263
+ required: true
264
+ },
265
+ cron: {
266
+ type: 'string',
267
+ name: 'cron',
268
+ title: '{{t("Repeat mode")}}',
269
+ 'x-decorator': 'FormItem',
270
+ 'x-component': 'CronField',
271
+ 'x-reactions': [
272
+ {
273
+ target: 'config.endsOn',
274
+ fulfill: {
275
+ state: {
276
+ visible: '{{!!$self.value}}',
277
+ },
278
+ }
279
+ },
280
+ {
281
+ target: 'config.limit',
282
+ fulfill: {
283
+ state: {
284
+ visible: '{{!!$self.value}}',
285
+ },
286
+ }
287
+ }
288
+ ]
289
+ },
290
+ endsOn: {
291
+ type: 'object',
292
+ title: '{{t("Ends on")}}',
293
+ 'x-decorator': 'FormItem',
294
+ 'x-component': 'EndsByField'
295
+ },
296
+ limit: {
297
+ type: 'number',
298
+ name: 'limit',
299
+ title: '{{t("Repeat limit")}}',
300
+ 'x-decorator': 'FormItem',
301
+ 'x-component': 'InputNumber',
302
+ 'x-component-props': {
303
+ placeholder: '{{t("No limit")}}',
304
+ min: 0
305
+ }
306
+ }
307
+ }
308
+ };
309
+
310
+ const ScheduleConfig = () => {
311
+ const { values = {}, clearFormGraph } = useForm();
312
+ const { config = {} } = values;
313
+ const [mode, setMode] = useState(config.mode);
314
+ useFormEffects(() => {
315
+ onFieldValueChange('config.mode', (field) => {
316
+ setMode(field.value);
317
+ clearFormGraph('config.collection');
318
+ clearFormGraph('config.startsOn');
319
+ clearFormGraph('config.cron');
320
+ clearFormGraph('config.endsOn');
321
+ })
322
+ });
323
+
324
+ return (
325
+ <>
326
+ <SchemaComponent
327
+ schema={{
328
+ type: 'number',
329
+ title: '{{t("Trigger mode")}}',
330
+ name: 'mode',
331
+ 'x-decorator': 'FormItem',
332
+ 'x-component': 'Radio.Group',
333
+ 'x-component-props': {
334
+ options: [
335
+ { value: 0, label: '{{t("Based on certain date")}}' },
336
+ { value: 1, label: '{{t("Based on date field of collection")}}' },
337
+ ]
338
+ },
339
+ required: true
340
+ }}
341
+ />
342
+ <SchemaComponent
343
+ schema={{
344
+ type: 'void',
345
+ properties: {
346
+ [`mode-${mode}`]: {
347
+ type: 'void',
348
+ 'x-component': 'fieldset',
349
+ 'x-component-props': {
350
+ className: css`
351
+ .ant-select{
352
+ width: auto;
353
+ min-width: 4em;
354
+ }
355
+
356
+ .ant-input-number{
357
+ width: 4em;
358
+ }
359
+
360
+ .ant-picker{
361
+ width: auto;
362
+ }
363
+ `
364
+ },
365
+ properties: ModeFieldsets[mode]
366
+ }
367
+ }
368
+ }}
369
+ components={{
370
+ DateFieldsSelect,
371
+ OnField,
372
+ CronField,
373
+ EndsByField
374
+ }}
375
+ />
376
+ </>
377
+ );
378
+ };
379
+
380
+ export default {
381
+ title: '{{t("Schedule event")}}',
382
+ type: 'schedule',
383
+ fieldset: {
384
+ config: {
385
+ type: 'object',
386
+ name: 'config',
387
+ 'x-component': 'ScheduleConfig',
388
+ 'x-component-props': {
389
+ }
390
+ }
391
+ },
392
+ scope: {
393
+ useCollectionDataSource
394
+ },
395
+ components: {
396
+ // FieldsSelect
397
+ ScheduleConfig
398
+ },
399
+ getter({ type, options, onChange }) {
400
+ const { t } = useTranslation();
401
+ const compile = useCompile();
402
+ const { collections = [] } = useCollectionManager();
403
+ const { workflow } = useFlowContext();
404
+ const collection = collections.find(item => item.name === workflow.config.collection) ?? { fields: [] };
405
+
406
+ return (
407
+ <Select
408
+ placeholder={t('Fields')}
409
+ value={options?.path?.replace(/^data\./, '')}
410
+ onChange={(path) => {
411
+ onChange({ type, options: { ...options, path: `data.${path}` } });
412
+ }}
413
+ >
414
+ {collection.fields
415
+ .filter(field => BaseTypeSet.has(field?.uiSchema?.type))
416
+ .map(field => (
417
+ <Select.Option key={field.name} value={field.name}>{compile(field.uiSchema.title)}</Select.Option>
418
+ ))}
419
+ </Select>
420
+ );
421
+ }
422
+ };