@onehat/ui 0.4.81 → 0.4.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.
- package/package.json +7 -6
- package/src/Components/Container/Container.js +4 -4
- package/src/Components/Form/Field/Combo/Combo.js +88 -16
- package/src/Components/Form/Field/Combo/MeterTypesCombo.js +1 -0
- package/src/Components/Form/Field/Date.js +1 -1
- package/src/Components/Form/Field/Json.js +2 -1
- package/src/Components/Form/Field/Select/PageSizeSelect.js +6 -1
- package/src/Components/Form/Field/Select/Select.js +14 -38
- package/src/Components/Form/Field/Tag/Tag.js +234 -14
- package/src/Components/Form/Field/Tag/ValueBox.js +20 -1
- package/src/Components/Form/Form.js +26 -13
- package/src/Components/Grid/Grid.js +316 -106
- package/src/Components/Grid/GridHeaderRow.js +42 -22
- package/src/Components/Grid/GridRow.js +16 -6
- package/src/Components/Grid/RowHandle.js +16 -4
- package/src/Components/Hoc/Secondary/withSecondaryEditor.js +137 -43
- package/src/Components/Hoc/Secondary/withSecondarySideEditor.js +1 -1
- package/src/Components/Hoc/withData.js +7 -0
- package/src/Components/Hoc/withEditor.js +19 -4
- package/src/Components/Hoc/withPresetButtons.js +1 -1
- package/src/Components/Hoc/withSideEditor.js +1 -1
- package/src/Components/Icons/Join.js +10 -0
- package/src/Components/Layout/AsyncOperation.js +61 -14
- package/src/Components/Layout/CenterBox.js +1 -1
- package/src/Components/Screens/Manager.js +1 -1
- package/src/Components/Toolbar/Pagination.js +108 -106
- package/src/Components/Toolbar/PaginationToolbar.js +3 -1
- package/src/Components/Toolbar/Toolbar.js +10 -6
- package/src/Components/Tree/TreeNode.js +39 -9
- package/src/Components/Viewer/Viewer.js +7 -2
- package/src/Constants/Progress.js +2 -1
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
import { useRef, } from 'react';
|
|
1
|
+
import { useRef, useState, useEffect, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
HStack,
|
|
4
4
|
VStackNative,
|
|
5
5
|
} from '@project-components/Gluestack';
|
|
6
6
|
import clsx from 'clsx';
|
|
7
|
+
import * as yup from 'yup'; // https://github.com/jquense/yup#string
|
|
8
|
+
import oneHatData from '@onehat/data';
|
|
7
9
|
import {
|
|
8
10
|
EDITOR_TYPE__WINDOWED,
|
|
9
11
|
} from '../../../../Constants/Editor.js';
|
|
12
|
+
import {
|
|
13
|
+
EDITOR_TYPE__PLAIN,
|
|
14
|
+
} from '../../../../Constants/Editor.js';
|
|
15
|
+
import Button from '../../../Buttons/Button.js';
|
|
16
|
+
import testProps from '../../../../Functions/testProps.js';
|
|
17
|
+
import Form from '../../Form.js';
|
|
18
|
+
import Viewer from '../../../Viewer/Viewer.js';
|
|
10
19
|
import withAlert from '../../../Hoc/withAlert.js';
|
|
11
20
|
import withComponent from '../../../Hoc/withComponent.js';
|
|
12
21
|
import withData from '../../../Hoc/withData.js';
|
|
13
22
|
import withModal from '../../../Hoc/withModal.js';
|
|
14
23
|
import withValue from '../../../Hoc/withValue.js';
|
|
15
24
|
import ValueBox from './ValueBox.js';
|
|
25
|
+
import Inflector from 'inflector-js';
|
|
16
26
|
import Combo, { ComboEditor } from '../Combo/Combo.js';
|
|
17
27
|
import UiGlobals from '../../../../UiGlobals.js';
|
|
18
28
|
import _ from 'lodash';
|
|
@@ -27,8 +37,14 @@ function TagComponent(props) {
|
|
|
27
37
|
minimizeForRow = false,
|
|
28
38
|
Editor,
|
|
29
39
|
_combo = {},
|
|
40
|
+
SourceRepository,
|
|
41
|
+
mustSaveBeforeEditingJoinData = false,
|
|
42
|
+
joinDataConfig,
|
|
43
|
+
getBaseParams, // See note in useEffect
|
|
44
|
+
outerValueId, // See note in useEffect
|
|
30
45
|
tooltip,
|
|
31
46
|
testID,
|
|
47
|
+
isDirty = false,
|
|
32
48
|
|
|
33
49
|
// parent Form
|
|
34
50
|
onChangeValue,
|
|
@@ -39,6 +55,10 @@ function TagComponent(props) {
|
|
|
39
55
|
// withComponent
|
|
40
56
|
self,
|
|
41
57
|
|
|
58
|
+
// withData
|
|
59
|
+
Repository: TargetRepository,
|
|
60
|
+
setBaseParams,
|
|
61
|
+
|
|
42
62
|
// withFilters
|
|
43
63
|
isInFilter,
|
|
44
64
|
|
|
@@ -53,11 +73,22 @@ function TagComponent(props) {
|
|
|
53
73
|
...propsToPass // break connection between Tag and Combo props
|
|
54
74
|
} = props,
|
|
55
75
|
styles = UiGlobals.styles,
|
|
76
|
+
propertyDef = SourceRepository?.getSchema().getPropertyDefinition(self.reference),
|
|
77
|
+
hasJoinData = propertyDef?.joinData?.length,
|
|
78
|
+
[JoinRepository] = useState(() => {
|
|
79
|
+
if (hasJoinData) {
|
|
80
|
+
return oneHatData.getRepository(propertyDef.joinModel, true);
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}),
|
|
84
|
+
[isInited, setIsInited] = useState(_.isUndefined(getBaseParams)), // default to true unless getBaseParams is defined
|
|
85
|
+
modelFieldStartsWith = hasJoinData ? Inflector.underscore(JoinRepository.getSchema().name) + '__' : '',
|
|
56
86
|
valueRef = useRef(value),
|
|
57
87
|
onView = async (item, e) => {
|
|
88
|
+
// show the joined record's viewer
|
|
58
89
|
const
|
|
59
90
|
id = item.id,
|
|
60
|
-
repository =
|
|
91
|
+
repository = TargetRepository;
|
|
61
92
|
if (repository.isLoading) {
|
|
62
93
|
await repository.waitUntilDoneLoading();
|
|
63
94
|
}
|
|
@@ -115,9 +146,8 @@ function TagComponent(props) {
|
|
|
115
146
|
}
|
|
116
147
|
|
|
117
148
|
// The value we get from combo is a simple int
|
|
118
|
-
// Convert this to id
|
|
149
|
+
// Convert this to { id, text} from either Repository or data array.
|
|
119
150
|
const
|
|
120
|
-
Repository = props.Repository,
|
|
121
151
|
data = props.data,
|
|
122
152
|
idIx = props.idIx,
|
|
123
153
|
displayIx = props.displayIx,
|
|
@@ -127,9 +157,9 @@ function TagComponent(props) {
|
|
|
127
157
|
|
|
128
158
|
if (!id) {
|
|
129
159
|
displayValue = '';
|
|
130
|
-
} else if (
|
|
131
|
-
if (!
|
|
132
|
-
item =
|
|
160
|
+
} else if (TargetRepository) {
|
|
161
|
+
if (!TargetRepository.isDestroyed) {
|
|
162
|
+
item = TargetRepository.getById(id);
|
|
133
163
|
if (!item) {
|
|
134
164
|
throw Error('item not found');
|
|
135
165
|
}
|
|
@@ -143,13 +173,46 @@ function TagComponent(props) {
|
|
|
143
173
|
displayValue = item[displayIx];
|
|
144
174
|
}
|
|
145
175
|
|
|
176
|
+
let joinData = {};
|
|
177
|
+
if (hasJoinData) {
|
|
178
|
+
// build up the default starting values for joinData,
|
|
179
|
+
// first with schema defaultValues...
|
|
180
|
+
const
|
|
181
|
+
allSchemaDefaults = JoinRepository.getSchema().getDefaultValues(),
|
|
182
|
+
modelSchemaDefaults = _.pickBy(allSchemaDefaults, (value, key) => {
|
|
183
|
+
return key.startsWith(modelFieldStartsWith);
|
|
184
|
+
}),
|
|
185
|
+
fullFieldNames = propertyDef.joinData.map((fieldName) => { // add the 'model_name__' prefix so we can get schema default values
|
|
186
|
+
return modelFieldStartsWith + fieldName;
|
|
187
|
+
}),
|
|
188
|
+
schemaDefaultValues = _.pick(modelSchemaDefaults, fullFieldNames);
|
|
189
|
+
joinData = _.mapKeys(schemaDefaultValues, (value, key) => { // strip out the 'model_name__' prefix from field names
|
|
190
|
+
return key.startsWith(modelFieldStartsWith) ? key.slice(modelFieldStartsWith.length) : key;
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// then override with default values in joinDataConfig, if they exist
|
|
194
|
+
if (joinDataConfig) {
|
|
195
|
+
_.each(Object.keys(joinDataConfig), (fieldName) => {
|
|
196
|
+
const fieldConfig = joinDataConfig[fieldName];
|
|
197
|
+
if (!_.isUndefined(fieldConfig.defaultValue)) { // null in jsonDataConfig will override a default value in schema!
|
|
198
|
+
joinData[fieldName] = fieldConfig.defaultValue;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
146
204
|
|
|
147
205
|
// add new value
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
206
|
+
const
|
|
207
|
+
newValue = [...value], // clone Tag's full current value (array), so we trigger a re-render after adding the new value
|
|
208
|
+
newItem = {
|
|
209
|
+
id,
|
|
210
|
+
text: displayValue,
|
|
211
|
+
};
|
|
212
|
+
if (hasJoinData) {
|
|
213
|
+
newItem.joinData = joinData;
|
|
214
|
+
}
|
|
215
|
+
newValue.push(newItem);
|
|
153
216
|
setValue(newValue);
|
|
154
217
|
clearComboValue();
|
|
155
218
|
},
|
|
@@ -160,6 +223,122 @@ function TagComponent(props) {
|
|
|
160
223
|
});
|
|
161
224
|
setValue(newValue);
|
|
162
225
|
},
|
|
226
|
+
onViewEditJoinData = async (item, e) => {
|
|
227
|
+
// show the joinData viewer/editor
|
|
228
|
+
|
|
229
|
+
/* item format:
|
|
230
|
+
item = {
|
|
231
|
+
id: 3,
|
|
232
|
+
text: "1000HR PM",
|
|
233
|
+
joinData: {
|
|
234
|
+
hide_every_n: 0,
|
|
235
|
+
also_resets: '[]',
|
|
236
|
+
},
|
|
237
|
+
}
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
// Prepare Form to edit the joinData
|
|
241
|
+
const
|
|
242
|
+
// create the Form.record, format: { meters_pm_schedules__also_resets: null, meters_pm_schedules__hide_every_n: 5 }
|
|
243
|
+
record = _.mapKeys(item.joinData, (value, key) => { // add the 'model_name__' prefix so we can match JoinRepository property names
|
|
244
|
+
return modelFieldStartsWith + key;
|
|
245
|
+
}),
|
|
246
|
+
// create the Form.items
|
|
247
|
+
items = propertyDef.joinData.map((fieldName) => {
|
|
248
|
+
let obj = {
|
|
249
|
+
name: modelFieldStartsWith + fieldName,
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// add in any specific config for joinData[fieldName]], if it exists
|
|
253
|
+
// (The outer *Editor can configure each Tag field's joinData Form item.
|
|
254
|
+
// This moves that configuration down and adds outerValueId)
|
|
255
|
+
if (joinDataConfig?.[fieldName]) {
|
|
256
|
+
const joinDataConfigFieldname = _.clone(joinDataConfig[fieldName]); // don't mutate original
|
|
257
|
+
joinDataConfigFieldname.outerValueId = item.id; // so that joinData can be aware of the value of the inspected ValueBox; see note in useEffect, below
|
|
258
|
+
obj = {
|
|
259
|
+
...obj,
|
|
260
|
+
...joinDataConfigFieldname,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return obj;
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
let height = 300;
|
|
268
|
+
let body;
|
|
269
|
+
const extraModalProps = {};
|
|
270
|
+
if (isViewOnly) {
|
|
271
|
+
// show Viewer
|
|
272
|
+
body = <Viewer
|
|
273
|
+
record={record}
|
|
274
|
+
Repository={JoinRepository}
|
|
275
|
+
items={items}
|
|
276
|
+
columnDefaults={{
|
|
277
|
+
labelWidth: 200,
|
|
278
|
+
}}
|
|
279
|
+
/>;
|
|
280
|
+
|
|
281
|
+
extraModalProps.customButtons = [
|
|
282
|
+
<Button
|
|
283
|
+
{...testProps('closeBtn')}
|
|
284
|
+
key="closeBtn"
|
|
285
|
+
onPress={hideModal}
|
|
286
|
+
text="Close"
|
|
287
|
+
className="text-white"
|
|
288
|
+
/>,
|
|
289
|
+
];
|
|
290
|
+
} else {
|
|
291
|
+
body = <Form
|
|
292
|
+
editorType={EDITOR_TYPE__PLAIN}
|
|
293
|
+
isEditorViewOnly={false}
|
|
294
|
+
record={record}
|
|
295
|
+
Repository={JoinRepository}
|
|
296
|
+
items={items}
|
|
297
|
+
additionalFooterButtons={[
|
|
298
|
+
{
|
|
299
|
+
text: 'Cancel',
|
|
300
|
+
onPress: hideModal,
|
|
301
|
+
skipSubmit: true,
|
|
302
|
+
variant: 'outline',
|
|
303
|
+
}
|
|
304
|
+
]}
|
|
305
|
+
onSave={(values)=> {
|
|
306
|
+
|
|
307
|
+
// strip the 'model_name__' prefix from the field names
|
|
308
|
+
values = _.mapKeys(values, (value, key) => {
|
|
309
|
+
return key.startsWith(modelFieldStartsWith) ? key.slice(modelFieldStartsWith.length) : key;
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Put these values back on joinData
|
|
313
|
+
item.joinData = values;
|
|
314
|
+
const newValue = [...valueRef.current]; // clone
|
|
315
|
+
const ix = _.findIndex(newValue, (val) => {
|
|
316
|
+
return val.id === item.id;
|
|
317
|
+
});
|
|
318
|
+
newValue[ix] = item;
|
|
319
|
+
setValue(newValue);
|
|
320
|
+
|
|
321
|
+
hideModal();
|
|
322
|
+
}}
|
|
323
|
+
/>;
|
|
324
|
+
}
|
|
325
|
+
switch (items.length) {
|
|
326
|
+
case 1: height = 250; break;
|
|
327
|
+
case 2: height = 400; break;
|
|
328
|
+
default: height = 600; break;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
showModal({
|
|
332
|
+
title: 'Extra data for "' + item.text + '"',
|
|
333
|
+
w: 400,
|
|
334
|
+
h: height,
|
|
335
|
+
canClose: true,
|
|
336
|
+
includeReset: false,
|
|
337
|
+
includeCancel: false,
|
|
338
|
+
body,
|
|
339
|
+
...extraModalProps,
|
|
340
|
+
});
|
|
341
|
+
},
|
|
163
342
|
onGridAdd = (selection) => {
|
|
164
343
|
// underlying GridEditor added a record.
|
|
165
344
|
// add it to this Tag's value
|
|
@@ -226,12 +405,53 @@ function TagComponent(props) {
|
|
|
226
405
|
key={ix}
|
|
227
406
|
text={val.text}
|
|
228
407
|
onView={() => onView(val)}
|
|
229
|
-
onDelete={!isViewOnly ? () => onDelete(val) : null}
|
|
230
408
|
showEye={showEye}
|
|
409
|
+
onViewEditJoinData={() => onViewEditJoinData(val)}
|
|
410
|
+
showJoin={hasJoinData && (!mustSaveBeforeEditingJoinData || !isDirty)}
|
|
411
|
+
onDelete={!isViewOnly ? () => onDelete(val) : null}
|
|
231
412
|
minimizeForRow={minimizeForRow}
|
|
232
413
|
/>;
|
|
233
414
|
});
|
|
234
415
|
|
|
416
|
+
if (!_.isUndefined(getBaseParams) && outerValueId) {
|
|
417
|
+
useEffect(() => {
|
|
418
|
+
|
|
419
|
+
// NOTE: This useEffect is so we can dynamically set the TargetRepository's baseParams,
|
|
420
|
+
// based on outerValueId, before it loads.
|
|
421
|
+
// We did this for cases where the Tag field has joinData that's managing a nested Tag field.
|
|
422
|
+
// ... This deals with recursion, so gets "alice in wonderland" quickly!
|
|
423
|
+
// If that inner Tag field has getBaseParams defined on a joinDataConfig field of the outer Tag,
|
|
424
|
+
// then that means it needs to set its baseParams dynamically, based on the value of the outer ValueBox.
|
|
425
|
+
|
|
426
|
+
// For example: in the MetersEditor:
|
|
427
|
+
// {
|
|
428
|
+
// name: 'meters__pm_schedules',
|
|
429
|
+
// mustSaveBeforeEditingJoinData: true,
|
|
430
|
+
// joinDataConfig: {
|
|
431
|
+
// also_resets: {
|
|
432
|
+
// getBaseParams: (values, outerValueId) => {
|
|
433
|
+
// const baseParams = {
|
|
434
|
+
// 'conditions[MetersPmSchedules.meter_id]': meter_id, // limit also_resets to those MetersPmSchedules related to this meter
|
|
435
|
+
// };
|
|
436
|
+
// if (outerValueId) {
|
|
437
|
+
// baseParams['conditions[MetersPmSchedules.id <>]'] = outerValueId; // exclude the ValueBox that was clicked on
|
|
438
|
+
// }
|
|
439
|
+
// return baseParams;
|
|
440
|
+
// },
|
|
441
|
+
// },
|
|
442
|
+
// },
|
|
443
|
+
// }
|
|
444
|
+
|
|
445
|
+
TargetRepository.setBaseParams(getBaseParams(value, outerValueId));
|
|
446
|
+
setIsInited(true);
|
|
447
|
+
|
|
448
|
+
}, [value]);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (!isInited) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
|
|
235
455
|
valueRef.current = value; // the onGrid* methods were dealing with stale data, so use a ref, and update it here
|
|
236
456
|
|
|
237
457
|
let WhichCombo = Combo;
|
|
@@ -309,7 +529,7 @@ function TagComponent(props) {
|
|
|
309
529
|
|
|
310
530
|
{!isViewOnly &&
|
|
311
531
|
<WhichCombo
|
|
312
|
-
Repository={
|
|
532
|
+
Repository={TargetRepository}
|
|
313
533
|
Editor={props.Editor}
|
|
314
534
|
onSubmit={onChangeComboValue}
|
|
315
535
|
parent={self}
|
|
@@ -6,6 +6,7 @@ import clsx from 'clsx';
|
|
|
6
6
|
import testProps from '../../../../Functions/testProps.js';
|
|
7
7
|
import IconButton from '../../../Buttons/IconButton.js';
|
|
8
8
|
import Eye from '../../../Icons/Eye.js';
|
|
9
|
+
import Edit from '../../../Icons/Edit.js';
|
|
9
10
|
import Xmark from '../../../Icons/Xmark.js';
|
|
10
11
|
import UiGlobals from '../../../../UiGlobals.js';
|
|
11
12
|
import _ from 'lodash';
|
|
@@ -14,8 +15,10 @@ export default function ValueBox(props) {
|
|
|
14
15
|
const {
|
|
15
16
|
text,
|
|
16
17
|
onView,
|
|
18
|
+
showEye = false,
|
|
19
|
+
onViewEditJoinData,
|
|
20
|
+
showJoin = false,
|
|
17
21
|
onDelete,
|
|
18
|
-
showEye,
|
|
19
22
|
minimizeForRow = false,
|
|
20
23
|
} = props,
|
|
21
24
|
styles = UiGlobals.styles;
|
|
@@ -49,6 +52,22 @@ export default function ValueBox(props) {
|
|
|
49
52
|
styles.FORM_TAG_BTN_CLASSNAME,
|
|
50
53
|
)}
|
|
51
54
|
/>}
|
|
55
|
+
{showJoin &&
|
|
56
|
+
<IconButton
|
|
57
|
+
{...testProps('joinBtn')}
|
|
58
|
+
icon={Edit}
|
|
59
|
+
_icon={{
|
|
60
|
+
size: styles.FORM_TAG_VALUEBOX_ICON_SIZE,
|
|
61
|
+
className: 'text-grey-600',
|
|
62
|
+
}}
|
|
63
|
+
onPress={onViewEditJoinData}
|
|
64
|
+
className={clsx(
|
|
65
|
+
'ValueBox-joinBtn',
|
|
66
|
+
'h-full',
|
|
67
|
+
minimizeForRow ? 'py-0' : '',
|
|
68
|
+
styles.FORM_TAG_BTN_CLASSNAME,
|
|
69
|
+
)}
|
|
70
|
+
/>}
|
|
52
71
|
<Text
|
|
53
72
|
className={clsx(
|
|
54
73
|
'ValueBox-Text',
|
|
@@ -183,7 +183,7 @@ function Form(props) {
|
|
|
183
183
|
pointerEvents: fabOpacity.value > 0 ? 'auto' : 'none', // Disable interaction when invisible
|
|
184
184
|
};
|
|
185
185
|
}),
|
|
186
|
-
initialValues = _.merge(startingValues, (record && !record.isDestroyed ? record.submitValues : {})),
|
|
186
|
+
initialValues = _.merge(startingValues, ((record && !record.isDestroyed) ? (record.submitValues || record) : {})),
|
|
187
187
|
defaultValues = isMultiple ? getNullFieldValues(initialValues, Repository) : initialValues, // when multiple entities, set all default values to null
|
|
188
188
|
validatorToUse = (() => {
|
|
189
189
|
// If a custom validator is provided, use it
|
|
@@ -440,6 +440,7 @@ function Form(props) {
|
|
|
440
440
|
}
|
|
441
441
|
if (type.match(/Tag/)) {
|
|
442
442
|
elementClassName += ' overflow-auto';
|
|
443
|
+
configPropsToPass.SourceRepository = Repository;
|
|
443
444
|
}
|
|
444
445
|
if (!type.match(/Toggle/)) {
|
|
445
446
|
elementClassName += ' h-full';
|
|
@@ -540,8 +541,8 @@ function Form(props) {
|
|
|
540
541
|
if (isHidden) {
|
|
541
542
|
return null;
|
|
542
543
|
}
|
|
543
|
-
if (type === 'DisplayField') {
|
|
544
|
-
isEditable = false;
|
|
544
|
+
if (type === 'DisplayField' || type?.match(/Grid/)) {
|
|
545
|
+
isEditable = false; // this merely disables the FormController for this element
|
|
545
546
|
}
|
|
546
547
|
if (!itemPropsToPass.className) {
|
|
547
548
|
itemPropsToPass.className = '';
|
|
@@ -667,16 +668,19 @@ function Form(props) {
|
|
|
667
668
|
if (isEditorViewOnly || !isEditable) {
|
|
668
669
|
let value = null;
|
|
669
670
|
if (isSingle) {
|
|
670
|
-
value = record?.properties[name]?.displayValue || null;
|
|
671
|
-
if (_.isNil(value) && record
|
|
671
|
+
value = record?.properties?.[name]?.displayValue || null;
|
|
672
|
+
if (_.isNil(value) && !_.isNil(record?.[name])) {
|
|
672
673
|
value = record[name];
|
|
673
674
|
}
|
|
674
|
-
if (_.isNil(value) && startingValues
|
|
675
|
+
if (_.isNil(value) && !_.isNil(startingValues?.[name])) {
|
|
675
676
|
value = startingValues[name];
|
|
676
677
|
}
|
|
677
678
|
}
|
|
679
|
+
if (type.match(/Tag/)) {
|
|
680
|
+
itemPropsToPass.SourceRepository = Repository;
|
|
681
|
+
}
|
|
678
682
|
|
|
679
|
-
let elementClassName = 'field-' + name;
|
|
683
|
+
let elementClassName = name ? 'field-' + name : '';
|
|
680
684
|
const defaultsClassName = defaults.className;
|
|
681
685
|
if (defaultsClassName) {
|
|
682
686
|
elementClassName += ' ' + defaultsClassName;
|
|
@@ -689,7 +693,6 @@ function Form(props) {
|
|
|
689
693
|
if (viewerTypeClassName) {
|
|
690
694
|
elementClassName += ' ' + viewerTypeClassName;
|
|
691
695
|
}
|
|
692
|
-
|
|
693
696
|
let element = <Element
|
|
694
697
|
{...testProps('field-' + name)}
|
|
695
698
|
value={value}
|
|
@@ -787,6 +790,9 @@ function Form(props) {
|
|
|
787
790
|
if (getDynamicProps) {
|
|
788
791
|
dynamicProps = getDynamicProps({ fieldState, formSetValue, formGetValues, formState });
|
|
789
792
|
}
|
|
793
|
+
if (type.match(/Tag/)) {
|
|
794
|
+
itemPropsToPass.SourceRepository = Repository;
|
|
795
|
+
}
|
|
790
796
|
|
|
791
797
|
let elementClassName = 'Form-Element field-' + name + ' w-full';
|
|
792
798
|
const defaultsClassName = defaults.className;
|
|
@@ -810,6 +816,7 @@ function Form(props) {
|
|
|
810
816
|
{...testProps('field-' + name)}
|
|
811
817
|
name={name}
|
|
812
818
|
value={value}
|
|
819
|
+
isDirty={isDirty}
|
|
813
820
|
onChangeValue={(newValue) => {
|
|
814
821
|
if (newValue === undefined) {
|
|
815
822
|
newValue = null; // React Hook Form doesn't respond well when setting value to undefined
|
|
@@ -886,7 +893,8 @@ function Form(props) {
|
|
|
886
893
|
>*</Text>;
|
|
887
894
|
}
|
|
888
895
|
}
|
|
889
|
-
|
|
896
|
+
const labelToUse = dynamicProps.label || label;
|
|
897
|
+
if (!disableLabels && labelToUse && editorType !== EDITOR_TYPE__INLINE) {
|
|
890
898
|
const style = {};
|
|
891
899
|
if (defaults?.labelWidth) {
|
|
892
900
|
style.width = defaults.labelWidth;
|
|
@@ -901,7 +909,7 @@ function Form(props) {
|
|
|
901
909
|
element = <HStack className="Form-HStack8 w-full">
|
|
902
910
|
<Label style={style}>
|
|
903
911
|
{requiredIndicator}
|
|
904
|
-
{
|
|
912
|
+
{labelToUse}
|
|
905
913
|
</Label>
|
|
906
914
|
{element}
|
|
907
915
|
</HStack>;
|
|
@@ -909,7 +917,7 @@ function Form(props) {
|
|
|
909
917
|
element = <VStack className="Form-VStack9 w-full mt-3">
|
|
910
918
|
<Label style={style}>
|
|
911
919
|
{requiredIndicator}
|
|
912
|
-
{
|
|
920
|
+
{labelToUse}
|
|
913
921
|
</Label>
|
|
914
922
|
{element}
|
|
915
923
|
</VStack>;
|
|
@@ -1485,8 +1493,13 @@ function Form(props) {
|
|
|
1485
1493
|
|
|
1486
1494
|
} // END if (containerWidth)
|
|
1487
1495
|
|
|
1488
|
-
let className =
|
|
1489
|
-
|
|
1496
|
+
let className = clsx(
|
|
1497
|
+
'Form-VStackNative',
|
|
1498
|
+
'[transform:translateZ(0)]', // so embedded FAB will be relative to this container, not to viewport
|
|
1499
|
+
);
|
|
1500
|
+
if (props.className) {
|
|
1501
|
+
className += ' ' + props.className;
|
|
1502
|
+
}
|
|
1490
1503
|
const scrollToTopAnchor = <Box ref={(el) => (ancillaryItemsRef.current[0] = el)} className="h-0" />;
|
|
1491
1504
|
return <VStackNative
|
|
1492
1505
|
ref={formRef}
|