@onehat/ui 0.2.76 → 0.2.78
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/Editor/Editor.js +1 -11
- package/src/Components/Form/Form.js +24 -22
- package/src/Components/Grid/Grid.js +29 -19
- package/src/Components/Grid/GridHeaderRow.js +6 -0
- package/src/Components/Grid/GridRow.js +6 -0
- package/src/Components/Hoc/withDraggable.js +8 -3
- package/src/Components/Hoc/withEditor.js +35 -11
- package/src/Components/Hoc/withInlineEditor.js +53 -22
- package/src/Components/Tree/Tree.js +282 -257
- package/src/Components/Tree/TreeNode.js +12 -18
- package/src/Constants/Directions.js +1 -0
- package/src/Constants/Styles.js +5 -0
- package/src/Constants/Tree.js +4 -1
- package/src/Constants/UiModes.js +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EDITOR_MODE__VIEW,
|
|
3
|
-
EDITOR_MODE__ADD,
|
|
4
|
-
EDITOR_MODE__EDIT,
|
|
5
3
|
} from '../../Constants/Editor.js';
|
|
6
4
|
import _ from 'lodash';
|
|
7
5
|
|
|
@@ -16,7 +14,6 @@ export default function Editor(props) {
|
|
|
16
14
|
onEditorClose: onClose,
|
|
17
15
|
onEditorDelete: onDelete,
|
|
18
16
|
editorMode,
|
|
19
|
-
setEditorMode,
|
|
20
17
|
|
|
21
18
|
// withData
|
|
22
19
|
Repository,
|
|
@@ -24,13 +21,7 @@ export default function Editor(props) {
|
|
|
24
21
|
// withSelection
|
|
25
22
|
selection,
|
|
26
23
|
|
|
27
|
-
} =
|
|
28
|
-
onEditMode = () => {
|
|
29
|
-
setEditorMode(EDITOR_MODE__EDIT);
|
|
30
|
-
},
|
|
31
|
-
onViewMode = () => {
|
|
32
|
-
setEditorMode(EDITOR_MODE__VIEW);
|
|
33
|
-
};
|
|
24
|
+
} = prop;
|
|
34
25
|
|
|
35
26
|
if (_.isEmpty(selection)) {
|
|
36
27
|
return null;
|
|
@@ -52,7 +43,6 @@ export default function Editor(props) {
|
|
|
52
43
|
return <Form
|
|
53
44
|
{...props}
|
|
54
45
|
record={selection}
|
|
55
|
-
onViewMode={onViewMode}
|
|
56
46
|
onCancel={onCancel}
|
|
57
47
|
onSave={onSave}
|
|
58
48
|
onClose={onClose}
|
|
@@ -87,6 +87,7 @@ function Form(props) {
|
|
|
87
87
|
onSave,
|
|
88
88
|
onClose,
|
|
89
89
|
onDelete,
|
|
90
|
+
editorStateRef,
|
|
90
91
|
|
|
91
92
|
// DataMgt
|
|
92
93
|
selectorId,
|
|
@@ -148,6 +149,11 @@ function Form(props) {
|
|
|
148
149
|
borderRightColor: 'trueGray.200',
|
|
149
150
|
px: 1,
|
|
150
151
|
};
|
|
152
|
+
|
|
153
|
+
if (editorType === EDITOR_TYPE__INLINE) {
|
|
154
|
+
columnProps.minWidth = styles.INLINE_EDITOR_MIN_WIDTH;
|
|
155
|
+
}
|
|
156
|
+
|
|
151
157
|
_.each(columnsConfig, (config, ix) => {
|
|
152
158
|
let {
|
|
153
159
|
fieldName,
|
|
@@ -159,7 +165,11 @@ function Form(props) {
|
|
|
159
165
|
} = config;
|
|
160
166
|
|
|
161
167
|
if (!isEditable) {
|
|
162
|
-
|
|
168
|
+
let renderedValue = renderer ? renderer(record) : record[fieldName];
|
|
169
|
+
if (_.isBoolean(renderedValue)) {
|
|
170
|
+
renderedValue = renderedValue.toString();
|
|
171
|
+
}
|
|
172
|
+
renderedValue += "\n(not editable)";
|
|
163
173
|
elements.push(<Box key={ix} w={w} flex={flex} {...columnProps}>
|
|
164
174
|
<Text numberOfLines={1} ellipsizeMode="head">{renderedValue}</Text>
|
|
165
175
|
</Box>);
|
|
@@ -200,13 +210,7 @@ function Form(props) {
|
|
|
200
210
|
}
|
|
201
211
|
}
|
|
202
212
|
const Element = getComponentFromType(editor);
|
|
203
|
-
|
|
204
|
-
debugger;
|
|
205
|
-
// LEFT OFF HERE
|
|
206
|
-
// Trying inline editor, based on columnsConfig
|
|
207
|
-
// Getting an error that the OrdersEditor is missing users__email.
|
|
208
|
-
// Why is this even on the OrdersEditor? Runner?
|
|
209
|
-
}
|
|
213
|
+
|
|
210
214
|
let element = <Element
|
|
211
215
|
name={name}
|
|
212
216
|
value={value}
|
|
@@ -450,6 +454,10 @@ function Form(props) {
|
|
|
450
454
|
// if (Repository && (!record || _.isEmpty(record))) {
|
|
451
455
|
// return null;
|
|
452
456
|
// }
|
|
457
|
+
|
|
458
|
+
if (!_.isNil(editorStateRef)) {
|
|
459
|
+
editorStateRef.current = formState; // Update state so HOC can know what's going on
|
|
460
|
+
}
|
|
453
461
|
|
|
454
462
|
const sizeProps = {};
|
|
455
463
|
if (!flex && !h && !w) {
|
|
@@ -517,6 +525,12 @@ function Form(props) {
|
|
|
517
525
|
if (_.isEmpty(formState.dirtyFields) && !record?.isRemotePhantom) {
|
|
518
526
|
isSaveDisabled = true;
|
|
519
527
|
}
|
|
528
|
+
|
|
529
|
+
if (editorType === EDITOR_TYPE__INLINE) {
|
|
530
|
+
buttonGroupProps.position = 'fixed';
|
|
531
|
+
buttonGroupProps.left = 10; // TODO: I would prefer to have this be centered, but it's a lot more complex than just making it stick to the left
|
|
532
|
+
footerProps.alignItems = 'flex-start';
|
|
533
|
+
}
|
|
520
534
|
|
|
521
535
|
return <Column {...sizeProps} onLayout={onLayout}>
|
|
522
536
|
|
|
@@ -532,13 +546,7 @@ function Form(props) {
|
|
|
532
546
|
{isSingle && editorMode === EDITOR_MODE__EDIT && onViewMode &&
|
|
533
547
|
<Button
|
|
534
548
|
key="viewBtn"
|
|
535
|
-
onPress={
|
|
536
|
-
if (!_.isEmpty(formState.dirtyFields)) {
|
|
537
|
-
confirm('This record has unsaved changes. Are you sure you want to switch to "View" mode? Changes will be lost.', onViewMode);
|
|
538
|
-
} else {
|
|
539
|
-
onViewMode();
|
|
540
|
-
}
|
|
541
|
-
}}
|
|
549
|
+
onPress={onViewMode}
|
|
542
550
|
leftIcon={<Icon as={Eye} color="#fff" size="sm" />}
|
|
543
551
|
color="#fff"
|
|
544
552
|
>To View</Button>}
|
|
@@ -579,13 +587,7 @@ function Form(props) {
|
|
|
579
587
|
{!isViewOnly && onCancel && <Button
|
|
580
588
|
key="cancelBtn"
|
|
581
589
|
variant="ghost"
|
|
582
|
-
onPress={
|
|
583
|
-
if (!_.isEmpty(formState.dirtyFields)) {
|
|
584
|
-
confirm('This record has unsaved changes. Are you sure you want to cancel editing? Changes will be lost.', onCancel);
|
|
585
|
-
} else {
|
|
586
|
-
onCancel();
|
|
587
|
-
}
|
|
588
|
-
}}
|
|
590
|
+
onPress={onCancel}
|
|
589
591
|
color="#fff"
|
|
590
592
|
>Cancel</Button>}
|
|
591
593
|
{!isViewOnly && onSave && <Button
|
|
@@ -127,8 +127,8 @@ function GridComponent(props) {
|
|
|
127
127
|
selectorSelected,
|
|
128
128
|
|
|
129
129
|
// withInlineEditor
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
inlineEditor = null,
|
|
131
|
+
isInlineEditorShown = false,
|
|
132
132
|
onEditorRowClick,
|
|
133
133
|
|
|
134
134
|
} = props,
|
|
@@ -137,8 +137,8 @@ function GridComponent(props) {
|
|
|
137
137
|
gridRef = useRef(),
|
|
138
138
|
[isReady, setIsReady] = useState(false),
|
|
139
139
|
[isLoading, setIsLoading] = useState(false),
|
|
140
|
-
[isReorderMode, setIsReorderMode] = useState(false),
|
|
141
140
|
[localColumnsConfig, setLocalColumnsConfigRaw] = useState([]),
|
|
141
|
+
[isDragMode, setIsDragMode] = useState(false),
|
|
142
142
|
[dragRowSlot, setDragRowSlot] = useState(null),
|
|
143
143
|
[dragRowIx, setDragRowIx] = useState(),
|
|
144
144
|
setLocalColumnsConfig = (config) => {
|
|
@@ -148,6 +148,9 @@ function GridComponent(props) {
|
|
|
148
148
|
}
|
|
149
149
|
},
|
|
150
150
|
onRowClick = (item, e) => {
|
|
151
|
+
if (isInlineEditorShown) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
151
154
|
const
|
|
152
155
|
{
|
|
153
156
|
shiftKey,
|
|
@@ -223,9 +226,8 @@ function GridComponent(props) {
|
|
|
223
226
|
if (canRowsReorder) {
|
|
224
227
|
items.unshift(<IconButton
|
|
225
228
|
key="reorderBtn"
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
icon={<Icon as={isReorderMode ? NoReorderRows : ReorderRows} color={styles.GRID_TOOLBAR_ITEMS_COLOR} />}
|
|
229
|
+
onPress={() => setIsDragMode(!isDragMode)}
|
|
230
|
+
icon={<Icon as={isDragMode ? NoReorderRows : ReorderRows} color={styles.GRID_TOOLBAR_ITEMS_COLOR} />}
|
|
229
231
|
/>);
|
|
230
232
|
}
|
|
231
233
|
return items;
|
|
@@ -234,6 +236,9 @@ function GridComponent(props) {
|
|
|
234
236
|
if (row.item.isDestroyed) {
|
|
235
237
|
return null;
|
|
236
238
|
}
|
|
239
|
+
if (row.item.id === 'inlineEditor') {
|
|
240
|
+
return inlineEditor;
|
|
241
|
+
}
|
|
237
242
|
|
|
238
243
|
let {
|
|
239
244
|
item,
|
|
@@ -249,7 +254,7 @@ function GridComponent(props) {
|
|
|
249
254
|
if (e.preventDefault && e.cancelable) {
|
|
250
255
|
e.preventDefault();
|
|
251
256
|
}
|
|
252
|
-
if (isHeaderRow ||
|
|
257
|
+
if (isHeaderRow || isDragMode) {
|
|
253
258
|
return
|
|
254
259
|
}
|
|
255
260
|
switch (e.detail) {
|
|
@@ -276,7 +281,7 @@ function GridComponent(props) {
|
|
|
276
281
|
if (e.preventDefault && e.cancelable) {
|
|
277
282
|
e.preventDefault();
|
|
278
283
|
}
|
|
279
|
-
if (isHeaderRow ||
|
|
284
|
+
if (isHeaderRow || isDragMode) {
|
|
280
285
|
return
|
|
281
286
|
}
|
|
282
287
|
|
|
@@ -310,6 +315,7 @@ function GridComponent(props) {
|
|
|
310
315
|
setSelection={setSelection}
|
|
311
316
|
gridRef={gridRef}
|
|
312
317
|
isHovered={isHovered}
|
|
318
|
+
isInlineEditorShown={isInlineEditorShown}
|
|
313
319
|
/>;
|
|
314
320
|
}
|
|
315
321
|
|
|
@@ -332,7 +338,7 @@ function GridComponent(props) {
|
|
|
332
338
|
}
|
|
333
339
|
let WhichGridRow = GridRow,
|
|
334
340
|
rowReorderProps = {};
|
|
335
|
-
if (canRowsReorder &&
|
|
341
|
+
if (canRowsReorder && isDragMode) {
|
|
336
342
|
WhichGridRow = ReorderableGridRow;
|
|
337
343
|
rowReorderProps = {
|
|
338
344
|
mode: VERTICAL,
|
|
@@ -354,6 +360,7 @@ function GridComponent(props) {
|
|
|
354
360
|
hideNavColumn={hideNavColumn}
|
|
355
361
|
bg={bg}
|
|
356
362
|
item={item}
|
|
363
|
+
isInlineEditorShown={isInlineEditorShown}
|
|
357
364
|
{...rowReorderProps}
|
|
358
365
|
/>;
|
|
359
366
|
}}
|
|
@@ -388,7 +395,7 @@ function GridComponent(props) {
|
|
|
388
395
|
row = node.parentElement.parentElement,
|
|
389
396
|
parent = row.parentElement,
|
|
390
397
|
parentRect = parent.getBoundingClientRect(),
|
|
391
|
-
rows = _.filter(
|
|
398
|
+
rows = _.filter(parent.children, (childNode) => {
|
|
392
399
|
return childNode.getBoundingClientRect().height !== 0; // Skip zero-height children
|
|
393
400
|
}),
|
|
394
401
|
currentY = proxyRect.top - parentRect.top, // top position of pointer, relative to page
|
|
@@ -473,7 +480,7 @@ function GridComponent(props) {
|
|
|
473
480
|
row = node.parentElement.parentElement,
|
|
474
481
|
parent = row.parentElement,
|
|
475
482
|
parentRect = parent.getBoundingClientRect(),
|
|
476
|
-
rows = _.filter(
|
|
483
|
+
rows = _.filter(parent.children, (childNode) => {
|
|
477
484
|
return childNode.getBoundingClientRect().height !== 0; // Skip zero-height children
|
|
478
485
|
}),
|
|
479
486
|
currentY = proxyRect.top - parentRect.top, // top position of pointer, relative to page
|
|
@@ -537,7 +544,7 @@ function GridComponent(props) {
|
|
|
537
544
|
const
|
|
538
545
|
rowContainerRect = rows[newIx].getBoundingClientRect(),
|
|
539
546
|
top = (useBottom ? rowContainerRect.bottom : rowContainerRect.top) - parentRect.top - parseInt(parent.style.borderWidth); // get relative Y position
|
|
540
|
-
let marker = dragRowSlot
|
|
547
|
+
let marker = dragRowSlot?.marker;
|
|
541
548
|
if (marker) {
|
|
542
549
|
marker.style.top = top -4 + 'px'; // -4 so it's always visible
|
|
543
550
|
}
|
|
@@ -661,10 +668,10 @@ function GridComponent(props) {
|
|
|
661
668
|
...propsToPass,
|
|
662
669
|
};
|
|
663
670
|
|
|
664
|
-
if (!config.w && !config.flex) {
|
|
671
|
+
if (!(config.w || config.width) && !config.flex) {
|
|
665
672
|
// Neither is set
|
|
666
673
|
config.w = 100; // default
|
|
667
|
-
} else if (config.flex && config.width) {
|
|
674
|
+
} else if (config.flex && (config.w || config.width)) {
|
|
668
675
|
// Both are set. Width overrules flex.
|
|
669
676
|
delete config.flex;
|
|
670
677
|
}
|
|
@@ -730,7 +737,7 @@ function GridComponent(props) {
|
|
|
730
737
|
|
|
731
738
|
}, [selectorId, selectorSelected]);
|
|
732
739
|
|
|
733
|
-
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons,
|
|
740
|
+
const footerToolbarItemComponents = useMemo(() => getFooterToolbarItems(), [additionalToolbarButtons, isDragMode]);
|
|
734
741
|
|
|
735
742
|
if (!isReady) {
|
|
736
743
|
return null;
|
|
@@ -742,6 +749,9 @@ function GridComponent(props) {
|
|
|
742
749
|
if (showHeaders) {
|
|
743
750
|
rowData.unshift({ id: 'headerRow' });
|
|
744
751
|
}
|
|
752
|
+
if (inlineEditor) {
|
|
753
|
+
rowData.push({ id: 'inlineEditor' }); // make editor the last row so it can scroll with all other rows
|
|
754
|
+
}
|
|
745
755
|
const initialNumToRender = rowData.length || 10;
|
|
746
756
|
|
|
747
757
|
// headers & footers
|
|
@@ -769,7 +779,7 @@ function GridComponent(props) {
|
|
|
769
779
|
{topToolbar}
|
|
770
780
|
|
|
771
781
|
<Column w="100%" flex={1} borderTopWidth={isLoading ? 2 : 1} borderTopColor={isLoading ? '#f00' : 'trueGray.300'} onClick={() => {
|
|
772
|
-
if (!
|
|
782
|
+
if (!isDragMode && !isInlineEditorShown) {
|
|
773
783
|
deselectAll();
|
|
774
784
|
}
|
|
775
785
|
}}>
|
|
@@ -782,9 +792,9 @@ function GridComponent(props) {
|
|
|
782
792
|
nestedScrollEnabled={true}
|
|
783
793
|
contentContainerStyle={{
|
|
784
794
|
overflow: 'auto',
|
|
785
|
-
borderWidth:
|
|
786
|
-
borderColor:
|
|
787
|
-
borderStyle:
|
|
795
|
+
borderWidth: isDragMode ? styles.REORDER_BORDER_WIDTH : 0,
|
|
796
|
+
borderColor: isDragMode ? styles.REORDER_BORDER_COLOR : null,
|
|
797
|
+
borderStyle: styles.REORDER_BORDER_STYLE,
|
|
788
798
|
flex: 1,
|
|
789
799
|
}}
|
|
790
800
|
refreshing={isLoading}
|
|
@@ -40,6 +40,7 @@ export default function GridHeaderRow(props) {
|
|
|
40
40
|
setSelection,
|
|
41
41
|
gridRef,
|
|
42
42
|
isHovered,
|
|
43
|
+
isInlineEditorShown,
|
|
43
44
|
} = props,
|
|
44
45
|
styles = UiGlobals.styles,
|
|
45
46
|
sortFn = Repository && Repository.getSortFn(),
|
|
@@ -316,6 +317,10 @@ export default function GridHeaderRow(props) {
|
|
|
316
317
|
}
|
|
317
318
|
}
|
|
318
319
|
|
|
320
|
+
if (isInlineEditorShown) {
|
|
321
|
+
propsToPass.minWidth = styles.INLINE_EDITOR_MIN_WIDTH;
|
|
322
|
+
}
|
|
323
|
+
|
|
319
324
|
return <Pressable
|
|
320
325
|
key={ix}
|
|
321
326
|
onPress={(e) => {
|
|
@@ -453,6 +458,7 @@ export default function GridHeaderRow(props) {
|
|
|
453
458
|
isSortDirectionAsc,
|
|
454
459
|
sortFn,
|
|
455
460
|
sortField,
|
|
461
|
+
isInlineEditorShown,
|
|
456
462
|
]);
|
|
457
463
|
}
|
|
458
464
|
|
|
@@ -23,6 +23,7 @@ export default function GridRow(props) {
|
|
|
23
23
|
hideNavColumn,
|
|
24
24
|
bg,
|
|
25
25
|
item,
|
|
26
|
+
isInlineEditorShown,
|
|
26
27
|
} = props,
|
|
27
28
|
styles = UiGlobals.styles,
|
|
28
29
|
isPhantom = item.isPhantom,
|
|
@@ -44,6 +45,10 @@ export default function GridRow(props) {
|
|
|
44
45
|
propsToPass.p = 1;
|
|
45
46
|
propsToPass.justifyContent = 'center';
|
|
46
47
|
|
|
48
|
+
if (isInlineEditorShown) {
|
|
49
|
+
propsToPass.minWidth = styles.INLINE_EDITOR_MIN_WIDTH;
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
let value;
|
|
48
53
|
if (_.isPlainObject(config)) {
|
|
49
54
|
if (config.renderer) {
|
|
@@ -141,6 +146,7 @@ export default function GridRow(props) {
|
|
|
141
146
|
item,
|
|
142
147
|
isPhantom,
|
|
143
148
|
hash, // this is an easy way to determine if the data has changed and the item needs to be rerendered
|
|
149
|
+
isInlineEditorShown,
|
|
144
150
|
]);
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -29,11 +29,13 @@ export default function withDraggable(WrappedComponent) {
|
|
|
29
29
|
onDrag,
|
|
30
30
|
onDragStop,
|
|
31
31
|
onChangeIsDragging,
|
|
32
|
+
getDraggableNodeFromNode = (node) => node,
|
|
32
33
|
getParentNode = (node) => node.parentElement.parentElement,
|
|
33
34
|
getProxy,
|
|
34
35
|
proxyParent,
|
|
35
36
|
proxyPositionRelativeToParent = false,
|
|
36
37
|
handle,
|
|
38
|
+
draggableProps = {},
|
|
37
39
|
...propsToPass
|
|
38
40
|
} = props,
|
|
39
41
|
{
|
|
@@ -57,7 +59,7 @@ export default function withDraggable(WrappedComponent) {
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
const
|
|
60
|
-
node = info.node,
|
|
62
|
+
node = getDraggableNodeFromNode(info.node),
|
|
61
63
|
parentContainer = getParentNode && getParentNode(node);
|
|
62
64
|
|
|
63
65
|
setNode(node);
|
|
@@ -226,8 +228,9 @@ export default function withDraggable(WrappedComponent) {
|
|
|
226
228
|
onStop={handleStop}
|
|
227
229
|
position={{ x: 0, y: 0, /* reset to dropped position */ }}
|
|
228
230
|
// bounds={bounds}
|
|
231
|
+
{...draggableProps}
|
|
229
232
|
>
|
|
230
|
-
<div className="nsResize">
|
|
233
|
+
<div className="nsResize" style={{ width: '100%', }}>
|
|
231
234
|
<WrappedComponent {...propsToPass} />
|
|
232
235
|
</div>
|
|
233
236
|
</Draggable>;
|
|
@@ -239,6 +242,7 @@ export default function withDraggable(WrappedComponent) {
|
|
|
239
242
|
onStop={handleStop}
|
|
240
243
|
position={{ x: 0, y: 0, /* reset to dropped position */ }}
|
|
241
244
|
// bounds={bounds}
|
|
245
|
+
{...draggableProps}
|
|
242
246
|
>
|
|
243
247
|
<div className="ewResize" style={{ height: '100%', }}>
|
|
244
248
|
<WrappedComponent {...propsToPass} />
|
|
@@ -252,8 +256,9 @@ export default function withDraggable(WrappedComponent) {
|
|
|
252
256
|
onStart={handleStart}
|
|
253
257
|
onDrag={handleDrag}
|
|
254
258
|
onStop={handleStop}
|
|
255
|
-
|
|
259
|
+
position={{ x: 0, y: 0, /* reset to dropped position */ }}
|
|
256
260
|
handle={handle}
|
|
261
|
+
{...draggableProps}
|
|
257
262
|
>
|
|
258
263
|
<WrappedComponent {...propsToPass} />
|
|
259
264
|
</Draggable>;
|
|
@@ -47,10 +47,10 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
47
47
|
hideAlert,
|
|
48
48
|
} = props,
|
|
49
49
|
listeners = useRef({}),
|
|
50
|
+
editorStateRef = useRef(),
|
|
50
51
|
[currentRecord, setCurrentRecord] = useState(null),
|
|
51
52
|
[isEditorShown, setIsEditorShown] = useState(false),
|
|
52
53
|
[isEditorViewOnly, setIsEditorViewOnly] = useState(false),
|
|
53
|
-
[isModalShown, setIsModalShown] = useState(false),
|
|
54
54
|
[lastSelection, setLastSelection] = useState(),
|
|
55
55
|
getListeners = () => {
|
|
56
56
|
return listeners.current;
|
|
@@ -165,7 +165,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
165
165
|
await getListeners().onBeforeDeleteSave(selection);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
await Repository.delete(selection);
|
|
168
|
+
await Repository.delete(selection, moveSubtreeUp);
|
|
169
169
|
if (!Repository.isAutoSave) {
|
|
170
170
|
await Repository.save();
|
|
171
171
|
}
|
|
@@ -237,15 +237,23 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
237
237
|
await getListeners().onAfterEdit(what);
|
|
238
238
|
}
|
|
239
239
|
},
|
|
240
|
-
onEditorCancel =
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
onEditorCancel = () => {
|
|
241
|
+
async function doIt() {
|
|
242
|
+
const
|
|
243
|
+
isSingle = selection.length === 1,
|
|
244
|
+
isPhantom = selection[0] && selection[0].isPhantom;
|
|
245
|
+
if (isSingle && isPhantom) {
|
|
246
|
+
await deleteRecord();
|
|
247
|
+
}
|
|
248
|
+
setEditorMode(EDITOR_MODE__VIEW);
|
|
249
|
+
setIsEditorShown(false);
|
|
250
|
+
}
|
|
251
|
+
const formState = editorStateRef.current;
|
|
252
|
+
if (!_.isEmpty(formState.dirtyFields)) {
|
|
253
|
+
confirm('This record has unsaved changes. Are you sure you want to cancel editing? Changes will be lost.', doIt);
|
|
254
|
+
} else {
|
|
255
|
+
doIt();
|
|
246
256
|
}
|
|
247
|
-
setEditorMode(EDITOR_MODE__VIEW);
|
|
248
|
-
setIsEditorShown(false);
|
|
249
257
|
},
|
|
250
258
|
onEditorClose = () => {
|
|
251
259
|
setIsEditorShown(false);
|
|
@@ -279,6 +287,20 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
279
287
|
}
|
|
280
288
|
}
|
|
281
289
|
return mode;
|
|
290
|
+
},
|
|
291
|
+
onEditMode = () => {
|
|
292
|
+
setEditorMode(EDITOR_MODE__EDIT);
|
|
293
|
+
},
|
|
294
|
+
onViewMode = () => {
|
|
295
|
+
function doIt() {
|
|
296
|
+
setEditorMode(EDITOR_MODE__VIEW);
|
|
297
|
+
}
|
|
298
|
+
const formState = editorStateRef.current;
|
|
299
|
+
if (!_.isEmpty(formState.dirtyFields)) {
|
|
300
|
+
confirm('This record has unsaved changes. Are you sure you want to switch to "View" mode? Changes will be lost.', doIt);
|
|
301
|
+
} else {
|
|
302
|
+
doIt();
|
|
303
|
+
}
|
|
282
304
|
};
|
|
283
305
|
|
|
284
306
|
useEffect(() => {
|
|
@@ -301,7 +323,9 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
301
323
|
isEditorShown={isEditorShown}
|
|
302
324
|
isEditorViewOnly={isEditorViewOnly}
|
|
303
325
|
editorMode={editorMode}
|
|
304
|
-
|
|
326
|
+
onEditMode={onEditMode}
|
|
327
|
+
onViewMode={onViewMode}
|
|
328
|
+
editorStateRef={editorStateRef}
|
|
305
329
|
setIsEditorShown={setIsEditorShown}
|
|
306
330
|
onAdd={(!userCanEdit || disableAdd) ? null : onAdd}
|
|
307
331
|
onEdit={(!userCanEdit || disableEdit) ? null : onEdit}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef, } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Box,
|
|
3
4
|
Column,
|
|
4
5
|
Modal,
|
|
5
6
|
Row,
|
|
@@ -28,6 +29,7 @@ export default function withInlineEditor(WrappedComponent) {
|
|
|
28
29
|
onEditorCancel,
|
|
29
30
|
onEditorSave,
|
|
30
31
|
onEditorClose,
|
|
32
|
+
editorStateRef,
|
|
31
33
|
|
|
32
34
|
// withSelection
|
|
33
35
|
selection,
|
|
@@ -36,6 +38,7 @@ export default function withInlineEditor(WrappedComponent) {
|
|
|
36
38
|
Repository,
|
|
37
39
|
} = props,
|
|
38
40
|
styles = UiGlobals.styles,
|
|
41
|
+
maskRef = useRef(),
|
|
39
42
|
inlineEditorRef = useRef(),
|
|
40
43
|
[localColumnsConfig, setLocalColumnsConfig] = useState([]),
|
|
41
44
|
[currentRow, setCurrentRow] = useState(),
|
|
@@ -55,36 +58,56 @@ export default function withInlineEditor(WrappedComponent) {
|
|
|
55
58
|
moveEditor(currentRow);
|
|
56
59
|
},
|
|
57
60
|
moveEditor = (currentRow) => {
|
|
61
|
+
if (!inlineEditorRef.current) {
|
|
62
|
+
debugger;
|
|
63
|
+
}
|
|
58
64
|
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
rowBounds = currentRow.getBoundingClientRect(),
|
|
66
|
+
editor = inlineEditorRef.current,
|
|
67
|
+
editorStyle = editor.style,
|
|
68
|
+
editorBounds = editor.parentElement.getBoundingClientRect(), // reference parentElement, because this doesn't change based on last moveEditor call
|
|
69
|
+
delta = editorBounds.top - rowBounds.top;
|
|
70
|
+
|
|
71
|
+
editorStyle.top = (-1 * delta) -20 + 'px';
|
|
64
72
|
};
|
|
65
73
|
|
|
74
|
+
if (isEditorShown && selection.length < 1) {
|
|
75
|
+
throw new Error('Lost the selection!');
|
|
76
|
+
}
|
|
66
77
|
if (isEditorShown && selection.length !== 1) {
|
|
67
78
|
throw new Error('Can only edit one at a time with inline editor!');
|
|
68
79
|
}
|
|
69
80
|
if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
|
|
70
81
|
throw new Error('Not yet implemented for RN.');
|
|
71
82
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
|
|
84
|
+
let inlineEditor = null;
|
|
85
|
+
if (useEditor && Repository) {
|
|
86
|
+
inlineEditor = <>
|
|
87
|
+
{isEditorShown && <Box
|
|
88
|
+
ref={maskRef}
|
|
89
|
+
position="fixed"
|
|
90
|
+
w="100vw"
|
|
91
|
+
h="100vh"
|
|
92
|
+
top="0"
|
|
93
|
+
left="0"
|
|
94
|
+
bg="#000"
|
|
95
|
+
opacity={0.35}
|
|
96
|
+
zIndex={0}
|
|
97
|
+
onClick={(e) => {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
onEditorCancel();
|
|
101
|
+
}}
|
|
102
|
+
></Box>}
|
|
103
|
+
<Column
|
|
104
|
+
ref={inlineEditorRef}
|
|
105
|
+
position="absolute"
|
|
106
|
+
zIndex={10}
|
|
107
|
+
>
|
|
86
108
|
{isEditorShown && <Form
|
|
87
|
-
editorType={EDITOR_TYPE__INLINE}
|
|
109
|
+
editorType={EDITOR_TYPE__INLINE}
|
|
110
|
+
editorStateRef={editorStateRef}
|
|
88
111
|
record={selection[0]}
|
|
89
112
|
Repository={Repository}
|
|
90
113
|
isMultiple={selection.length > 1}
|
|
@@ -113,7 +136,15 @@ export default function withInlineEditor(WrappedComponent) {
|
|
|
113
136
|
px={0}
|
|
114
137
|
/>}
|
|
115
138
|
</Column>
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
</>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return <WrappedComponent
|
|
143
|
+
{...props}
|
|
144
|
+
onChangeColumnsConfig={onChangeColumnsConfig}
|
|
145
|
+
onEditorRowClick={onRowClick}
|
|
146
|
+
inlineEditor={inlineEditor}
|
|
147
|
+
isInlineEditorShown={isEditorShown}
|
|
148
|
+
/>;
|
|
118
149
|
});
|
|
119
150
|
}
|