@onehat/ui 0.4.25 → 0.4.27
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/Buttons/SquareButton.js +20 -16
- package/src/Components/Editor/Editor.js +5 -1
- package/src/Components/Form/Field/Tag/Tag.js +2 -2
- package/src/Components/Form/Field/Tag/ValueBox.js +19 -14
- package/src/Components/Grid/Grid.js +7 -4
- package/src/Components/Hoc/Secondary/withSecondaryEditor.js +39 -10
- package/src/Components/Hoc/Secondary/withSecondarySideEditor.js +23 -7
- package/src/Components/Hoc/Secondary/withSecondaryWindowedEditor.js +23 -17
- package/src/Components/Hoc/withModal.js +2 -1
- package/src/Components/Hoc/withPdfButtons.js +7 -1
- package/src/Components/Icons/LowPriority.js +1 -1
- package/src/Components/Screens/Manager.js +11 -1
- package/src/Components/Toolbar/PaginationToolbar.js +3 -2
- package/src/Functions/Cypress/dom_functions.js +44 -5
- package/src/Functions/testProps.js +4 -1
- package/src/Components/Window/Editor.js +0 -14
package/package.json
CHANGED
|
@@ -7,14 +7,13 @@ export default function SquareButton(props) {
|
|
|
7
7
|
const {
|
|
8
8
|
text,
|
|
9
9
|
isActive = false,
|
|
10
|
-
|
|
10
|
+
activeClassName,
|
|
11
11
|
invertColorWhenActive = false,
|
|
12
12
|
showText = true,
|
|
13
13
|
disableInteractions = false,
|
|
14
14
|
fontSize = '20px',
|
|
15
15
|
...propsToPass
|
|
16
16
|
} = props,
|
|
17
|
-
bg = isActive ? activeColor || '#56a6f8' : '#fff',
|
|
18
17
|
color = invertColorWhenActive && isActive ? '#fff' : '#000';
|
|
19
18
|
|
|
20
19
|
if (!props.icon) {
|
|
@@ -24,21 +23,26 @@ export default function SquareButton(props) {
|
|
|
24
23
|
throw Error('text missing. If you want to hide the text, use showText={false}');
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
let className = `
|
|
27
|
+
SquareButton
|
|
28
|
+
rounded-md
|
|
29
|
+
p-2
|
|
30
|
+
h-[100px]
|
|
31
|
+
w-[100px]
|
|
32
|
+
flex
|
|
33
|
+
flex-col
|
|
34
|
+
justify-center
|
|
35
|
+
items-center
|
|
36
|
+
bg-grey-200
|
|
37
|
+
hover:bg-grey-400
|
|
38
|
+
disabled:bg-grey-100
|
|
39
|
+
`;
|
|
40
|
+
if (isActive && activeClassName) {
|
|
41
|
+
className += ' ' + activeClassName;
|
|
42
|
+
}
|
|
43
|
+
|
|
27
44
|
return <IconButton
|
|
28
|
-
className={
|
|
29
|
-
SquareButton
|
|
30
|
-
rounded-md
|
|
31
|
-
p-2
|
|
32
|
-
bg-[${bg}]
|
|
33
|
-
hover:bg-[${bg}]
|
|
34
|
-
disabled:bg-[${bg}]
|
|
35
|
-
h-[100px]
|
|
36
|
-
w-[100px]
|
|
37
|
-
flex
|
|
38
|
-
flex-col
|
|
39
|
-
justify-center
|
|
40
|
-
items-center
|
|
41
|
-
`}
|
|
45
|
+
className={className}
|
|
42
46
|
style={{
|
|
43
47
|
// backgroundColor: bg,
|
|
44
48
|
}}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EDITOR_MODE__VIEW,
|
|
3
|
+
EDITOR_TYPE__SIDE,
|
|
3
4
|
} from '../../Constants/Editor.js';
|
|
4
5
|
import withComponent from '../Hoc/withComponent.js';
|
|
5
6
|
import withPdfButtons from '../Hoc/withPdfButtons.js';
|
|
@@ -34,7 +35,10 @@ function Editor(props) {
|
|
|
34
35
|
return null; // hide the editor when no selection
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
const propsToPass = _.omit(props, ['self', 'reference', 'parent']);
|
|
38
|
+
const propsToPass = _.omit(props, ['self', 'reference', 'parent', 'style']);
|
|
39
|
+
if (propsToPass.editorType === EDITOR_TYPE__SIDE) {
|
|
40
|
+
propsToPass.style = props.style; // side editor needs the style prop, but a windowed editor can get messed up if it's present (and withModal is used)!
|
|
41
|
+
}
|
|
38
42
|
|
|
39
43
|
let canEdit = true;
|
|
40
44
|
if (canRecordBeEdited && !canRecordBeEdited(selection)) {
|
|
@@ -77,7 +77,6 @@ function TagComponent(props) {
|
|
|
77
77
|
showModal({
|
|
78
78
|
body: <Editor
|
|
79
79
|
editorType={EDITOR_TYPE__WINDOWED}
|
|
80
|
-
{...propsToPass}
|
|
81
80
|
parent={self}
|
|
82
81
|
reference="viewer"
|
|
83
82
|
isEditorViewOnly={true}
|
|
@@ -234,6 +233,7 @@ function TagComponent(props) {
|
|
|
234
233
|
onView={() => onView(val)}
|
|
235
234
|
onDelete={!isViewOnly ? () => onDelete(val) : null}
|
|
236
235
|
showEye={showEye}
|
|
236
|
+
minimizeForRow={minimizeForRow}
|
|
237
237
|
/>;
|
|
238
238
|
});
|
|
239
239
|
|
|
@@ -297,7 +297,7 @@ function TagComponent(props) {
|
|
|
297
297
|
valueBoxesClassName += ' min-h-[25px] h-full overflow-auto flex-1';
|
|
298
298
|
} else {
|
|
299
299
|
// shrink both down
|
|
300
|
-
valueBoxesClassName += ' h-auto min-h-[25px] max-h-[
|
|
300
|
+
valueBoxesClassName += ' Scott h-auto min-h-[25px] max-h-[35px] overflow-auto flex-1';
|
|
301
301
|
comboClassName += ' h-auto min-h-0 max-h-[25px] flex-1';
|
|
302
302
|
}
|
|
303
303
|
}
|
|
@@ -15,6 +15,7 @@ export default function ValueBox(props) {
|
|
|
15
15
|
onView,
|
|
16
16
|
onDelete,
|
|
17
17
|
showEye,
|
|
18
|
+
minimizeForRow = false,
|
|
18
19
|
} = props,
|
|
19
20
|
styles = UiGlobals.styles;
|
|
20
21
|
return <HStackNative
|
|
@@ -31,20 +32,22 @@ export default function ValueBox(props) {
|
|
|
31
32
|
${!onDelete && 'pr-4'}
|
|
32
33
|
`}
|
|
33
34
|
>
|
|
34
|
-
{showEye &&
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
{showEye &&
|
|
36
|
+
<IconButton
|
|
37
|
+
{...testProps('eyeBtn')}
|
|
38
|
+
icon={Eye}
|
|
39
|
+
_icon={{
|
|
40
|
+
size: styles.FORM_TAG_VALUEBOX_ICON_SIZE,
|
|
41
|
+
className: 'text-grey-600',
|
|
42
|
+
}}
|
|
43
|
+
onPress={onView}
|
|
44
|
+
className={`
|
|
45
|
+
ValueBox-eyeBtn
|
|
46
|
+
h-full
|
|
47
|
+
${minimizeForRow ? 'py-0' : ''}
|
|
48
|
+
${styles.FORM_TAG_BTN_CLASSNAME}
|
|
49
|
+
`}
|
|
50
|
+
/>}
|
|
48
51
|
<Text
|
|
49
52
|
className={`
|
|
50
53
|
ValueBox-Text
|
|
@@ -52,6 +55,7 @@ export default function ValueBox(props) {
|
|
|
52
55
|
${styles.FORM_TAG_VALUEBOX_CLASSNAME}
|
|
53
56
|
${showEye ? 'ml-0' : 'ml-1'}
|
|
54
57
|
${onDelete ? 'mr-0' : 'mr-1'}
|
|
58
|
+
${minimizeForRow ? 'py-0' : ''}
|
|
55
59
|
`}
|
|
56
60
|
>{text}</Text>
|
|
57
61
|
{onDelete &&
|
|
@@ -66,6 +70,7 @@ export default function ValueBox(props) {
|
|
|
66
70
|
className={`
|
|
67
71
|
ValueBox-xBtn
|
|
68
72
|
h-full
|
|
73
|
+
${minimizeForRow ? 'py-0' : ''}
|
|
69
74
|
${styles.FORM_TAG_BTN_CLASSNAME}
|
|
70
75
|
`}
|
|
71
76
|
/>}
|
|
@@ -153,6 +153,7 @@ function GridComponent(props) {
|
|
|
153
153
|
alternateRowBackgrounds = true,
|
|
154
154
|
alternatingInterval = 2,
|
|
155
155
|
defaultRowHeight = 48,
|
|
156
|
+
getRowTestId,
|
|
156
157
|
|
|
157
158
|
// The selectorSelected mechanism allows us to filter results of the primary model, (e.g. WorkOrders)
|
|
158
159
|
// by the selection on the secondary model (e.g. Equipment). It's used on Grids, Trees, Forms, etc.
|
|
@@ -390,7 +391,7 @@ function GridComponent(props) {
|
|
|
390
391
|
|
|
391
392
|
let rowComponent =
|
|
392
393
|
<Pressable
|
|
393
|
-
{...testProps((Repository ? Repository.schema.name : 'GridRow') + '-' + item?.id)}
|
|
394
|
+
{...testProps(getRowTestId ? getRowTestId(row) : ((Repository ? Repository.schema.name : 'GridRow') + '-' + item?.id))}
|
|
394
395
|
onPress={(e) => {
|
|
395
396
|
if (e.preventDefault && e.cancelable) {
|
|
396
397
|
e.preventDefault();
|
|
@@ -416,7 +417,7 @@ function GridComponent(props) {
|
|
|
416
417
|
if (canUser && !canUser(VIEW)) { // permissions
|
|
417
418
|
return;
|
|
418
419
|
}
|
|
419
|
-
onView(
|
|
420
|
+
onView(!props.isEditorViewOnly);
|
|
420
421
|
}
|
|
421
422
|
} else {
|
|
422
423
|
if (onEdit) {
|
|
@@ -597,6 +598,7 @@ function GridComponent(props) {
|
|
|
597
598
|
`}
|
|
598
599
|
>
|
|
599
600
|
<ExpandButton
|
|
601
|
+
{...testProps((Repository ? Repository.schema.name : 'GridRow') + '-expandBtn-' + item?.id)}
|
|
600
602
|
isExpanded={isExpanded}
|
|
601
603
|
onToggle={() => setIsExpanded(index, !isExpanded)}
|
|
602
604
|
_icon={{
|
|
@@ -1272,7 +1274,8 @@ function GridComponent(props) {
|
|
|
1272
1274
|
</VStackNative>
|
|
1273
1275
|
|
|
1274
1276
|
if (isDropTarget) {
|
|
1275
|
-
grid = <
|
|
1277
|
+
grid = <VStackNative
|
|
1278
|
+
{...testProps(self, '-dropTarget')}
|
|
1276
1279
|
ref={dropTargetRef}
|
|
1277
1280
|
className={`
|
|
1278
1281
|
Grid-dropTarget
|
|
@@ -1281,7 +1284,7 @@ function GridComponent(props) {
|
|
|
1281
1284
|
border-[#0ff]
|
|
1282
1285
|
${canDrop && isOver ? "border-[4px]" : "border-[0px]"}
|
|
1283
1286
|
`}
|
|
1284
|
-
>{grid}</
|
|
1287
|
+
>{grid}</VStackNative>
|
|
1285
1288
|
}
|
|
1286
1289
|
return grid;
|
|
1287
1290
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState, useRef, } from 'react';
|
|
1
|
+
import { forwardRef, useEffect, useState, useRef, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
ADD,
|
|
4
4
|
EDIT,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
EDITOR_MODE__ADD,
|
|
12
12
|
EDITOR_MODE__EDIT,
|
|
13
13
|
EDITOR_TYPE__SIDE,
|
|
14
|
+
EDITOR_TYPE__INLINE,
|
|
14
15
|
} from '../../../Constants/Editor.js';
|
|
15
16
|
import Button from '../../Buttons/Button.js';
|
|
16
17
|
import UiGlobals from '../../../UiGlobals.js';
|
|
@@ -20,10 +21,10 @@ import _ from 'lodash';
|
|
|
20
21
|
// This HOC will eventually get out of sync with that one, and may need to be updated.
|
|
21
22
|
|
|
22
23
|
export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
23
|
-
return (props) => {
|
|
24
|
+
return forwardRef((props, ref) => {
|
|
24
25
|
|
|
25
26
|
if (props.secondaryDisableWithEditor) {
|
|
26
|
-
return <WrappedComponent {...props} isTree={isTree} />;
|
|
27
|
+
return <WrappedComponent {...props} ref={ref} isTree={isTree} />;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
let [secondaryEditorMode, secondarySetEditorMode] = useState(EDITOR_MODE__VIEW); // Can change below, so use 'let'
|
|
@@ -52,6 +53,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
52
53
|
secondaryNewEntityDisplayValue,
|
|
53
54
|
secondaryNewEntityDisplayProperty, // in case the field to set for newEntityDisplayValue is different from model
|
|
54
55
|
secondaryDefaultValues,
|
|
56
|
+
secondaryStayInEditModeOnSelectionChange = false,
|
|
55
57
|
|
|
56
58
|
// withComponent
|
|
57
59
|
self,
|
|
@@ -132,7 +134,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
132
134
|
// NOTE: This is a hack to prevent adding a new record while the repository is still loading.
|
|
133
135
|
// This can happen when the repository is still loading, and the user clicks the 'Add' button.
|
|
134
136
|
setTimeout(() => {
|
|
135
|
-
|
|
137
|
+
secondaryDoAdd(e, values);
|
|
136
138
|
}, 500);
|
|
137
139
|
return;
|
|
138
140
|
}
|
|
@@ -169,7 +171,9 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
169
171
|
if (!secondarySelection[0]) {
|
|
170
172
|
throw Error('Must select a parent node.');
|
|
171
173
|
}
|
|
172
|
-
|
|
174
|
+
const parent = secondarySelection[0];
|
|
175
|
+
addValues.parentId = parent.id;
|
|
176
|
+
addValues.depth = parent.depth +1;
|
|
173
177
|
} else {
|
|
174
178
|
// Set repository to sort by id DESC and switch to page 1, so this new entity is guaranteed to show up on the current page, even after saving
|
|
175
179
|
const currentSorter = SecondaryRepository.sorters[0];
|
|
@@ -200,10 +204,13 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
200
204
|
setIsSaving(false);
|
|
201
205
|
setSecondaryIsIgnoreNextSelectionChange(true);
|
|
202
206
|
secondarySetSelection([entity]);
|
|
207
|
+
if (getListeners().onAfterAdd) {
|
|
208
|
+
await getListeners().onAfterAdd(entity);
|
|
209
|
+
}
|
|
203
210
|
if (SecondaryRepository.isAutoSave) {
|
|
204
211
|
// for isAutoSave Repositories, submit the handers right away
|
|
205
|
-
if (getListeners().
|
|
206
|
-
await getListeners().
|
|
212
|
+
if (getListeners().onAfterAddSave) {
|
|
213
|
+
await getListeners().onAfterAddSave(entity);
|
|
207
214
|
}
|
|
208
215
|
if (secondaryOnAdd) {
|
|
209
216
|
await secondaryOnAdd(entity);
|
|
@@ -331,6 +338,13 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
331
338
|
showPermissionsError(VIEW, secondaryModel);
|
|
332
339
|
return;
|
|
333
340
|
}
|
|
341
|
+
if (secondaryEditorType === EDITOR_TYPE__INLINE) {
|
|
342
|
+
alert('Cannot view in inline editor.');
|
|
343
|
+
return; // inline editor doesn't have a view mode
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// check permissions for view
|
|
347
|
+
|
|
334
348
|
if (secondarySelection.length !== 1) {
|
|
335
349
|
return;
|
|
336
350
|
}
|
|
@@ -350,6 +364,10 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
350
364
|
showPermissionsError(DUPLICATE, secondaryModel);
|
|
351
365
|
return;
|
|
352
366
|
}
|
|
367
|
+
|
|
368
|
+
// check permissions for duplicate
|
|
369
|
+
|
|
370
|
+
|
|
353
371
|
if (secondarySelection.length !== 1) {
|
|
354
372
|
return;
|
|
355
373
|
}
|
|
@@ -436,8 +454,8 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
436
454
|
if (secondaryOnAdd) {
|
|
437
455
|
await secondaryOnAdd(secondarySelection);
|
|
438
456
|
}
|
|
439
|
-
if (getListeners().
|
|
440
|
-
await getListeners().
|
|
457
|
+
if (getListeners().onAfterAddSave) {
|
|
458
|
+
await getListeners().onAfterAddSave(secondarySelection);
|
|
441
459
|
}
|
|
442
460
|
setIsAdding(false);
|
|
443
461
|
if (!canUser || canUser(EDIT, secondaryModel)) {
|
|
@@ -500,6 +518,16 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
500
518
|
});
|
|
501
519
|
},
|
|
502
520
|
calculateEditorMode = (secondaryIsIgnoreNextSelectionChange = false) => {
|
|
521
|
+
|
|
522
|
+
let doStayInEditModeOnSelectionChange = secondaryStayInEditModeOnSelectionChange;
|
|
523
|
+
if (!_.isNil(UiGlobals.stayInEditModeOnSelectionChange)) {
|
|
524
|
+
// allow global override to for this property
|
|
525
|
+
doStayInEditModeOnSelectionChange = UiGlobals.stayInEditModeOnSelectionChange;
|
|
526
|
+
}
|
|
527
|
+
if (doStayInEditModeOnSelectionChange) {
|
|
528
|
+
secondaryIsIgnoreNextSelectionChange = true;
|
|
529
|
+
}
|
|
530
|
+
|
|
503
531
|
// calculateEditorMode gets called only on selection changes
|
|
504
532
|
let mode;
|
|
505
533
|
if (secondaryEditorType === EDITOR_TYPE__SIDE && !_.isNil(UiGlobals.isSideEditorAlwaysEditMode) && UiGlobals.isSideEditorAlwaysEditMode) {
|
|
@@ -579,6 +607,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
579
607
|
|
|
580
608
|
return <WrappedComponent
|
|
581
609
|
{...props}
|
|
610
|
+
ref={ref}
|
|
582
611
|
secondaryDisableWithEditor={false}
|
|
583
612
|
secondaryCurrentRecord={secondaryCurrentRecord}
|
|
584
613
|
secondarySetCurrentRecord={secondarySetCurrentRecord}
|
|
@@ -612,5 +641,5 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
|
|
|
612
641
|
secondarySetSelection={secondarySetSelectionDecorated}
|
|
613
642
|
isTree={isTree}
|
|
614
643
|
/>;
|
|
615
|
-
};
|
|
644
|
+
});
|
|
616
645
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
1
2
|
import {
|
|
2
3
|
EDITOR_TYPE__SIDE,
|
|
3
4
|
} from '../../../Constants/Editor.js';
|
|
@@ -10,20 +11,21 @@ import _ from 'lodash';
|
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
function withAdditionalProps(WrappedComponent) {
|
|
13
|
-
return (props) => {
|
|
14
|
+
return forwardRef((props, ref) => {
|
|
14
15
|
// provide the editorType to withEditor
|
|
15
16
|
return <WrappedComponent
|
|
16
17
|
editorType={EDITOR_TYPE__SIDE}
|
|
17
18
|
{...props}
|
|
19
|
+
ref={ref}
|
|
18
20
|
/>;
|
|
19
|
-
};
|
|
21
|
+
});
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
// NOTE: Effectivtly, the HOC composition is:
|
|
23
25
|
// withAdditionalProps(withSecondaryEditor(withSecondarySideEditor))
|
|
24
26
|
|
|
25
27
|
export default function withSecondarySideEditor(WrappedComponent, isTree = false) {
|
|
26
|
-
|
|
28
|
+
const SideEditor = forwardRef((props, ref) => {
|
|
27
29
|
const {
|
|
28
30
|
SecondaryEditor,
|
|
29
31
|
secondaryEditorProps = {},
|
|
@@ -36,6 +38,7 @@ export default function withSecondarySideEditor(WrappedComponent, isTree = false
|
|
|
36
38
|
secondarySelectorId,
|
|
37
39
|
secondarySelectorSelected,
|
|
38
40
|
secondarySelectorSelectedField,
|
|
41
|
+
style,
|
|
39
42
|
|
|
40
43
|
...propsToPass
|
|
41
44
|
} = props;
|
|
@@ -44,8 +47,23 @@ export default function withSecondarySideEditor(WrappedComponent, isTree = false
|
|
|
44
47
|
throw Error('SecondaryEditor is not defined');
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
if (isResizable) {
|
|
51
|
+
secondaryEditorProps.w = 500;
|
|
52
|
+
secondaryEditorProps.isResizable = true;
|
|
53
|
+
} else {
|
|
54
|
+
secondaryEditorProps.flex = secondarySideFlex;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!secondaryEditorProps.className) {
|
|
58
|
+
secondaryEditorProps.className = '';
|
|
59
|
+
}
|
|
60
|
+
secondaryEditorProps.className += ' border-l-1 border-l-grey-300';
|
|
61
|
+
|
|
47
62
|
return <Container
|
|
63
|
+
parent={self}
|
|
64
|
+
reference="SideEditor"
|
|
48
65
|
center={<WrappedComponent
|
|
66
|
+
ref={ref}
|
|
49
67
|
isTree={isTree}
|
|
50
68
|
isSideEditor={true}
|
|
51
69
|
{...props}
|
|
@@ -53,13 +71,11 @@ export default function withSecondarySideEditor(WrappedComponent, isTree = false
|
|
|
53
71
|
east={<Editor
|
|
54
72
|
{...propsToPass}
|
|
55
73
|
editorType={EDITOR_TYPE__SIDE}
|
|
56
|
-
flex={secondarySideFlex}
|
|
57
|
-
borderLeftWidth={1}
|
|
58
|
-
borderLeftColor="#ccc"
|
|
59
74
|
{...secondaryEditorProps}
|
|
60
75
|
parent={self}
|
|
61
76
|
reference="secondaryEditor"
|
|
62
77
|
/>}
|
|
63
78
|
/>;
|
|
64
|
-
})
|
|
79
|
+
});
|
|
80
|
+
return withAdditionalProps(withSecondaryEditor(SideEditor, isTree));
|
|
65
81
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
1
2
|
import {
|
|
2
3
|
Modal, ModalBackdrop, ModalHeader, ModalContent, ModalCloseButton, ModalBody, ModalFooter,
|
|
3
4
|
} from '@project-components/Gluestack';
|
|
@@ -13,20 +14,21 @@ import _ from 'lodash';
|
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
function withAdditionalProps(WrappedComponent) {
|
|
16
|
-
return (props) => {
|
|
17
|
+
return forwardRef((props, ref) => {
|
|
17
18
|
// provide the editorType to withEditor
|
|
18
19
|
return <WrappedComponent
|
|
19
20
|
editorType={EDITOR_TYPE__WINDOWED}
|
|
20
21
|
{...props}
|
|
22
|
+
ref={ref}
|
|
21
23
|
/>;
|
|
22
|
-
};
|
|
24
|
+
});
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
// NOTE: Effectivtly, the HOC composition is:
|
|
26
28
|
// withAdditionalProps(withSecondaryEditor(withSecondaryWindowedEditor))
|
|
27
29
|
|
|
28
30
|
export default function withSecondaryWindowedEditor(WrappedComponent, isTree = false) {
|
|
29
|
-
|
|
31
|
+
const WindowedEditor = forwardRef((props, ref) => {
|
|
30
32
|
const {
|
|
31
33
|
secondaryIsEditorShown = false,
|
|
32
34
|
secondarySetIsEditorShown,
|
|
@@ -41,6 +43,7 @@ export default function withSecondaryWindowedEditor(WrappedComponent, isTree = f
|
|
|
41
43
|
secondarySelectorSelected,
|
|
42
44
|
secondarySelectorSelectedField,
|
|
43
45
|
h,
|
|
46
|
+
style,
|
|
44
47
|
|
|
45
48
|
...propsToPass
|
|
46
49
|
} = props;
|
|
@@ -65,25 +68,28 @@ export default function withSecondaryWindowedEditor(WrappedComponent, isTree = f
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
return <>
|
|
68
|
-
<WrappedComponent {...props} />
|
|
71
|
+
<WrappedComponent {...props} ref={ref} />
|
|
69
72
|
{secondaryIsEditorShown &&
|
|
70
73
|
<Modal
|
|
71
74
|
isOpen={true}
|
|
72
75
|
onClose={() => secondarySetIsEditorShown(false)}
|
|
76
|
+
className="withSecondaryEditor-Modal"
|
|
73
77
|
>
|
|
74
|
-
<ModalBackdrop />
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
<ModalBackdrop className="withSecondaryEditor-ModalBackdrop" />
|
|
79
|
+
<SecondaryEditor
|
|
80
|
+
editorType={EDITOR_TYPE__WINDOWED}
|
|
81
|
+
{...propsToPass}
|
|
82
|
+
{...secondaryEditorProps}
|
|
83
|
+
parent={self}
|
|
84
|
+
reference="secondaryEditor"
|
|
85
|
+
className={`
|
|
86
|
+
bg-white
|
|
87
|
+
shadow-lg
|
|
88
|
+
rounded-lg
|
|
89
|
+
`}
|
|
90
|
+
/>
|
|
86
91
|
</Modal>}
|
|
87
92
|
</>;
|
|
88
|
-
}
|
|
93
|
+
});
|
|
94
|
+
return withAdditionalProps(withSecondaryEditor(WindowedEditor, isTree));
|
|
89
95
|
}
|
|
@@ -163,13 +163,14 @@ export default function withModal(WrappedComponent) {
|
|
|
163
163
|
<Panel
|
|
164
164
|
title={title}
|
|
165
165
|
isCollapsible={false}
|
|
166
|
-
className="bg-white
|
|
166
|
+
className="withModal-Panel bg-white"
|
|
167
167
|
h={h > windowHeight ? windowHeight : h}
|
|
168
168
|
w={w > windowWidth ? windowWidth : w}
|
|
169
169
|
isWindow={true}
|
|
170
170
|
disableAutoFlex={true}
|
|
171
171
|
onClose={canClose ? hideModal : null}
|
|
172
172
|
footer={footer}
|
|
173
|
+
isScrollable={true}
|
|
173
174
|
>{modalBody}</Panel>
|
|
174
175
|
}
|
|
175
176
|
}
|
|
@@ -83,7 +83,13 @@ export default function withPdfButtons(WrappedComponent) {
|
|
|
83
83
|
|
|
84
84
|
if (!_.isEmpty(ancillaryItems)) {
|
|
85
85
|
const
|
|
86
|
-
ancillaryItemsClone = _.
|
|
86
|
+
ancillaryItemsClone = _.cloneDeepWith(ancillaryItems, (value) => {
|
|
87
|
+
// Exclude the 'parent' property from being cloned, as it would introduce an infinitely recursive loop
|
|
88
|
+
if (value && value.parent) {
|
|
89
|
+
const { parent, ...rest } = value;
|
|
90
|
+
return rest;
|
|
91
|
+
}
|
|
92
|
+
}),
|
|
87
93
|
items = [];
|
|
88
94
|
_.each(ancillaryItemsClone, (ancillaryItem) => { // clone, as we don't want to alter the item by reference
|
|
89
95
|
let name;
|
|
@@ -3,7 +3,7 @@ import { Path, Svg } from 'react-native-svg';
|
|
|
3
3
|
|
|
4
4
|
const SvgComponent = createIcon({
|
|
5
5
|
Root: Svg,
|
|
6
|
-
viewBox: '0 0
|
|
6
|
+
viewBox: '0 0 101.44 83.8',
|
|
7
7
|
path: <Path d="M58.92 4.5L99.9 68.86c4.12 6.47-.53 14.94-8.2 14.94H9.74c-7.67 0-12.32-8.47-8.2-14.94L42.52 4.5c3.82-6 12.58-6 16.4 0zm-8.2 68.21c3.24 0 5.34-2.34 5.34-5.46-.06-3.18-2.16-5.46-5.34-5.46s-5.4 2.28-5.4 5.46 2.16 5.46 5.4 5.46zm3.42-13.92l1.32-27.18h-9.54l1.38 27.18h6.84z" strokeWidth={0} />
|
|
8
8
|
});
|
|
9
9
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HStack,
|
|
3
|
+
Icon,
|
|
3
4
|
Text,
|
|
4
5
|
VStackNative,
|
|
5
6
|
} from '@project-components/Gluestack';
|
|
@@ -98,7 +99,16 @@ function ManagerScreen(props) {
|
|
|
98
99
|
className="max-h-screen overflow-hidden flex-1 w-full"
|
|
99
100
|
>
|
|
100
101
|
<HStack className="h-[80px] items-center border-b-[2px] border-b-[#ccc]">
|
|
101
|
-
|
|
102
|
+
{props.icon ?
|
|
103
|
+
<Icon
|
|
104
|
+
as={props.icon}
|
|
105
|
+
className={`
|
|
106
|
+
ml-5
|
|
107
|
+
`}
|
|
108
|
+
size="xl"
|
|
109
|
+
color="#000"
|
|
110
|
+
/> : null}
|
|
111
|
+
<Text {...textProps} className="pl-4 text-[26px] font-[700]">{title}</Text>
|
|
102
112
|
{allowSideBySide &&
|
|
103
113
|
<>
|
|
104
114
|
<IconButton
|
|
@@ -47,8 +47,9 @@ export default function PaginationToolbar(props) {
|
|
|
47
47
|
minimize={minimize}
|
|
48
48
|
disablePageSize={disablePageSize}
|
|
49
49
|
/>
|
|
50
|
-
{toolbarItems.length
|
|
50
|
+
{toolbarItems.length ?
|
|
51
51
|
<HStack className={`
|
|
52
|
+
PaginationToolbar-HStack
|
|
52
53
|
flex-1
|
|
53
54
|
space-x-1
|
|
54
55
|
border-l
|
|
@@ -56,6 +57,6 @@ export default function PaginationToolbar(props) {
|
|
|
56
57
|
ml-3
|
|
57
58
|
pl-3
|
|
58
59
|
`}
|
|
59
|
-
>{toolbarItems}</HStack>}
|
|
60
|
+
>{toolbarItems}</HStack> : null}
|
|
60
61
|
</Toolbar>;
|
|
61
62
|
};
|
|
@@ -24,9 +24,11 @@ export function getDomNodes(selectors, options = {}) {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Builds selector string for data-testid attributes.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* It leaves classname, id, and attribute selectors unchanged.
|
|
28
|
+
*
|
|
29
|
+
* If selectors is an array, these will be considered nested selectors.
|
|
29
30
|
* e.g. ['parent', 'child'] will be converted to '[data-testid="parent"] [data-testid="child"]'
|
|
31
|
+
* @argument {string|string[]} selectors - data-testid attribute values
|
|
30
32
|
* @return {string}
|
|
31
33
|
*/
|
|
32
34
|
export function getTestIdSelectors(selectors, isGetFirst = false) {
|
|
@@ -34,10 +36,47 @@ export function getTestIdSelectors(selectors, isGetFirst = false) {
|
|
|
34
36
|
selectors = [selectors];
|
|
35
37
|
}
|
|
36
38
|
const selectorParts = _.map(selectors, (selector) => {
|
|
37
|
-
if (selector.match(
|
|
38
|
-
|
|
39
|
+
if (!selector.match(/^\./) // className, like .my-class
|
|
40
|
+
&& !selector.match(/^#/) // id, like @my-id
|
|
41
|
+
&& !selector.match(/=/) // attribute, like [role="switch"]
|
|
42
|
+
){
|
|
43
|
+
selector = '[data-testid="' + selector + '"]';
|
|
44
|
+
}
|
|
45
|
+
if (isGetFirst) {
|
|
46
|
+
selector += ':first';
|
|
39
47
|
}
|
|
40
|
-
return
|
|
48
|
+
return selector;
|
|
41
49
|
});
|
|
42
50
|
return selectorParts.join(' ');
|
|
43
51
|
}
|
|
52
|
+
|
|
53
|
+
export function drag(draggableSelectors, droppableSelectors, options = {}) {
|
|
54
|
+
if (typeof options.force === 'undefined') {
|
|
55
|
+
options.force = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// getDomNode(getTestIdSelectors(droppableSelectors)).then((node) => {
|
|
59
|
+
// const selectors = getTestIdSelectors(droppableSelectors);
|
|
60
|
+
// debugger;
|
|
61
|
+
// });
|
|
62
|
+
|
|
63
|
+
options = {
|
|
64
|
+
source: { // applies to the element being dragged
|
|
65
|
+
x: 10,
|
|
66
|
+
// y: 100,
|
|
67
|
+
position: 'left',
|
|
68
|
+
},
|
|
69
|
+
target: { // applies to the drop target
|
|
70
|
+
position: 'left',
|
|
71
|
+
x: 20,
|
|
72
|
+
},
|
|
73
|
+
force: true, // applied to both the source and target element
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
return getDomNode(draggableSelectors)
|
|
78
|
+
.drag(getTestIdSelectors(droppableSelectors), options)
|
|
79
|
+
.then((success) => {
|
|
80
|
+
debugger;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -4,7 +4,7 @@ import UiGlobals from '../UiGlobals.js';
|
|
|
4
4
|
// This adds a data-testid attribute to the DOM node,
|
|
5
5
|
// which can be quried in Cypress by: document.querySelector(`[data-testid='MyTestId']`);
|
|
6
6
|
|
|
7
|
-
export default function testProps(id) {
|
|
7
|
+
export default function testProps(id, suffix) {
|
|
8
8
|
if (!UiGlobals.debugMode) {
|
|
9
9
|
return {};
|
|
10
10
|
}
|
|
@@ -19,6 +19,9 @@ export default function testProps(id) {
|
|
|
19
19
|
if (id.match(/\s/g)) {
|
|
20
20
|
id = id.replace(/\s/g, '_'); // convert any spaces to underscores
|
|
21
21
|
}
|
|
22
|
+
if (suffix) {
|
|
23
|
+
id += suffix; // this is used in conjunction with 'self' object
|
|
24
|
+
}
|
|
22
25
|
if (!window && Platform.OS === 'android') {
|
|
23
26
|
return {
|
|
24
27
|
accessibilityLabel: id,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import Container from '../Container/Container.js';
|
|
2
|
-
import emptyFn from '../../Functions/emptyFn.js';
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
|
|
5
|
-
export default function EditorWindow(props) {
|
|
6
|
-
const {
|
|
7
|
-
title,
|
|
8
|
-
isOpen = false,
|
|
9
|
-
onClose = emptyFn,
|
|
10
|
-
...propsToPass
|
|
11
|
-
} = props;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|