@onehat/ui 0.3.32 → 0.3.33
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 +1 -1
- package/src/Components/Form/Form.js +2 -1
- package/src/Components/Hoc/withComponent.js +6 -0
- package/src/Components/Hoc/withData.js +6 -0
- package/src/Components/Hoc/withEditor.js +44 -6
- package/src/Components/Hoc/withFilters.js +35 -5
- package/src/Components/Hoc/withSelection.js +16 -0
package/package.json
CHANGED
|
@@ -77,6 +77,7 @@ function Form(props) {
|
|
|
77
77
|
// sizing of outer container
|
|
78
78
|
h,
|
|
79
79
|
maxHeight,
|
|
80
|
+
minHeight = 0,
|
|
80
81
|
w,
|
|
81
82
|
maxWidth,
|
|
82
83
|
flex,
|
|
@@ -617,7 +618,7 @@ function Form(props) {
|
|
|
617
618
|
} else {
|
|
618
619
|
formComponents = buildFromItems();
|
|
619
620
|
const formAncillaryComponents = buildAncillary();
|
|
620
|
-
editor = <ScrollView _web={{
|
|
621
|
+
editor = <ScrollView _web={{ minHeight, }} width="100%" pb={1}>
|
|
621
622
|
<Column p={4}>{formComponents}</Column>
|
|
622
623
|
<Column m={2} pt={4}>{formAncillaryComponents}</Column>
|
|
623
624
|
</ScrollView>;
|
|
@@ -10,6 +10,7 @@ export default function withComponent(WrappedComponent) {
|
|
|
10
10
|
const {
|
|
11
11
|
// self: parent,
|
|
12
12
|
parent,
|
|
13
|
+
componentMethods,
|
|
13
14
|
...propsToPass
|
|
14
15
|
} = props,
|
|
15
16
|
{ reference } = props,
|
|
@@ -38,6 +39,11 @@ export default function withComponent(WrappedComponent) {
|
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
useEffect(() => {
|
|
42
|
+
if (componentMethods) {
|
|
43
|
+
_.each(componentMethods, (method, name) => {
|
|
44
|
+
selfRef.current[name] = method;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
41
47
|
if (parent && reference) {
|
|
42
48
|
parent.registerChild(selfRef.current);
|
|
43
49
|
}
|
|
@@ -28,6 +28,9 @@ export default function withData(WrappedComponent) {
|
|
|
28
28
|
displayField = 'value',
|
|
29
29
|
idIx,
|
|
30
30
|
displayIx,
|
|
31
|
+
|
|
32
|
+
// withComponent
|
|
33
|
+
self,
|
|
31
34
|
} = props,
|
|
32
35
|
propsToPass = _.omit(props, ['model']), // passing 'model' would mess things up if withData gets called twice (e.g. withData(...withData(...)) ), as we'd be trying to recreate Repository twice
|
|
33
36
|
localIdIx = idIx || (fields && idField ? fields.indexOf(idField) : null),
|
|
@@ -64,6 +67,9 @@ export default function withData(WrappedComponent) {
|
|
|
64
67
|
if (setRepository) { // pass it on up to higher components
|
|
65
68
|
setRepository(Repository);
|
|
66
69
|
}
|
|
70
|
+
if (self) {
|
|
71
|
+
self.repository = Repository;
|
|
72
|
+
}
|
|
67
73
|
setIsReady(true);
|
|
68
74
|
})();
|
|
69
75
|
|
|
@@ -22,6 +22,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
22
22
|
disableDelete = false,
|
|
23
23
|
disableDuplicate = false,
|
|
24
24
|
disableView = false,
|
|
25
|
+
useRemoteDuplicate = false, // call specific copyToNew function on server, rather than simple duplicate on client
|
|
25
26
|
getRecordIdentifier = (selection) => {
|
|
26
27
|
if (selection.length > 1) {
|
|
27
28
|
return 'records?';
|
|
@@ -224,6 +225,9 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
224
225
|
if (selection.length !== 1) {
|
|
225
226
|
return;
|
|
226
227
|
}
|
|
228
|
+
if (useRemoteDuplicate) {
|
|
229
|
+
return onRemoteDuplicate();
|
|
230
|
+
}
|
|
227
231
|
const
|
|
228
232
|
entity = selection[0],
|
|
229
233
|
idProperty = Repository.getSchema().model.idProperty,
|
|
@@ -233,6 +237,40 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
233
237
|
setEditorMode(EDITOR_MODE__EDIT);
|
|
234
238
|
setIsEditorShown(true);
|
|
235
239
|
},
|
|
240
|
+
onRemoteDuplicate = async () => {
|
|
241
|
+
|
|
242
|
+
// Call /duplicate on server
|
|
243
|
+
const
|
|
244
|
+
Model = Repository.getSchema().name,
|
|
245
|
+
entity = selection[0],
|
|
246
|
+
id = entity.id;
|
|
247
|
+
const result = await Repository._send('POST', Model + '/duplicate', { id });
|
|
248
|
+
const {
|
|
249
|
+
root,
|
|
250
|
+
success,
|
|
251
|
+
total,
|
|
252
|
+
message
|
|
253
|
+
} = Repository._processServerResponse(result);
|
|
254
|
+
|
|
255
|
+
if (!success) {
|
|
256
|
+
throw Error(message);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const duplicateId = root.id;
|
|
260
|
+
|
|
261
|
+
// Filter the grid with only the duplicate's ID, and open it for editing.
|
|
262
|
+
self.filterById(duplicateId, () => { // because of the way useFilters is made, we have to use a callback, not await a Promise.
|
|
263
|
+
|
|
264
|
+
// Select the only node
|
|
265
|
+
const duplicateEntity = Repository.getById(duplicateId);
|
|
266
|
+
self.setSelection([duplicateEntity]);
|
|
267
|
+
|
|
268
|
+
// edit it
|
|
269
|
+
onEdit();
|
|
270
|
+
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
},
|
|
236
274
|
onEditorSave = async (data, e) => {
|
|
237
275
|
const
|
|
238
276
|
what = record || selection,
|
|
@@ -343,12 +381,12 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
343
381
|
}, [selection]);
|
|
344
382
|
|
|
345
383
|
if (self) {
|
|
346
|
-
self.
|
|
347
|
-
self.
|
|
348
|
-
self.
|
|
349
|
-
self.
|
|
350
|
-
self.
|
|
351
|
-
self.
|
|
384
|
+
self.add = onAdd;
|
|
385
|
+
self.edit = onEdit;
|
|
386
|
+
self.delete = onDelete;
|
|
387
|
+
self.moveChildren = onMoveChildren;
|
|
388
|
+
self.deleteChildren = onDeleteChildren;
|
|
389
|
+
self.duplicate = onDuplicate;
|
|
352
390
|
}
|
|
353
391
|
|
|
354
392
|
if (lastSelection !== selection) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect, useId, } from 'react';
|
|
1
|
+
import { useState, useEffect, useId, useRef, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Column,
|
|
4
4
|
Modal,
|
|
@@ -46,6 +46,9 @@ export default function withFilters(WrappedComponent) {
|
|
|
46
46
|
|
|
47
47
|
// withData
|
|
48
48
|
Repository,
|
|
49
|
+
|
|
50
|
+
// withComponent
|
|
51
|
+
self,
|
|
49
52
|
} = props;
|
|
50
53
|
|
|
51
54
|
let modal = null,
|
|
@@ -59,7 +62,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
59
62
|
defaultFilters: modelDefaultFilters,
|
|
60
63
|
ancillaryFilters: modelAncillaryFilters,
|
|
61
64
|
} = Repository.getSchema().model,
|
|
62
|
-
id = props.id || useId(),
|
|
65
|
+
id = props.id || props.reference || useId(),
|
|
63
66
|
|
|
64
67
|
// determine the starting filters
|
|
65
68
|
startingFilters = !_.isEmpty(customFilters) ? customFilters : // custom filters override component filters
|
|
@@ -124,6 +127,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
const
|
|
130
|
+
filterCallbackRef = useRef(),
|
|
127
131
|
[filters, setFiltersRaw] = useState(formattedStartingFilters), // array of formatted filters
|
|
128
132
|
[slots, setSlots] = useState(startingSlots), // array of field names user is currently filtering on; blank slots have a null entry in array
|
|
129
133
|
[modalFilters, setModalFilters] = useState([]),
|
|
@@ -230,6 +234,21 @@ export default function withFilters(WrappedComponent) {
|
|
|
230
234
|
}
|
|
231
235
|
return inArray(filterType, ['NumberRange', 'DateRange']);
|
|
232
236
|
},
|
|
237
|
+
filterById = (id, cb) => {
|
|
238
|
+
onClearFilters();
|
|
239
|
+
filterCallbackRef.current = cb; // store the callback, so we can call it the next time this HOC renders with new filters
|
|
240
|
+
const newFilters = _.clone(filters);
|
|
241
|
+
_.remove(newFilters, (filter) => {
|
|
242
|
+
return filter.field === 'q';
|
|
243
|
+
});
|
|
244
|
+
newFilters.unshift({
|
|
245
|
+
field: 'q',
|
|
246
|
+
title: 'Search all text fields',
|
|
247
|
+
type: 'Input',
|
|
248
|
+
value: 'id:' + id,
|
|
249
|
+
});
|
|
250
|
+
setFilters(newFilters, false, false);
|
|
251
|
+
},
|
|
233
252
|
renderFilters = () => {
|
|
234
253
|
const
|
|
235
254
|
filterProps = {
|
|
@@ -347,7 +366,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
347
366
|
} else {
|
|
348
367
|
const
|
|
349
368
|
isAncillary = type === FILTER_TYPE_ANCILLARY,
|
|
350
|
-
filterName =
|
|
369
|
+
filterName = (isAncillary ? 'ancillary___' : '') + field;
|
|
351
370
|
newFilterNames.push(filterName);
|
|
352
371
|
newRepoFilters.push({ name: filterName, value, });
|
|
353
372
|
}
|
|
@@ -362,12 +381,17 @@ export default function withFilters(WrappedComponent) {
|
|
|
362
381
|
setPreviousFilterNames(newFilterNames);
|
|
363
382
|
}
|
|
364
383
|
|
|
365
|
-
Repository.filter(newRepoFilters, null, false); // false so other filters remain
|
|
366
|
-
|
|
367
384
|
if (searchAllText && Repository.searchAncillary && !Repository.hasBaseParam('searchAncillary')) {
|
|
368
385
|
Repository.setBaseParam('searchAncillary', true);
|
|
369
386
|
}
|
|
370
387
|
|
|
388
|
+
await Repository.filter(newRepoFilters, null, false); // false so other filters remain
|
|
389
|
+
|
|
390
|
+
if (filterCallbackRef.current) {
|
|
391
|
+
filterCallbackRef.current(); // call the callback
|
|
392
|
+
filterCallbackRef.current = null; // clear the callback
|
|
393
|
+
}
|
|
394
|
+
|
|
371
395
|
if (!isReady) {
|
|
372
396
|
setIsReady(true);
|
|
373
397
|
}
|
|
@@ -378,6 +402,11 @@ export default function withFilters(WrappedComponent) {
|
|
|
378
402
|
return null;
|
|
379
403
|
}
|
|
380
404
|
|
|
405
|
+
if (self) {
|
|
406
|
+
self.filterById = filterById;
|
|
407
|
+
self.setFilters = setFilters;
|
|
408
|
+
}
|
|
409
|
+
|
|
381
410
|
const
|
|
382
411
|
renderedFilters = renderFilters(),
|
|
383
412
|
hasFilters = !!renderedFilters.length;
|
|
@@ -499,6 +528,7 @@ export default function withFilters(WrappedComponent) {
|
|
|
499
528
|
editorType={EDITOR_TYPE__PLAIN}
|
|
500
529
|
flex={1}
|
|
501
530
|
startingValues={formStartingValues}
|
|
531
|
+
minHeight={minHeight}
|
|
502
532
|
items={[
|
|
503
533
|
{
|
|
504
534
|
type: 'Column',
|
|
@@ -27,6 +27,9 @@ export default function withSelection(WrappedComponent) {
|
|
|
27
27
|
autoSelectFirstItem = false,
|
|
28
28
|
fireEvent,
|
|
29
29
|
|
|
30
|
+
// withComponent
|
|
31
|
+
self,
|
|
32
|
+
|
|
30
33
|
// withValue
|
|
31
34
|
value,
|
|
32
35
|
setValue,
|
|
@@ -309,6 +312,19 @@ export default function withSelection(WrappedComponent) {
|
|
|
309
312
|
|
|
310
313
|
}, []);
|
|
311
314
|
|
|
315
|
+
if (self) {
|
|
316
|
+
self.setSelection = setSelection;
|
|
317
|
+
self.selectNext = selectNext;
|
|
318
|
+
self.selectPrev = selectPrev;
|
|
319
|
+
self.addToSelection = addToSelection;
|
|
320
|
+
self.removeFromSelection = removeFromSelection;
|
|
321
|
+
self.deselectAll = deselectAll;
|
|
322
|
+
self.selectRangeTo = selectRangeTo;
|
|
323
|
+
self.isInSelection = isInSelection;
|
|
324
|
+
self.getIdsFromLocalSelection = getIdsFromLocalSelection;
|
|
325
|
+
self.getDisplayValuesFromSelection = getDisplayValuesFromLocalSelection;
|
|
326
|
+
}
|
|
327
|
+
|
|
312
328
|
if (usesWithValue) {
|
|
313
329
|
useEffect(() => {
|
|
314
330
|
if (!isReady) {
|