@onehat/ui 0.3.241 → 0.3.243
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
CHANGED
|
@@ -173,134 +173,197 @@ function Form(props) {
|
|
|
173
173
|
context: { isPhantom },
|
|
174
174
|
}),
|
|
175
175
|
buildFromColumnsConfig = () => {
|
|
176
|
-
//
|
|
176
|
+
// Only used in InlineEditor
|
|
177
177
|
// Build the fields that match the current columnsConfig in the grid
|
|
178
178
|
const
|
|
179
|
-
model = Repository.getSchema().model,
|
|
180
179
|
elements = [],
|
|
181
|
-
columnProps = {
|
|
180
|
+
columnProps = { // props applied to every column
|
|
182
181
|
justifyContent: 'center',
|
|
183
182
|
alignItems: 'center',
|
|
184
183
|
borderRightWidth: 1,
|
|
185
184
|
borderRightColor: 'trueGray.200',
|
|
186
185
|
px: 1,
|
|
186
|
+
minWidth: styles.INLINE_EDITOR_MIN_WIDTH,
|
|
187
187
|
};
|
|
188
|
-
|
|
189
|
-
if (editorType === EDITOR_TYPE__INLINE) {
|
|
190
|
-
columnProps.minWidth = styles.INLINE_EDITOR_MIN_WIDTH;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
188
|
_.each(columnsConfig, (config, ix) => {
|
|
194
189
|
let {
|
|
195
190
|
fieldName,
|
|
191
|
+
isEditable = false,
|
|
192
|
+
editor = null,
|
|
196
193
|
editField,
|
|
197
|
-
isEditable,
|
|
198
|
-
editor,
|
|
199
194
|
renderer,
|
|
200
195
|
w,
|
|
201
196
|
flex,
|
|
197
|
+
onChange: onEditorChange,
|
|
202
198
|
useSelectorId = false,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
getDynamicProps,
|
|
200
|
+
getIsRequired,
|
|
201
|
+
...propsToPass
|
|
202
|
+
} = config,
|
|
203
|
+
type,
|
|
204
|
+
editorTypeProps = {},
|
|
205
|
+
viewerTypeProps = {};
|
|
206
|
+
|
|
207
|
+
if (editField) {
|
|
208
|
+
// Sometimes, columns will be configured to display one field
|
|
209
|
+
// and edit a different field
|
|
210
|
+
fieldName = editField;
|
|
211
|
+
}
|
|
212
|
+
const propertyDef = fieldName && Repository?.getSchema().getPropertyDefinition(fieldName);
|
|
213
|
+
if (propertyDef?.isEditingDisabled && checkIsEditingDisabled) {
|
|
214
|
+
isEditable = false;
|
|
215
|
+
}
|
|
216
|
+
if (!_.isNil(editor)) {
|
|
217
|
+
// if editor is defined on column, use it
|
|
218
|
+
if (_.isString(editor)) {
|
|
219
|
+
type = editor;
|
|
220
|
+
} else if (_.isPlainObject(editor)) {
|
|
221
|
+
const {
|
|
222
|
+
type: t,
|
|
223
|
+
...p
|
|
224
|
+
} = editor;
|
|
225
|
+
type = t;
|
|
226
|
+
editorTypeProps = p;
|
|
209
227
|
}
|
|
210
|
-
renderedValue += "\n(not editable)";
|
|
211
|
-
elements.push(<Box key={ix} w={w} flex={flex} {...columnProps}>
|
|
212
|
-
<Text numberOfLines={1} ellipsizeMode="head">{renderedValue}</Text>
|
|
213
|
-
</Box>);
|
|
214
228
|
} else {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (!editor) {
|
|
254
|
-
editor = 'Text';
|
|
255
|
-
}
|
|
256
|
-
if (!editor.match(/Toggle/)) {
|
|
257
|
-
editorProps.h = '40px'; // Toggle height gets applied incorrectly; just skip it
|
|
258
|
-
}
|
|
229
|
+
// editor is not defined, fall back to property definition
|
|
230
|
+
if (isEditable) {
|
|
231
|
+
const
|
|
232
|
+
{
|
|
233
|
+
type: t,
|
|
234
|
+
...p
|
|
235
|
+
} = propertyDef?.editorType;
|
|
236
|
+
type = t;
|
|
237
|
+
editorTypeProps = p;
|
|
238
|
+
} else if (propertyDef?.viewerType) {
|
|
239
|
+
const
|
|
240
|
+
{
|
|
241
|
+
type: t,
|
|
242
|
+
...p
|
|
243
|
+
} = propertyDef?.viewerType;
|
|
244
|
+
type = t;
|
|
245
|
+
viewerTypeProps = p;
|
|
246
|
+
} else {
|
|
247
|
+
type = 'Text';
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const isCombo = type?.match && type.match(/Combo/);
|
|
251
|
+
if (config.hasOwnProperty('autoLoad')) {
|
|
252
|
+
editorTypeProps.autoLoad = config.autoLoad;
|
|
253
|
+
} else {
|
|
254
|
+
if (isCombo && Repository?.isRemote && !Repository?.isLoaded) {
|
|
255
|
+
editorTypeProps.autoLoad = true;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (isCombo) {
|
|
259
|
+
// editorTypeProps.showEyeButton = true;
|
|
260
|
+
if (_.isNil(propsToPass.showXButton)) {
|
|
261
|
+
editorTypeProps.showXButton = true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const Element = getComponentFromType(type);
|
|
259
265
|
|
|
260
|
-
|
|
266
|
+
if (isEditorViewOnly || !isEditable) {
|
|
267
|
+
let value = null;
|
|
268
|
+
if (renderer) {
|
|
269
|
+
value = renderer(record);
|
|
270
|
+
} else {
|
|
271
|
+
if (record?.properties && record.properties[fieldName]) {
|
|
272
|
+
value = record.properties[fieldName].displayValue;
|
|
273
|
+
}
|
|
274
|
+
if (_.isNil(value) && record && record[fieldName]) {
|
|
275
|
+
value = record[fieldName];
|
|
276
|
+
}
|
|
277
|
+
if (_.isNil(value) && startingValues && startingValues[fieldName]) {
|
|
278
|
+
value = startingValues[fieldName];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
261
281
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
let element = <Element
|
|
283
|
+
value={value}
|
|
284
|
+
parent={self}
|
|
285
|
+
reference={fieldName}
|
|
286
|
+
{...propsToPass}
|
|
287
|
+
{...viewerTypeProps}
|
|
288
|
+
/>;
|
|
289
|
+
elements.push(<Box key={ix} w={w} flex={flex} {...columnProps}>{element}</Box>);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
elements.push(<Controller
|
|
294
|
+
key={'controller-' + ix}
|
|
295
|
+
name={fieldName}
|
|
296
|
+
// rules={rules}
|
|
297
|
+
control={control}
|
|
298
|
+
render={(args) => {
|
|
299
|
+
const {
|
|
300
|
+
field,
|
|
301
|
+
fieldState,
|
|
302
|
+
// formState,
|
|
303
|
+
} = args,
|
|
304
|
+
{
|
|
305
|
+
onChange,
|
|
306
|
+
onBlur,
|
|
307
|
+
name,
|
|
308
|
+
value,
|
|
309
|
+
// ref,
|
|
310
|
+
} = field,
|
|
311
|
+
{
|
|
312
|
+
isTouched,
|
|
313
|
+
isDirty,
|
|
314
|
+
error,
|
|
315
|
+
} = fieldState;
|
|
316
|
+
|
|
317
|
+
if (isValidElement(Element)) {
|
|
318
|
+
throw new Error('Should not yet be valid React element. Did you use <Element> instead of () => <Element> when defining it?')
|
|
319
|
+
}
|
|
285
320
|
|
|
286
|
-
|
|
287
|
-
|
|
321
|
+
if (useSelectorId) { // This causes the whole form to use selectorId
|
|
322
|
+
editorTypeProps.selectorId = selectorId;
|
|
323
|
+
}
|
|
324
|
+
if (propsToPass.selectorId || editorTypeProps.selectorId) { // editorTypeProps.selectorId causes just this one field to use selectorId
|
|
325
|
+
if (_.isNil(propsToPass.selectorSelected)) {
|
|
326
|
+
editorTypeProps.selectorSelected = record;
|
|
288
327
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
// {element}
|
|
295
|
-
// <Text color="#f00">{error.message}</Text>
|
|
296
|
-
// </Column>;
|
|
297
|
-
// }
|
|
328
|
+
}
|
|
329
|
+
let dynamicProps = {};
|
|
330
|
+
if (getDynamicProps) {
|
|
331
|
+
dynamicProps = getDynamicProps({ fieldState, formSetValue, formGetValues, formState });
|
|
332
|
+
}
|
|
298
333
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
|
|
334
|
+
if (type.match(/Tag/)) {
|
|
335
|
+
editorTypeProps.overflow = 'auto';
|
|
336
|
+
}
|
|
337
|
+
if (!type.match(/Toggle/)) {
|
|
338
|
+
editorTypeProps.h = '40px';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
let element = <Element
|
|
342
|
+
name={name}
|
|
343
|
+
value={value}
|
|
344
|
+
onChangeValue={(newValue) => {
|
|
345
|
+
if (newValue === undefined) {
|
|
346
|
+
newValue = null; // React Hook Form doesn't respond well when setting value to undefined
|
|
347
|
+
}
|
|
348
|
+
onChange(newValue);
|
|
349
|
+
if (onEditorChange) {
|
|
350
|
+
onEditorChange(newValue, formSetValue, formGetValues, formState, trigger);
|
|
351
|
+
}
|
|
352
|
+
}}
|
|
353
|
+
onBlur={onBlur}
|
|
354
|
+
flex={1}
|
|
355
|
+
parent={self}
|
|
356
|
+
reference={name}
|
|
357
|
+
{...propsToPass}
|
|
358
|
+
{...editorTypeProps}
|
|
359
|
+
{...dynamicProps}
|
|
360
|
+
/>;
|
|
361
|
+
|
|
362
|
+
const dirtyIcon = isDirty && !disableDirtyIcon ? <Icon as={Pencil} size="2xs" color="trueGray.300" position="absolute" top="2px" left="2px" /> : null;
|
|
363
|
+
return <Row key={ix} bg={error ? '#fdd' : '#fff'} w={w} flex={flex} {...columnProps}>{dirtyIcon}{element}</Row>;
|
|
364
|
+
}}
|
|
365
|
+
/>);
|
|
366
|
+
|
|
304
367
|
});
|
|
305
368
|
return <Row>{elements}</Row>;
|
|
306
369
|
},
|
|
@@ -328,7 +391,8 @@ function Form(props) {
|
|
|
328
391
|
getIsRequired,
|
|
329
392
|
...propsToPass
|
|
330
393
|
} = item,
|
|
331
|
-
editorTypeProps = {}
|
|
394
|
+
editorTypeProps = {},
|
|
395
|
+
viewerTypeProps = {};
|
|
332
396
|
|
|
333
397
|
if (isHidden) {
|
|
334
398
|
return null;
|
|
@@ -359,6 +423,7 @@ function Form(props) {
|
|
|
359
423
|
...p
|
|
360
424
|
} = propertyDef?.viewerType;
|
|
361
425
|
type = t;
|
|
426
|
+
viewerTypeProps = p;
|
|
362
427
|
} else {
|
|
363
428
|
type = 'Text';
|
|
364
429
|
}
|
|
@@ -378,9 +443,9 @@ function Form(props) {
|
|
|
378
443
|
}
|
|
379
444
|
}
|
|
380
445
|
const Element = getComponentFromType(type);
|
|
381
|
-
let children;
|
|
382
446
|
|
|
383
447
|
if (inArray(type, ['Column', 'Row', 'FieldSet'])) {
|
|
448
|
+
let children;
|
|
384
449
|
if (_.isEmpty(items)) {
|
|
385
450
|
return null;
|
|
386
451
|
}
|
|
@@ -432,6 +497,7 @@ function Form(props) {
|
|
|
432
497
|
parent={self}
|
|
433
498
|
reference={name}
|
|
434
499
|
{...propsToPass}
|
|
500
|
+
{...viewerTypeProps}
|
|
435
501
|
/>;
|
|
436
502
|
if (!disableLabels && label) {
|
|
437
503
|
const labelProps = {};
|
|
@@ -492,6 +558,7 @@ function Form(props) {
|
|
|
492
558
|
isDirty,
|
|
493
559
|
error,
|
|
494
560
|
} = fieldState;
|
|
561
|
+
|
|
495
562
|
if (isValidElement(Element)) {
|
|
496
563
|
throw new Error('Should not yet be valid React element. Did you use <Element> instead of () => <Element> when defining it?')
|
|
497
564
|
}
|
|
@@ -62,13 +62,6 @@ export default function withInlineEditor(WrappedComponent, skipWrappers = false)
|
|
|
62
62
|
onChangeColumnsConfig = (columnsConfig) => {
|
|
63
63
|
setLocalColumnsConfig(columnsConfig);
|
|
64
64
|
},
|
|
65
|
-
onRowClick = (item, rowIndex, e) => {
|
|
66
|
-
// move the editor up to the appropriate row
|
|
67
|
-
const currentRow = e.currentTarget;
|
|
68
|
-
moveEditor(currentRow);
|
|
69
|
-
|
|
70
|
-
setCurrentRow(currentRow);
|
|
71
|
-
},
|
|
72
65
|
onScreenResize = () => {
|
|
73
66
|
// TODO: Attach a div with zIndex 0 to body to monitor resize events. THis is handler
|
|
74
67
|
|
|
@@ -83,12 +76,28 @@ export default function withInlineEditor(WrappedComponent, skipWrappers = false)
|
|
|
83
76
|
delta = editorBounds.top - rowBounds.top;
|
|
84
77
|
|
|
85
78
|
editorStyle.top = (-1 * delta) + 'px';
|
|
79
|
+
},
|
|
80
|
+
onEditorShown = () => {
|
|
81
|
+
// determine which row to move the editor to
|
|
82
|
+
const
|
|
83
|
+
data = self.gridRef.current.props.data, // This is okay, because (for now) the inlineEditor is only for use with grids
|
|
84
|
+
ix = data.indexOf(selection[0]),
|
|
85
|
+
gridRowsContainer = self.gridRef.current._listRef._scrollRef.childNodes[0],
|
|
86
|
+
currentRow = gridRowsContainer.childNodes[ix];
|
|
87
|
+
|
|
88
|
+
// TODO: verify it works if not using a Repository
|
|
89
|
+
|
|
90
|
+
moveEditor(currentRow);
|
|
91
|
+
setCurrentRow(currentRow);
|
|
86
92
|
};
|
|
87
93
|
|
|
88
94
|
useEffect(() => {
|
|
89
95
|
if (maskRef.current) {
|
|
90
96
|
maskRef.current.focus();
|
|
91
97
|
}
|
|
98
|
+
if (isEditorShown) {
|
|
99
|
+
onEditorShown();
|
|
100
|
+
}
|
|
92
101
|
}, [isEditorShown]);
|
|
93
102
|
|
|
94
103
|
if (isEditorShown && selection.length < 1) {
|
|
@@ -166,7 +175,6 @@ export default function withInlineEditor(WrappedComponent, skipWrappers = false)
|
|
|
166
175
|
return <WrappedComponent
|
|
167
176
|
{...props}
|
|
168
177
|
onChangeColumnsConfig={onChangeColumnsConfig}
|
|
169
|
-
onEditorRowClick={onRowClick}
|
|
170
178
|
inlineEditor={inlineEditor}
|
|
171
179
|
isInlineEditorShown={isEditorShown}
|
|
172
180
|
/>;
|