@nocobase/client-v2 2.1.0-beta.38 → 2.1.0-beta.41

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 (137) hide show
  1. package/es/Application.d.ts +6 -0
  2. package/es/collection-field-interface/CollectionFieldInterface.d.ts +51 -15
  3. package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +82 -3
  4. package/es/collection-manager/field-configure.d.ts +80 -0
  5. package/es/collection-manager/field-validation.d.ts +43 -0
  6. package/es/collection-manager/filter-operators/index.d.ts +46 -0
  7. package/es/collection-manager/filter-operators/operators.d.ts +30 -0
  8. package/es/collection-manager/interfaces/checkbox.d.ts +1 -41
  9. package/es/collection-manager/interfaces/checkboxGroup.d.ts +12 -44
  10. package/es/collection-manager/interfaces/collection.d.ts +12 -51
  11. package/es/collection-manager/interfaces/color.d.ts +1 -16
  12. package/es/collection-manager/interfaces/createdAt.d.ts +1 -44
  13. package/es/collection-manager/interfaces/createdBy.d.ts +0 -4
  14. package/es/collection-manager/interfaces/dateOnly.d.ts +7 -44
  15. package/es/collection-manager/interfaces/datetime.d.ts +1 -44
  16. package/es/collection-manager/interfaces/datetimeNoTz.d.ts +1 -44
  17. package/es/collection-manager/interfaces/email.d.ts +1 -29
  18. package/es/collection-manager/interfaces/id.d.ts +1 -16
  19. package/es/collection-manager/interfaces/index.d.ts +2 -3
  20. package/es/collection-manager/interfaces/input.d.ts +1 -102
  21. package/es/collection-manager/interfaces/integer.d.ts +1 -95
  22. package/es/collection-manager/interfaces/json.d.ts +16 -7
  23. package/es/collection-manager/interfaces/m2m.d.ts +11 -19
  24. package/es/collection-manager/interfaces/m2o.d.ts +11 -19
  25. package/es/collection-manager/interfaces/markdown.d.ts +1 -63
  26. package/es/collection-manager/interfaces/multipleSelect.d.ts +12 -44
  27. package/es/collection-manager/interfaces/nanoid.d.ts +1 -34
  28. package/es/collection-manager/interfaces/number.d.ts +1 -87
  29. package/es/collection-manager/interfaces/o2m.d.ts +12 -24
  30. package/es/collection-manager/interfaces/obo.d.ts +207 -0
  31. package/es/collection-manager/interfaces/oho.d.ts +207 -0
  32. package/es/collection-manager/interfaces/password.d.ts +1 -56
  33. package/es/collection-manager/interfaces/percent.d.ts +1 -84
  34. package/es/collection-manager/interfaces/phone.d.ts +1 -25
  35. package/es/collection-manager/interfaces/properties/index.d.ts +0 -28
  36. package/es/collection-manager/interfaces/radioGroup.d.ts +1 -29
  37. package/es/collection-manager/interfaces/richText.d.ts +1 -63
  38. package/es/collection-manager/interfaces/select.d.ts +12 -44
  39. package/es/collection-manager/interfaces/snowflake-id.d.ts +1 -34
  40. package/es/collection-manager/interfaces/tableoid.d.ts +1 -10
  41. package/es/collection-manager/interfaces/textarea.d.ts +1 -51
  42. package/es/collection-manager/interfaces/time.d.ts +1 -16
  43. package/es/collection-manager/interfaces/types.d.ts +3 -12
  44. package/es/collection-manager/interfaces/unixTimestamp.d.ts +1 -44
  45. package/es/collection-manager/interfaces/updatedAt.d.ts +1 -44
  46. package/es/collection-manager/interfaces/updatedBy.d.ts +0 -4
  47. package/es/collection-manager/interfaces/url.d.ts +1 -20
  48. package/es/collection-manager/interfaces/uuid.d.ts +1 -34
  49. package/es/collection-manager/template-fields.d.ts +53 -0
  50. package/es/components/form/VariableInput.d.ts +53 -2
  51. package/es/components/form/filter/CollectionFilter.d.ts +9 -1
  52. package/es/components/form/filter/CollectionFilterItem.d.ts +10 -2
  53. package/es/flow/components/filter/useFilterOptions.d.ts +13 -1
  54. package/es/flow/models/blocks/assign-form/assignFieldValuesFlow.d.ts +84 -0
  55. package/es/flow/models/blocks/assign-form/index.d.ts +1 -0
  56. package/es/flow/models/blocks/form/FormActionModel.d.ts +9 -2
  57. package/es/index.d.ts +4 -0
  58. package/es/index.mjs +105 -142
  59. package/lib/index.js +106 -143
  60. package/package.json +7 -7
  61. package/src/Application.tsx +24 -0
  62. package/src/collection-field-interface/CollectionFieldInterface.ts +71 -77
  63. package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +201 -4
  64. package/src/collection-manager/field-configure.ts +548 -0
  65. package/src/collection-manager/field-validation.ts +195 -0
  66. package/src/collection-manager/filter-operators/index.ts +176 -0
  67. package/src/collection-manager/{interfaces/properties → filter-operators}/operators.ts +24 -13
  68. package/src/collection-manager/interfaces/checkbox.ts +2 -9
  69. package/src/collection-manager/interfaces/checkboxGroup.ts +2 -10
  70. package/src/collection-manager/interfaces/collection.ts +2 -15
  71. package/src/collection-manager/interfaces/color.ts +2 -2
  72. package/src/collection-manager/interfaces/createdAt.ts +2 -2
  73. package/src/collection-manager/interfaces/createdBy.ts +1 -12
  74. package/src/collection-manager/interfaces/dateOnly.ts +8 -2
  75. package/src/collection-manager/interfaces/datetime.ts +2 -2
  76. package/src/collection-manager/interfaces/datetimeNoTz.ts +2 -2
  77. package/src/collection-manager/interfaces/email.ts +2 -9
  78. package/src/collection-manager/interfaces/id.ts +1 -2
  79. package/src/collection-manager/interfaces/index.ts +2 -3
  80. package/src/collection-manager/interfaces/input.ts +2 -133
  81. package/src/collection-manager/interfaces/integer.ts +2 -71
  82. package/src/collection-manager/interfaces/json.tsx +17 -11
  83. package/src/collection-manager/interfaces/m2m.tsx +0 -21
  84. package/src/collection-manager/interfaces/m2o.tsx +0 -22
  85. package/src/collection-manager/interfaces/markdown.ts +2 -51
  86. package/src/collection-manager/interfaces/multipleSelect.ts +2 -14
  87. package/src/collection-manager/interfaces/nanoid.ts +2 -2
  88. package/src/collection-manager/interfaces/number.ts +2 -85
  89. package/src/collection-manager/interfaces/o2m.tsx +1 -22
  90. package/src/collection-manager/interfaces/obo.tsx +145 -0
  91. package/src/collection-manager/interfaces/oho.tsx +145 -0
  92. package/src/collection-manager/interfaces/password.ts +2 -44
  93. package/src/collection-manager/interfaces/percent.ts +2 -74
  94. package/src/collection-manager/interfaces/phone.ts +2 -2
  95. package/src/collection-manager/interfaces/properties/index.ts +0 -133
  96. package/src/collection-manager/interfaces/radioGroup.ts +2 -2
  97. package/src/collection-manager/interfaces/richText.ts +2 -51
  98. package/src/collection-manager/interfaces/select.ts +2 -14
  99. package/src/collection-manager/interfaces/snowflake-id.ts +2 -2
  100. package/src/collection-manager/interfaces/tableoid.ts +1 -2
  101. package/src/collection-manager/interfaces/textarea.ts +2 -51
  102. package/src/collection-manager/interfaces/time.ts +2 -2
  103. package/src/collection-manager/interfaces/types.ts +4 -12
  104. package/src/collection-manager/interfaces/unixTimestamp.tsx +2 -2
  105. package/src/collection-manager/interfaces/updatedAt.ts +2 -2
  106. package/src/collection-manager/interfaces/updatedBy.ts +1 -12
  107. package/src/collection-manager/interfaces/url.ts +2 -4
  108. package/src/collection-manager/interfaces/uuid.ts +2 -2
  109. package/src/collection-manager/template-fields.ts +109 -0
  110. package/src/components/README.md +1 -0
  111. package/src/components/README.zh-CN.md +1 -0
  112. package/src/components/form/VariableInput.tsx +101 -28
  113. package/src/components/form/__tests__/VariableInput.test.ts +85 -0
  114. package/src/components/form/filter/CollectionFilter.tsx +11 -1
  115. package/src/components/form/filter/CollectionFilterItem.tsx +12 -4
  116. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +42 -0
  117. package/src/components/form/filter/useFilterActionProps.ts +7 -4
  118. package/src/flow/components/filter/useFilterOptions.ts +27 -5
  119. package/src/flow/models/actions/UpdateRecordActionModel.tsx +14 -95
  120. package/src/flow/models/actions/UpdateRecordActionUtils.ts +4 -7
  121. package/src/flow/models/actions/__tests__/AssignFormRefill.test.ts +26 -1
  122. package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +63 -2
  123. package/src/flow/models/blocks/assign-form/assignFieldValuesFlow.tsx +206 -0
  124. package/src/flow/models/blocks/assign-form/index.ts +1 -0
  125. package/src/flow/models/blocks/form/FormActionModel.tsx +30 -3
  126. package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +71 -0
  127. package/src/flow/models/blocks/form/submitHandler.ts +8 -1
  128. package/src/flow/models/fields/CollectionSelectorFieldModel.tsx +8 -2
  129. package/src/flow/models/fields/DisplayEnumFieldModel.tsx +8 -2
  130. package/src/index.ts +4 -0
  131. package/es/collection-manager/interfaces/linkTo.d.ts +0 -90
  132. package/es/collection-manager/interfaces/o2o.d.ts +0 -621
  133. package/es/collection-manager/interfaces/properties/operators.d.ts +0 -294
  134. package/es/collection-manager/interfaces/subTable.d.ts +0 -172
  135. package/src/collection-manager/interfaces/linkTo.ts +0 -120
  136. package/src/collection-manager/interfaces/o2o.tsx +0 -561
  137. package/src/collection-manager/interfaces/subTable.ts +0 -218
@@ -0,0 +1,548 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import type { ComponentType, ReactNode } from 'react';
11
+ import { getPickerFormat } from '@nocobase/utils/client';
12
+ import { get, has } from 'lodash';
13
+
14
+ export type FieldConfigureComponentType =
15
+ | 'Input'
16
+ | 'Input.TextArea'
17
+ | 'InputNumber'
18
+ | 'Checkbox'
19
+ | 'Checkbox.Group'
20
+ | 'ColorPicker'
21
+ | 'DatePicker'
22
+ | 'Radio.Group'
23
+ | 'Select'
24
+ | 'CollectionSelect'
25
+ | 'RemoteSelect'
26
+ | 'TargetKey'
27
+ | 'SourceKey'
28
+ | 'ExpiresRadio'
29
+ | 'ArrayTable'
30
+ | 'FieldValidation'
31
+ | 'ForeignKey'
32
+ | 'Input.JSON'
33
+ | 'Markdown'
34
+ | 'Percent'
35
+ | 'RichText'
36
+ | 'SourceCollection'
37
+ | 'Space'
38
+ | 'ThroughCollection'
39
+ | 'TimePicker'
40
+ | 'UnixTimestamp'
41
+ | (string & {});
42
+
43
+ export const CollectionSelect = 'CollectionSelect';
44
+
45
+ export interface FieldConfigureRuntimeContext {
46
+ createOnly?: boolean;
47
+ editMainOnly?: boolean;
48
+ createMainOnly?: boolean;
49
+ disabledJSONB?: boolean;
50
+ primaryKeyOnly?: boolean;
51
+ showReverseFieldConfig?: boolean;
52
+ [key: string]: unknown;
53
+ }
54
+
55
+ export interface FieldConfigureRuntimeState {
56
+ componentProps?: Record<string, unknown>;
57
+ dataSource?: unknown;
58
+ disabled?: boolean;
59
+ hidden?: boolean;
60
+ hasValue?: boolean;
61
+ value?: unknown;
62
+ }
63
+
64
+ export interface FieldConfigureEffectContext {
65
+ changedName?: string;
66
+ context: FieldConfigureRuntimeContext;
67
+ getValue: (name: string) => unknown;
68
+ setValue: (name: string, value: unknown) => void;
69
+ values: Record<string, unknown>;
70
+ }
71
+
72
+ export interface FieldConfigureItem {
73
+ name: string;
74
+ title?: ReactNode;
75
+ component?: FieldConfigureComponentType;
76
+ Component?: ComponentType<any>;
77
+ componentProps?: Record<string, unknown>;
78
+ defaultValue?: unknown;
79
+ description?: ReactNode;
80
+ hidden?: boolean | string | ((context: FieldConfigureEffectContext) => boolean);
81
+ disabled?: boolean | string | ((context: FieldConfigureEffectContext) => boolean);
82
+ options?: Array<{ label: ReactNode; value: string | number | boolean }>;
83
+ required?: boolean;
84
+ dependencies?: string[];
85
+ effect?: (context: FieldConfigureEffectContext) => void;
86
+ schema?: Record<string, unknown>;
87
+ layout?: {
88
+ row?: string;
89
+ column?: string;
90
+ columnIndex?: number;
91
+ span?: number;
92
+ };
93
+ }
94
+
95
+ const commonConfigurePropertyNames = new Set(['name', 'uiSchema.title']);
96
+ const propertyLayoutComponents = new Set(['Grid', 'Grid.Row', 'Grid.Col', 'div']);
97
+
98
+ function getExpressionContext(context: FieldConfigureEffectContext) {
99
+ return {
100
+ ...context.context,
101
+ ...context.values,
102
+ };
103
+ }
104
+
105
+ export function evaluateFieldConfigureExpression(value: unknown, context: FieldConfigureEffectContext) {
106
+ if (typeof value === 'boolean') {
107
+ return value;
108
+ }
109
+ if (typeof value !== 'string') {
110
+ return false;
111
+ }
112
+
113
+ const expression = value.replace(/^\s*\{\{\s*/, '').replace(/\s*\}\}\s*$/, '');
114
+ const expressionContext = getExpressionContext(context);
115
+ const evaluateToken = (token: string) => {
116
+ const trimmed = token.trim().replace(/^\$/, '');
117
+ if (!trimmed) {
118
+ return false;
119
+ }
120
+ if (trimmed.startsWith('!')) {
121
+ return !evaluateToken(trimmed.slice(1).trim());
122
+ }
123
+ if (trimmed === 'true') {
124
+ return true;
125
+ }
126
+ if (trimmed === 'false') {
127
+ return false;
128
+ }
129
+ const callExpression = trimmed.match(/^([A-Za-z_$][\w$]*)\((.*)\)$/);
130
+ if (callExpression) {
131
+ const [, functionName, rawArgs] = callExpression;
132
+ const fn = get(expressionContext, functionName);
133
+ if (typeof fn !== 'function') {
134
+ return false;
135
+ }
136
+ const args = rawArgs
137
+ .split(',')
138
+ .map((arg) => arg.trim())
139
+ .filter(Boolean)
140
+ .map((arg) => arg.replace(/^['"]|['"]$/g, ''));
141
+ return !!fn(...args);
142
+ }
143
+ return !!get(expressionContext, trimmed);
144
+ };
145
+
146
+ return expression.split('||').some((orPart) => orPart.split('&&').every((andPart) => evaluateToken(andPart)));
147
+ }
148
+
149
+ function normalizeConfigureStateExpression(value: unknown) {
150
+ if (typeof value === 'string') {
151
+ return (context: FieldConfigureEffectContext) => evaluateFieldConfigureExpression(value, context);
152
+ }
153
+ return value as FieldConfigureItem['hidden'];
154
+ }
155
+
156
+ function normalizeConfigureHiddenExpression(schema: Record<string, any>) {
157
+ if (schema?.['x-hidden'] !== undefined) {
158
+ return normalizeConfigureStateExpression(schema['x-hidden']);
159
+ }
160
+ if (schema?.['x-visible'] !== undefined) {
161
+ return (context: FieldConfigureEffectContext) => !evaluateFieldConfigureExpression(schema['x-visible'], context);
162
+ }
163
+ return undefined;
164
+ }
165
+
166
+ function collectConfigureLeafProperties(
167
+ properties: Record<string, any>,
168
+ prefix = '',
169
+ layout?: FieldConfigureItem['layout'],
170
+ ): Array<{ name: string; schema: any; layout?: FieldConfigureItem['layout'] }> {
171
+ return Object.entries(properties || {}).flatMap(([key, schema]) => {
172
+ const name = prefix ? `${prefix}.${key}` : key;
173
+ const childProperties = schema?.properties;
174
+ const component = schema?.['x-component'];
175
+
176
+ if (childProperties && component === 'Grid.Row') {
177
+ const columns = Object.entries(childProperties).filter(
178
+ ([, childSchema]) => (childSchema as Record<string, any>)?.['x-component'] === 'Grid.Col',
179
+ );
180
+ const span = columns.length > 0 ? Math.floor(24 / columns.length) : 24;
181
+
182
+ return columns.flatMap(([columnKey, columnSchema], columnIndex) =>
183
+ collectConfigureLeafProperties((columnSchema as Record<string, any>)?.properties || {}, prefix, {
184
+ row: name,
185
+ column: columnKey,
186
+ columnIndex,
187
+ span,
188
+ }),
189
+ );
190
+ }
191
+
192
+ if (childProperties && (!component || propertyLayoutComponents.has(component))) {
193
+ return collectConfigureLeafProperties(childProperties, prefix, layout);
194
+ }
195
+
196
+ return [{ name, schema, layout }];
197
+ });
198
+ }
199
+
200
+ function isConvertibleConfigureProperty(name: string, schema: Record<string, any>) {
201
+ if (commonConfigurePropertyNames.has(name)) {
202
+ return false;
203
+ }
204
+ return !!schema?.['x-component'] || schema?.default !== undefined || schema?.['x-hidden'] !== undefined;
205
+ }
206
+
207
+ export function configurePropertiesToItems(
208
+ properties: Record<string, any> = {},
209
+ options: { components?: Record<string, ComponentType<any>> } = {},
210
+ ): FieldConfigureItem[] {
211
+ return collectConfigureLeafProperties(properties)
212
+ .filter(({ name, schema }) => isConvertibleConfigureProperty(name, schema))
213
+ .map(({ name, schema, layout }) => {
214
+ const component = schema?.['x-component'] as FieldConfigureComponentType | undefined;
215
+ return {
216
+ name,
217
+ title: schema?.title || schema?.['x-content'],
218
+ component,
219
+ Component: component ? options.components?.[component] : undefined,
220
+ componentProps: schema?.['x-component-props'],
221
+ defaultValue: schema?.default,
222
+ description: schema?.description,
223
+ hidden: normalizeConfigureHiddenExpression(schema),
224
+ disabled: normalizeConfigureStateExpression(schema?.['x-disabled']) as FieldConfigureItem['disabled'],
225
+ options: Array.isArray(schema?.enum) ? schema.enum : undefined,
226
+ required: schema?.required,
227
+ schema,
228
+ layout,
229
+ };
230
+ });
231
+ }
232
+
233
+ const DATE_FORMAT_OPTIONS = [
234
+ { label: 'MMMM Do YYYY', value: 'MMMM Do YYYY' },
235
+ { label: 'YYYY-MM-DD', value: 'YYYY-MM-DD' },
236
+ { label: 'MM/DD/YY', value: 'MM/DD/YY' },
237
+ { label: 'YYYY/MM/DD', value: 'YYYY/MM/DD' },
238
+ { label: 'DD/MM/YYYY', value: 'DD/MM/YYYY' },
239
+ { label: '{{t("Custom")}}', value: 'custom' },
240
+ ];
241
+
242
+ const TIME_FORMAT_OPTIONS = [
243
+ { label: '{{t("12 hour")}}', value: 'hh:mm:ss a' },
244
+ { label: '{{t("24 hour")}}', value: 'HH:mm:ss' },
245
+ ];
246
+
247
+ function getPicker(values: Record<string, unknown>) {
248
+ return get(values, 'uiSchema.x-component-props.picker') || 'date';
249
+ }
250
+
251
+ function getShowTime(values: Record<string, unknown>) {
252
+ return get(values, 'uiSchema.x-component-props.showTime');
253
+ }
254
+
255
+ export function getCoreFieldConfigureState(
256
+ name: string,
257
+ values: Record<string, unknown>,
258
+ context: FieldConfigureRuntimeContext = {},
259
+ ): FieldConfigureRuntimeState {
260
+ if (name === 'unique' || name === 'primaryKey') {
261
+ return {
262
+ disabled: !context.createMainOnly || !!context.primaryKeyOnly,
263
+ };
264
+ }
265
+
266
+ if (name === 'autoIncrement') {
267
+ return {
268
+ disabled: !context.createMainOnly,
269
+ };
270
+ }
271
+
272
+ if (name.startsWith('reverseField.')) {
273
+ return {
274
+ disabled: !context.showReverseFieldConfig,
275
+ hidden: !context.showReverseFieldConfig,
276
+ };
277
+ }
278
+
279
+ if (name === 'autoCreateReverseField' && get(values, 'reverseField.key')) {
280
+ return {
281
+ disabled: true,
282
+ };
283
+ }
284
+
285
+ if (name === 'uiSchema.x-component-props.dateFormat') {
286
+ return {
287
+ componentProps: {
288
+ picker: getPicker(values),
289
+ },
290
+ };
291
+ }
292
+
293
+ if (name === 'uiSchema.x-component-props.showTime') {
294
+ return {
295
+ hidden: getPicker(values) !== 'date',
296
+ };
297
+ }
298
+
299
+ if (name === 'uiSchema.x-component-props.timeFormat') {
300
+ return {
301
+ hidden: getPicker(values) !== 'date' || getShowTime(values) === false,
302
+ };
303
+ }
304
+
305
+ if (name === 'defaultValue') {
306
+ const shouldHide =
307
+ !!get(values, 'primaryKey') ||
308
+ !!get(values, 'unique') ||
309
+ !!get(values, 'autoIncrement') ||
310
+ !!get(values, 'defaultToCurrentTime');
311
+
312
+ return {
313
+ hidden: shouldHide,
314
+ ...(shouldHide ? { value: null, hasValue: true } : null),
315
+ componentProps: {
316
+ gmt: get(values, 'uiSchema.x-component-props.gmt'),
317
+ showTime: get(values, 'uiSchema.x-component-props.showTime'),
318
+ dateFormat: get(values, 'uiSchema.x-component-props.dateFormat'),
319
+ timeFormat: get(values, 'uiSchema.x-component-props.timeFormat'),
320
+ picker: get(values, 'uiSchema.x-component-props.picker'),
321
+ format: get(values, 'uiSchema.x-component-props.format'),
322
+ },
323
+ dataSource: get(values, 'uiSchema.enum'),
324
+ };
325
+ }
326
+
327
+ if ((name === 'precision' || name === 'scale') && get(values, 'type') !== 'decimal') {
328
+ return {
329
+ hidden: true,
330
+ };
331
+ }
332
+
333
+ return {};
334
+ }
335
+
336
+ export function runCoreFieldConfigureEffects(options: FieldConfigureEffectContext) {
337
+ const { context, getValue, setValue, values } = options;
338
+ const primaryKey = !!getValue('primaryKey');
339
+ const unique = !!getValue('unique');
340
+
341
+ if (context.createMainOnly && primaryKey && (!options.changedName || options.changedName === 'primaryKey')) {
342
+ if (getValue('unique') !== false) {
343
+ setValue('unique', false);
344
+ }
345
+ if (has(values, 'autoIncrement') && getValue('autoIncrement') !== true) {
346
+ setValue('autoIncrement', true);
347
+ }
348
+ }
349
+
350
+ if (context.createMainOnly && unique && primaryKey && options.changedName === 'unique') {
351
+ setValue('primaryKey', false);
352
+ }
353
+
354
+ if (get(values, 'reverseField.key') && getValue('autoCreateReverseField') !== true) {
355
+ setValue('autoCreateReverseField', true);
356
+ }
357
+
358
+ if (
359
+ options.changedName === 'uiSchema.x-component-props.picker' ||
360
+ ['primaryKey', 'unique', 'autoIncrement', 'defaultToCurrentTime'].includes(options.changedName || '')
361
+ ) {
362
+ if (
363
+ getValue('defaultValue') != null &&
364
+ (!!getValue('primaryKey') ||
365
+ !!getValue('unique') ||
366
+ !!getValue('autoIncrement') ||
367
+ !!getValue('defaultToCurrentTime') ||
368
+ options.changedName === 'uiSchema.x-component-props.picker')
369
+ ) {
370
+ setValue('defaultValue', null);
371
+ }
372
+ }
373
+
374
+ const hasDateTimeConfigure =
375
+ has(values, 'uiSchema.x-component-props.picker') ||
376
+ has(values, 'uiSchema.x-component-props.dateFormat') ||
377
+ has(values, 'uiSchema.x-component-props.showTime') ||
378
+ has(values, 'uiSchema.x-component-props.timeFormat');
379
+
380
+ if (!hasDateTimeConfigure) {
381
+ return;
382
+ }
383
+
384
+ const picker = getPicker(values);
385
+ if (
386
+ options.changedName === 'uiSchema.x-component-props.picker' &&
387
+ has(values, 'uiSchema.x-component-props.dateFormat') &&
388
+ get(values, 'uiSchema.x-component-props.dateFormat') !== getPickerFormat(picker as string)
389
+ ) {
390
+ setValue('uiSchema.x-component-props.dateFormat', getPickerFormat(picker as string));
391
+ }
392
+
393
+ if (has(values, 'uiSchema.x-component-props.showTime') && picker !== 'date' && getShowTime(values) !== false) {
394
+ setValue('uiSchema.x-component-props.showTime', false);
395
+ }
396
+
397
+ if (
398
+ has(values, 'uiSchema.x-component-props.timeFormat') &&
399
+ getShowTime(values) &&
400
+ !get(values, 'uiSchema.x-component-props.timeFormat')
401
+ ) {
402
+ setValue('uiSchema.x-component-props.timeFormat', 'HH:mm:ss');
403
+ }
404
+ }
405
+
406
+ export function indexConfigureItems(options: { autoIncrement?: boolean } = {}): FieldConfigureItem[] {
407
+ const items: FieldConfigureItem[] = [
408
+ {
409
+ name: 'primaryKey',
410
+ title: '{{t("Primary")}}',
411
+ component: 'Checkbox',
412
+ },
413
+ {
414
+ name: 'unique',
415
+ title: '{{t("Unique")}}',
416
+ component: 'Checkbox',
417
+ },
418
+ ];
419
+
420
+ if (options.autoIncrement) {
421
+ items.push({
422
+ name: 'autoIncrement',
423
+ title: '{{t("Auto increment")}}',
424
+ component: 'Checkbox',
425
+ });
426
+ }
427
+
428
+ return items;
429
+ }
430
+
431
+ export function dateTimeFormatConfigureItems(
432
+ options: {
433
+ includePicker?: boolean;
434
+ hidden?: FieldConfigureItem['hidden'];
435
+ showTimeDefault?: boolean;
436
+ } = {},
437
+ ): FieldConfigureItem[] {
438
+ const items: FieldConfigureItem[] = [];
439
+
440
+ if (options.includePicker !== false) {
441
+ items.push({
442
+ name: 'uiSchema.x-component-props.picker',
443
+ title: '{{t("Picker")}}',
444
+ component: 'Radio.Group',
445
+ defaultValue: 'date',
446
+ options: [
447
+ { label: '{{t("Date")}}', value: 'date' },
448
+ { label: '{{t("Month")}}', value: 'month' },
449
+ { label: '{{t("Quarter")}}', value: 'quarter' },
450
+ { label: '{{t("Year")}}', value: 'year' },
451
+ ],
452
+ hidden: options.hidden,
453
+ });
454
+ }
455
+
456
+ items.push(
457
+ {
458
+ name: 'uiSchema.x-component-props.dateFormat',
459
+ title: '{{t("Date format")}}',
460
+ component: 'ExpiresRadio',
461
+ defaultValue: 'YYYY-MM-DD',
462
+ options: DATE_FORMAT_OPTIONS,
463
+ componentProps: {
464
+ defaultValue: 'dddd',
465
+ formats: ['MMMM Do YYYY', 'YYYY-MM-DD', 'MM/DD/YY', 'YYYY/MM/DD', 'DD/MM/YYYY'],
466
+ },
467
+ hidden: options.hidden,
468
+ },
469
+ {
470
+ name: 'uiSchema.x-component-props.showTime',
471
+ title: '{{t("Show time")}}',
472
+ component: 'Checkbox',
473
+ defaultValue: options.showTimeDefault,
474
+ hidden: options.hidden,
475
+ },
476
+ {
477
+ name: 'uiSchema.x-component-props.timeFormat',
478
+ title: '{{t("Time format")}}',
479
+ component: 'Radio.Group',
480
+ defaultValue: 'HH:mm:ss',
481
+ options: TIME_FORMAT_OPTIONS,
482
+ hidden: (context) => {
483
+ if (typeof options.hidden === 'function' && options.hidden(context)) {
484
+ return true;
485
+ }
486
+ if (typeof options.hidden === 'boolean') {
487
+ return options.hidden;
488
+ }
489
+ return getShowTime(context.values) === false;
490
+ },
491
+ },
492
+ );
493
+
494
+ return items;
495
+ }
496
+
497
+ export function reverseFieldConfigureItems(): FieldConfigureItem[] {
498
+ return [
499
+ {
500
+ name: 'autoCreateReverseField',
501
+ title: '{{t("Create inverse field in the target collection")}}',
502
+ component: 'Checkbox',
503
+ defaultValue: false,
504
+ },
505
+ {
506
+ name: 'reverseField.type',
507
+ title: '{{t("Inverse relationship type")}}',
508
+ component: 'Select',
509
+ required: true,
510
+ options: [
511
+ { label: "{{t('HasOne')}}", value: 'hasOne' },
512
+ { label: "{{t('HasMany')}}", value: 'hasMany' },
513
+ { label: "{{t('BelongsTo')}}", value: 'belongsTo' },
514
+ { label: "{{t('BelongsToMany')}}", value: 'belongsToMany' },
515
+ ],
516
+ hidden: ({ context, values }) => !context.showReverseFieldConfig && !get(values, 'autoCreateReverseField'),
517
+ disabled: ({ context }) => !context.showReverseFieldConfig,
518
+ },
519
+ {
520
+ name: 'reverseField.uiSchema.title',
521
+ title: '{{t("Inverse field display name")}}',
522
+ component: 'Input',
523
+ required: true,
524
+ hidden: ({ context, values }) => !context.showReverseFieldConfig && !get(values, 'autoCreateReverseField'),
525
+ disabled: ({ context }) => !context.showReverseFieldConfig,
526
+ },
527
+ {
528
+ name: 'reverseField.name',
529
+ title: '{{t("Inverse field name")}}',
530
+ component: 'Input',
531
+ required: true,
532
+ description:
533
+ "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
534
+ hidden: ({ context, values }) => !context.showReverseFieldConfig && !get(values, 'autoCreateReverseField'),
535
+ disabled: ({ context }) => !context.showReverseFieldConfig,
536
+ },
537
+ ];
538
+ }
539
+
540
+ export const reverseFieldConfigureItem = reverseFieldConfigureItems;
541
+
542
+ export function OptionsEditor(options: { name?: string; title?: ReactNode } = {}): FieldConfigureItem {
543
+ return {
544
+ name: options.name || 'uiSchema.enum',
545
+ title: options.title || '{{t("Options")}}',
546
+ component: 'ArrayTable',
547
+ };
548
+ }