@onehat/ui 0.3.68 → 0.3.70
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/Filter/DateRange.js +8 -2
- package/src/Components/Form/Field/Combo/Combo.js +67 -42
- package/src/Components/Form/Field/Date.js +389 -156
- package/src/Components/Hoc/withEditor.js +4 -40
- package/src/Components/Messages/Loading.js +6 -6
- package/src/Functions/processImage.js +2 -2
- package/src/Functions/registerReactNativeComponents.js +2 -0
- package/src/Functions/registerWebComponents.js +2 -0
- package/src/Hooks/useAdjustedWindowSize.js +4 -2
- package/src/PlatformImports/ReactNative/Datetime.js +3 -2
- package/src/PlatformImports/ReactNative/useWindowSize.js +4 -0
- package/src/{Hooks → PlatformImports/Web}/useWindowSize.js +0 -1
package/package.json
CHANGED
|
@@ -24,6 +24,7 @@ const
|
|
|
24
24
|
} = props,
|
|
25
25
|
[low, setLow] = useState(''),
|
|
26
26
|
[high, setHigh] = useState(''),
|
|
27
|
+
[isReady, setIsReady] = useState(false),
|
|
27
28
|
onChangeLow = (value) => {
|
|
28
29
|
setLow(value);
|
|
29
30
|
const newValue = {
|
|
@@ -59,9 +60,16 @@ const
|
|
|
59
60
|
if (value.high !== high) {
|
|
60
61
|
setHigh(value.high);
|
|
61
62
|
}
|
|
63
|
+
if (!isReady) {
|
|
64
|
+
setIsReady(true);
|
|
65
|
+
}
|
|
62
66
|
|
|
63
67
|
}, [value]);
|
|
64
68
|
|
|
69
|
+
if (!isReady) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
return <Row
|
|
66
74
|
justifyContent="center"
|
|
67
75
|
alignItems="center"
|
|
@@ -72,7 +80,6 @@ const
|
|
|
72
80
|
value={low}
|
|
73
81
|
onChangeValue={onChangeLow}
|
|
74
82
|
mode={mode}
|
|
75
|
-
startingValue={null}
|
|
76
83
|
// minValue={minValue}
|
|
77
84
|
// maxValue={maxValue}
|
|
78
85
|
tooltip={(tooltip ? tooltip + ' ' : '') + 'Low'}
|
|
@@ -82,7 +89,6 @@ const
|
|
|
82
89
|
value={high}
|
|
83
90
|
onChangeValue={onChangeHigh}
|
|
84
91
|
mode={mode}
|
|
85
|
-
startingValue={null}
|
|
86
92
|
// minValue={minValue}
|
|
87
93
|
// maxValue={maxValue}
|
|
88
94
|
tooltip={(tooltip ? tooltip + ' ' : '') + 'High'}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef, } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Button,
|
|
3
4
|
Modal,
|
|
4
5
|
Popover,
|
|
5
6
|
Pressable,
|
|
@@ -21,6 +22,7 @@ import emptyFn from '../../../../Functions/emptyFn.js';
|
|
|
21
22
|
import { Grid, WindowedGridEditor } from '../../../Grid/Grid.js';
|
|
22
23
|
import IconButton from '../../../Buttons/IconButton.js';
|
|
23
24
|
import CaretDown from '../../../Icons/CaretDown.js';
|
|
25
|
+
import Check from '../../../Icons/Check.js';
|
|
24
26
|
import Xmark from '../../../Icons/Xmark.js';
|
|
25
27
|
import _ from 'lodash';
|
|
26
28
|
|
|
@@ -70,6 +72,7 @@ export function ComboComponent(props) {
|
|
|
70
72
|
[gridSelection, setGridSelection] = useState(null),
|
|
71
73
|
[textInputValue, setTextInputValue] = useState(''),
|
|
72
74
|
[newEntityDisplayValue, setNewEntityDisplayValue] = useState(null),
|
|
75
|
+
[filteredData, setFilteredData] = useState(data),
|
|
73
76
|
[width, setWidth] = useState(0),
|
|
74
77
|
[top, setTop] = useState(0),
|
|
75
78
|
[left, setLeft] = useState(0),
|
|
@@ -129,6 +132,7 @@ export function ComboComponent(props) {
|
|
|
129
132
|
displayValue = [];
|
|
130
133
|
if (Repository) {
|
|
131
134
|
if (!Repository.isLoaded) {
|
|
135
|
+
debugger;
|
|
132
136
|
throw Error('Not yet implemented'); // Would a Combo ever have multiple remote selections? Shouldn't that be a Tag field??
|
|
133
137
|
}
|
|
134
138
|
if (Repository.isLoading) {
|
|
@@ -168,9 +172,9 @@ export function ComboComponent(props) {
|
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
displayValueRef.current = displayValue;
|
|
171
|
-
|
|
175
|
+
resetTextInputValue();
|
|
172
176
|
},
|
|
173
|
-
|
|
177
|
+
resetTextInputValue = () => {
|
|
174
178
|
setTextInputValue(getDisplayValue());
|
|
175
179
|
},
|
|
176
180
|
onInputKeyPress = (e, inputValue) => {
|
|
@@ -180,7 +184,7 @@ export function ComboComponent(props) {
|
|
|
180
184
|
switch(e.key) {
|
|
181
185
|
case 'Escape':
|
|
182
186
|
setIsSearchMode(false);
|
|
183
|
-
|
|
187
|
+
resetTextInputValue();
|
|
184
188
|
hideMenu();
|
|
185
189
|
break;
|
|
186
190
|
case 'Enter':
|
|
@@ -245,8 +249,8 @@ export function ComboComponent(props) {
|
|
|
245
249
|
}, 300);
|
|
246
250
|
},
|
|
247
251
|
onInputFocus = (e) => {
|
|
248
|
-
if (inputRef.current
|
|
249
|
-
inputRef.current
|
|
252
|
+
if (inputRef.current?.select) {
|
|
253
|
+
inputRef.current?.select();
|
|
250
254
|
}
|
|
251
255
|
},
|
|
252
256
|
onInputBlur = (e) => {
|
|
@@ -256,7 +260,7 @@ export function ComboComponent(props) {
|
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
setIsSearchMode(false);
|
|
259
|
-
|
|
263
|
+
resetTextInputValue();
|
|
260
264
|
hideMenu();
|
|
261
265
|
},
|
|
262
266
|
onTriggerPress = (e) => {
|
|
@@ -277,7 +281,7 @@ export function ComboComponent(props) {
|
|
|
277
281
|
}
|
|
278
282
|
|
|
279
283
|
setIsSearchMode(false);
|
|
280
|
-
|
|
284
|
+
resetTextInputValue();
|
|
281
285
|
hideMenu();
|
|
282
286
|
},
|
|
283
287
|
onClearBtn = () => {
|
|
@@ -303,7 +307,7 @@ export function ComboComponent(props) {
|
|
|
303
307
|
}
|
|
304
308
|
|
|
305
309
|
// clear filter
|
|
306
|
-
if (Repository.isRemote) {
|
|
310
|
+
if (Repository.isRemote || Repository.remote) {
|
|
307
311
|
let searchField = 'q';
|
|
308
312
|
const searchValue = null;
|
|
309
313
|
|
|
@@ -316,18 +320,20 @@ export function ComboComponent(props) {
|
|
|
316
320
|
searchField = displayFieldName + ' LIKE';
|
|
317
321
|
}
|
|
318
322
|
|
|
319
|
-
Repository.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
+
if (Repository.hasFilter(searchField)) {
|
|
324
|
+
Repository.clear();
|
|
325
|
+
await Repository.filter(searchField, searchValue);
|
|
326
|
+
if (!this.isAutoLoad) {
|
|
327
|
+
await Repository.reload();
|
|
328
|
+
}
|
|
323
329
|
}
|
|
324
330
|
|
|
325
331
|
} else {
|
|
326
|
-
|
|
332
|
+
Repository.clear();
|
|
327
333
|
}
|
|
328
334
|
|
|
329
335
|
} else {
|
|
330
|
-
|
|
336
|
+
setFilteredData(data);
|
|
331
337
|
}
|
|
332
338
|
},
|
|
333
339
|
searchForMatches = async (value) => {
|
|
@@ -339,21 +345,26 @@ export function ComboComponent(props) {
|
|
|
339
345
|
|
|
340
346
|
let found;
|
|
341
347
|
if (Repository) {
|
|
348
|
+
|
|
349
|
+
if (_.isEmpty(value) && Repository.hasFilters) {
|
|
350
|
+
Repository.clearFilters();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
342
354
|
if (Repository.isLoading) {
|
|
343
355
|
await Repository.waitUntilDoneLoading();
|
|
344
356
|
}
|
|
345
357
|
|
|
346
358
|
// Set filter
|
|
347
|
-
let filter = {};
|
|
348
359
|
if (Repository.isRemote) {
|
|
349
|
-
let searchField = 'q';
|
|
350
|
-
const searchValue = _.isEmpty(value) ? null : value + '%';
|
|
351
|
-
|
|
352
|
-
// Check to see if displayField is a real field
|
|
353
360
|
const
|
|
354
361
|
schema = Repository.getSchema(),
|
|
355
362
|
displayFieldName = schema.model.displayProperty,
|
|
356
|
-
displayFieldDef = schema.getPropertyDefinition(displayFieldName)
|
|
363
|
+
displayFieldDef = schema.getPropertyDefinition(displayFieldName),
|
|
364
|
+
searchValue = _.isEmpty(value) ? null : value + '%';
|
|
365
|
+
let searchField = 'q';
|
|
366
|
+
|
|
367
|
+
// Verify displayField is a real field
|
|
357
368
|
if (!displayFieldDef.isVirtual) {
|
|
358
369
|
searchField = displayFieldName + ' LIKE';
|
|
359
370
|
}
|
|
@@ -362,39 +373,28 @@ export function ComboComponent(props) {
|
|
|
362
373
|
if (!this.isAutoLoad) {
|
|
363
374
|
await Repository.reload();
|
|
364
375
|
}
|
|
365
|
-
|
|
366
376
|
} else {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
// Fuzzy search with getBy filter function
|
|
370
|
-
filter = (entity) => {
|
|
377
|
+
// local filter
|
|
378
|
+
Repository.filter((entity) => {
|
|
371
379
|
const
|
|
372
380
|
displayValue = entity.displayValue,
|
|
373
381
|
regex = new RegExp('^' + value);
|
|
374
382
|
return displayValue.match(regex);
|
|
375
|
-
};
|
|
376
|
-
Repository.filter(filter);
|
|
383
|
+
});
|
|
377
384
|
}
|
|
378
385
|
|
|
379
386
|
setNewEntityDisplayValue(value); // capture the search query so we can tell Grid what to use for a new entity's displayValue
|
|
380
387
|
|
|
381
388
|
} else {
|
|
382
|
-
|
|
383
|
-
throw Error('Not yet implemented'); // NOTE: When implementing this, also implement clearGridFilters
|
|
384
|
-
|
|
385
389
|
// Search through data
|
|
386
|
-
|
|
390
|
+
const regex = new RegExp('^' + value);
|
|
391
|
+
found = _.filter(data, (item) => {
|
|
387
392
|
if (_.isString(item[displayIx]) && _.isString(value)) {
|
|
388
|
-
return item[displayIx].
|
|
393
|
+
return item[displayIx].match(regex);
|
|
389
394
|
}
|
|
390
|
-
return item[displayIx]
|
|
395
|
+
return item[displayIx] == value; // equality, not identity
|
|
391
396
|
});
|
|
392
|
-
|
|
393
|
-
// const
|
|
394
|
-
// newSelection = [found];
|
|
395
|
-
|
|
396
|
-
// setTextInputValue(newTextValue);
|
|
397
|
-
// }
|
|
397
|
+
setFilteredData(found);
|
|
398
398
|
}
|
|
399
399
|
};
|
|
400
400
|
|
|
@@ -429,6 +429,7 @@ export function ComboComponent(props) {
|
|
|
429
429
|
|
|
430
430
|
let xButton = null,
|
|
431
431
|
inputAndTrigger = null,
|
|
432
|
+
checkBtn = null,
|
|
432
433
|
grid = null,
|
|
433
434
|
dropdownMenu = null,
|
|
434
435
|
assembledComponents = null;
|
|
@@ -588,7 +589,7 @@ export function ComboComponent(props) {
|
|
|
588
589
|
'Editor',
|
|
589
590
|
'model',
|
|
590
591
|
'Repository',
|
|
591
|
-
'data',
|
|
592
|
+
// 'data',
|
|
592
593
|
'idIx',
|
|
593
594
|
'displayIx',
|
|
594
595
|
'value',
|
|
@@ -614,6 +615,7 @@ export function ComboComponent(props) {
|
|
|
614
615
|
}}
|
|
615
616
|
autoAdjustPageSizeToHeight={false}
|
|
616
617
|
{...gridProps}
|
|
618
|
+
data={filteredData}
|
|
617
619
|
reference="dropdownGrid"
|
|
618
620
|
parent={self}
|
|
619
621
|
h={UiGlobals.mode === UI_MODE_WEB ? styles.FORM_COMBO_MENU_HEIGHT + 'px' : null}
|
|
@@ -638,7 +640,7 @@ export function ComboComponent(props) {
|
|
|
638
640
|
// when user selected the record matching the current value, kill search mode
|
|
639
641
|
if (selection[0]?.id === value) {
|
|
640
642
|
setIsSearchMode(false);
|
|
641
|
-
|
|
643
|
+
resetTextInputValue();
|
|
642
644
|
if (hideMenuOnSelection) {
|
|
643
645
|
hideMenu();
|
|
644
646
|
}
|
|
@@ -657,7 +659,7 @@ export function ComboComponent(props) {
|
|
|
657
659
|
// when user selected the record matching the current value, kill search mode
|
|
658
660
|
if (selection[0] && selection[0][idIx] === value) {
|
|
659
661
|
setIsSearchMode(false);
|
|
660
|
-
|
|
662
|
+
resetTextInputValue();
|
|
661
663
|
if (hideMenuOnSelection) {
|
|
662
664
|
hideMenu();
|
|
663
665
|
}
|
|
@@ -735,6 +737,27 @@ export function ComboComponent(props) {
|
|
|
735
737
|
</Popover>;
|
|
736
738
|
}
|
|
737
739
|
if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
|
|
740
|
+
if (isEditor) {
|
|
741
|
+
// in RN, an editor has no way to accept the selection of the grid, so we need to add a check button to do this
|
|
742
|
+
const isCheckBtnDisabled = _.isEmpty(value);
|
|
743
|
+
checkBtn = <IconButton
|
|
744
|
+
_icon={{
|
|
745
|
+
as: Check,
|
|
746
|
+
color: isCheckBtnDisabled ? 'disabled' : 'trueGray.600',
|
|
747
|
+
size: 'sm',
|
|
748
|
+
}}
|
|
749
|
+
isDisabled={isCheckBtnDisabled}
|
|
750
|
+
onPress={acceptSelection}
|
|
751
|
+
h="100%"
|
|
752
|
+
borderWidth={1}
|
|
753
|
+
borderColor="#bbb"
|
|
754
|
+
borderRadius="md"
|
|
755
|
+
bg={styles.FORM_COMBO_TRIGGER_BG}
|
|
756
|
+
_hover={{
|
|
757
|
+
bg: styles.FORM_COMBO_TRIGGER_HOVER_BG,
|
|
758
|
+
}}
|
|
759
|
+
/>;
|
|
760
|
+
}
|
|
738
761
|
const inputAndTriggerClone = // for RN, this is the actual input and trigger, as we need them to appear up above in the modal
|
|
739
762
|
<Row h={10}>
|
|
740
763
|
{disableDirectEntry ?
|
|
@@ -798,6 +821,7 @@ export function ComboComponent(props) {
|
|
|
798
821
|
bg: styles.FORM_COMBO_TRIGGER_HOVER_BG,
|
|
799
822
|
}}
|
|
800
823
|
/>
|
|
824
|
+
{checkBtn}
|
|
801
825
|
</Row>;
|
|
802
826
|
dropdownMenu = <Modal
|
|
803
827
|
isOpen={true}
|
|
@@ -811,6 +835,7 @@ export function ComboComponent(props) {
|
|
|
811
835
|
>
|
|
812
836
|
{inputAndTriggerClone}
|
|
813
837
|
{grid}
|
|
838
|
+
<Button mt={2} onPress={() => setIsMenuShown(false)}>Close</Button>
|
|
814
839
|
</Modal>;
|
|
815
840
|
}
|
|
816
841
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef, } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Box,
|
|
3
4
|
Icon,
|
|
5
|
+
Modal,
|
|
4
6
|
Popover,
|
|
5
7
|
Pressable,
|
|
6
8
|
Row,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
DATETIME,
|
|
14
16
|
} from '../../../Constants/Date.js';
|
|
15
17
|
import {
|
|
18
|
+
UI_MODE_REACT_NATIVE,
|
|
16
19
|
UI_MODE_WEB,
|
|
17
20
|
} from '../../../Constants/UiModes.js';
|
|
18
21
|
import UiGlobals from '../../../UiGlobals.js';
|
|
@@ -20,24 +23,36 @@ import Formatters from '@onehat/data/src/Util/Formatters.js';
|
|
|
20
23
|
import Parsers from '@onehat/data/src/Util/Parsers.js';
|
|
21
24
|
import Input from '../Field/Input.js';
|
|
22
25
|
import IconButton from '../../Buttons/IconButton.js';
|
|
26
|
+
import Xmark from '../../Icons/Xmark.js';
|
|
23
27
|
import withComponent from '../../Hoc/withComponent.js';
|
|
24
28
|
import withValue from '../../Hoc/withValue.js';
|
|
25
29
|
import emptyFn from '../../../Functions/emptyFn.js';
|
|
26
30
|
import Calendar from '../../Icons/Calendar.js';
|
|
27
31
|
import getComponentFromType from '../../../Functions/getComponentFromType.js';
|
|
32
|
+
import moment from 'moment';
|
|
28
33
|
import _ from 'lodash';
|
|
29
34
|
|
|
30
35
|
|
|
31
36
|
export function DateElement(props) {
|
|
32
37
|
const {
|
|
33
|
-
placeholderText,
|
|
34
|
-
value,
|
|
35
|
-
setValue,
|
|
36
38
|
format,
|
|
37
39
|
mode = DATE,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
|
|
41
|
+
additionalButtons,
|
|
42
|
+
tooltipRef = null,
|
|
43
|
+
tooltip = null,
|
|
44
|
+
menuMinWidth = 150,
|
|
45
|
+
disableDirectEntry = false,
|
|
46
|
+
hideMenuOnSelection = true,
|
|
47
|
+
showXButton = false,
|
|
48
|
+
_input = {},
|
|
40
49
|
isDisabled = false,
|
|
50
|
+
tooltipPlacement = 'bottom',
|
|
51
|
+
placeholder = 'Choose a date.',
|
|
52
|
+
|
|
53
|
+
// withValue
|
|
54
|
+
value,
|
|
55
|
+
setValue,
|
|
41
56
|
} = props,
|
|
42
57
|
styles = UiGlobals.styles,
|
|
43
58
|
Datetime = getComponentFromType('Datetime'),
|
|
@@ -46,6 +61,7 @@ export function DateElement(props) {
|
|
|
46
61
|
pickerRef = useRef(),
|
|
47
62
|
[isPickerShown, setIsPickerShown] = useState(false),
|
|
48
63
|
[isRendered, setIsRendered] = useState(false),
|
|
64
|
+
[textInputValue, setTextInputValue] = useState(value),
|
|
49
65
|
[isTranslateX, setIsTranslateX] = useState(false),
|
|
50
66
|
[isTranslateY, setIsTranslateY] = useState(false),
|
|
51
67
|
[top, setTop] = useState(0),
|
|
@@ -83,7 +99,16 @@ export function DateElement(props) {
|
|
|
83
99
|
}
|
|
84
100
|
setIsPickerShown(false);
|
|
85
101
|
},
|
|
86
|
-
|
|
102
|
+
togglePicker = () => {
|
|
103
|
+
setIsPickerShown(!isPickerShown);
|
|
104
|
+
},
|
|
105
|
+
onInputKeyPress = (e, inputValue) => {
|
|
106
|
+
if (disableDirectEntry) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (UiGlobals.mode !== UI_MODE_WEB) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
87
112
|
switch(e.key) {
|
|
88
113
|
case 'Escape':
|
|
89
114
|
case 'Enter':
|
|
@@ -93,13 +118,16 @@ export function DateElement(props) {
|
|
|
93
118
|
}
|
|
94
119
|
},
|
|
95
120
|
onInputBlur = (e) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
121
|
+
// if (UiGlobals.mode !== UI_MODE_WEB) {
|
|
122
|
+
// return;
|
|
123
|
+
// }
|
|
124
|
+
// const {
|
|
125
|
+
// relatedTarget
|
|
126
|
+
// } = e;
|
|
127
|
+
// if (!relatedTarget ||
|
|
128
|
+
// (!inputRef.current.contains(relatedTarget) && triggerRef.current !== relatedTarget && (!pickerRef.current || !pickerRef.current.contains(relatedTarget)))) {
|
|
129
|
+
// // hidePicker();
|
|
130
|
+
// }
|
|
103
131
|
},
|
|
104
132
|
onInputClick = (e) => {
|
|
105
133
|
if (!isRendered) {
|
|
@@ -107,9 +135,13 @@ export function DateElement(props) {
|
|
|
107
135
|
}
|
|
108
136
|
showPicker();
|
|
109
137
|
},
|
|
110
|
-
|
|
111
|
-
if (
|
|
138
|
+
onInputChangeText = (value) => {
|
|
139
|
+
if (disableDirectEntry) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (_.isEmpty(value)) {
|
|
112
143
|
setValue(null);
|
|
144
|
+
setTextInputValue('');
|
|
113
145
|
return;
|
|
114
146
|
}
|
|
115
147
|
switch(mode) {
|
|
@@ -133,7 +165,20 @@ export function DateElement(props) {
|
|
|
133
165
|
break;
|
|
134
166
|
default:
|
|
135
167
|
}
|
|
136
|
-
|
|
168
|
+
|
|
169
|
+
if (value !== 'Invalid date') {
|
|
170
|
+
setValue(value);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
setTextInputValue(value);
|
|
174
|
+
if (!isPickerShown) {
|
|
175
|
+
showPicker();
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
onInputFocus = (e) => {
|
|
179
|
+
if (inputRef.current?.select) {
|
|
180
|
+
inputRef.current?.select();
|
|
181
|
+
}
|
|
137
182
|
},
|
|
138
183
|
onTriggerPress = (e) => {
|
|
139
184
|
if (!isRendered) {
|
|
@@ -144,10 +189,10 @@ export function DateElement(props) {
|
|
|
144
189
|
} else {
|
|
145
190
|
showPicker();
|
|
146
191
|
}
|
|
147
|
-
inputRef.current
|
|
192
|
+
inputRef.current?.focus();
|
|
148
193
|
},
|
|
149
194
|
onTriggerBlur = (e) => {
|
|
150
|
-
if (!isPickerShown) {
|
|
195
|
+
if (!isPickerShown || UiGlobals.mode !== UI_MODE_WEB) {
|
|
151
196
|
return;
|
|
152
197
|
}
|
|
153
198
|
const {
|
|
@@ -172,28 +217,15 @@ export function DateElement(props) {
|
|
|
172
217
|
break;
|
|
173
218
|
default:
|
|
174
219
|
}
|
|
175
|
-
setValue(value);
|
|
176
|
-
};
|
|
177
220
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
translateProps = {};
|
|
183
|
-
if (isTranslateX) {
|
|
184
|
-
translateParts.push('translateX(-100%)');
|
|
185
|
-
}
|
|
186
|
-
if (isTranslateY) {
|
|
187
|
-
translateParts.push('translateY(-100%)');
|
|
188
|
-
}
|
|
189
|
-
if (!_.isEmpty(translateParts)) {
|
|
190
|
-
translateProps.style = {
|
|
191
|
-
transform: translateParts.join(' '),
|
|
221
|
+
if (moment && moment?.isValid()) {
|
|
222
|
+
setValue(value);
|
|
223
|
+
setTextInputValue(value);
|
|
224
|
+
}
|
|
192
225
|
};
|
|
193
|
-
|
|
194
|
-
|
|
226
|
+
|
|
195
227
|
// Format the display date/time/datetime
|
|
196
|
-
let title =
|
|
228
|
+
let title = placeholder,
|
|
197
229
|
pickerValue = null,
|
|
198
230
|
height = 300,
|
|
199
231
|
width = 300;
|
|
@@ -226,147 +258,348 @@ export function DateElement(props) {
|
|
|
226
258
|
pickerValue = pickerValue.toDate();
|
|
227
259
|
}
|
|
228
260
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
261
|
+
let xButton = null,
|
|
262
|
+
inputAndTrigger = null,
|
|
263
|
+
grid = null,
|
|
264
|
+
dropdownMenu = null,
|
|
265
|
+
assembledComponents = null;
|
|
266
|
+
|
|
267
|
+
if (showXButton && !_.isNil(value)) {
|
|
268
|
+
xButton = <IconButton
|
|
269
|
+
_icon={{
|
|
270
|
+
as: Xmark,
|
|
271
|
+
color: 'trueGray.600',
|
|
272
|
+
size: 'sm',
|
|
273
|
+
}}
|
|
239
274
|
isDisabled={isDisabled}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
borderBottomRightRadius={0}
|
|
244
|
-
bg={styles.FORM_DATE_ICON_BG}
|
|
275
|
+
onPress={onClearBtn}
|
|
276
|
+
h="100%"
|
|
277
|
+
bg={styles.FORM_COMBO_TRIGGER_BG}
|
|
245
278
|
_hover={{
|
|
246
|
-
bg: styles.
|
|
279
|
+
bg: styles.FORM_COMBO_TRIGGER_HOVER_BG,
|
|
247
280
|
}}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
281
|
+
/>;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (UiGlobals.mode === UI_MODE_WEB) {
|
|
285
|
+
inputAndTrigger = <>
|
|
286
|
+
<IconButton
|
|
287
|
+
ref={triggerRef}
|
|
288
|
+
_icon={{
|
|
289
|
+
as: Calendar,
|
|
290
|
+
color: styles.FORM_DATE_ICON_COLOR,
|
|
291
|
+
size: 'sm',
|
|
292
|
+
}}
|
|
293
|
+
onPress={onTriggerPress}
|
|
294
|
+
onBlur={onTriggerBlur}
|
|
295
|
+
h={10}
|
|
296
|
+
w={10}
|
|
297
|
+
isDisabled={isDisabled}
|
|
298
|
+
borderWidth={1}
|
|
299
|
+
borderColor="#bbb"
|
|
300
|
+
borderLeftRadius="md"
|
|
301
|
+
borderRighttRadius={0}
|
|
302
|
+
bg={styles.FORM_DATE_ICON_BG}
|
|
303
|
+
_hover={{
|
|
304
|
+
bg: styles.FORM_DATE_ICON_BG_HOVER,
|
|
305
|
+
}}
|
|
306
|
+
/>
|
|
307
|
+
{disableDirectEntry ?
|
|
308
|
+
<Pressable
|
|
309
|
+
onPress={togglePicker}
|
|
310
|
+
flex={1}
|
|
311
|
+
h="100%"
|
|
312
|
+
>
|
|
313
|
+
<Text
|
|
314
|
+
ref={inputRef}
|
|
315
|
+
flex={1}
|
|
316
|
+
h="100%"
|
|
317
|
+
numberOfLines={1}
|
|
318
|
+
ellipsizeMode="head"
|
|
319
|
+
m={0}
|
|
320
|
+
p={2}
|
|
321
|
+
borderWidth={1}
|
|
322
|
+
borderColor="trueGray.400"
|
|
323
|
+
borderLeftWidth={0}
|
|
324
|
+
borderLeftRadius={0}
|
|
325
|
+
borderRightRadius="md"
|
|
326
|
+
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
327
|
+
color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
|
|
328
|
+
bg={styles.FORM_DATE_INPUT_BG}
|
|
329
|
+
_focus={{
|
|
330
|
+
bg: styles.FORM_DATE_INPUT_FOCUS_BG,
|
|
331
|
+
}}
|
|
332
|
+
>{_.isEmpty(textInputValue) ? placeholder : textInputValue}</Text>
|
|
333
|
+
</Pressable> :
|
|
334
|
+
<Input
|
|
335
|
+
ref={inputRef}
|
|
336
|
+
value={textInputValue}
|
|
337
|
+
// setValue={onInputSetValue}
|
|
338
|
+
onChangeValue={onInputChangeText}
|
|
339
|
+
onKeyPress={onInputKeyPress}
|
|
340
|
+
onBlur={onInputBlur}
|
|
341
|
+
onFocus={onInputFocus}
|
|
342
|
+
autoSubmit={true}
|
|
343
|
+
isDisabled={isDisabled}
|
|
344
|
+
// onLayout={(e) => {
|
|
345
|
+
// const {
|
|
346
|
+
// height,
|
|
347
|
+
// width,
|
|
348
|
+
// } = e.nativeEvent.layout;
|
|
349
|
+
// setWidth(Math.round(width));
|
|
350
|
+
// setTop(Math.round(height));
|
|
351
|
+
// }}
|
|
352
|
+
flex={1}
|
|
353
|
+
h="100%"
|
|
354
|
+
m={0}
|
|
355
|
+
autoSubmitDelay={1000}
|
|
356
|
+
borderTopRightRadius={0}
|
|
357
|
+
borderBottomRightRadius={0}
|
|
358
|
+
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
359
|
+
color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
|
|
360
|
+
bg={styles.FORM_DATE_INPUT_BG}
|
|
361
|
+
_focus={{
|
|
362
|
+
bg: styles.FORM_DATE_INPUT_FOCUS_BG,
|
|
363
|
+
}}
|
|
364
|
+
placeholder={placeholder}
|
|
365
|
+
{..._input}
|
|
366
|
+
/>}
|
|
367
|
+
</>;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
|
|
371
|
+
// This input and trigger are for show
|
|
372
|
+
// The just show the current value and open the menu
|
|
373
|
+
inputAndTrigger = <>
|
|
374
|
+
<IconButton
|
|
375
|
+
ref={triggerRef}
|
|
376
|
+
_icon={{
|
|
377
|
+
as: Calendar,
|
|
378
|
+
color: styles.FORM_DATE_ICON_COLOR,
|
|
379
|
+
size: 'sm',
|
|
380
|
+
}}
|
|
381
|
+
isDisabled={isDisabled}
|
|
382
|
+
onPress={onTriggerPress}
|
|
383
|
+
onBlur={onTriggerBlur}
|
|
384
|
+
h="100%"
|
|
385
|
+
w={10}
|
|
386
|
+
borderWidth={1}
|
|
387
|
+
borderColor="#bbb"
|
|
388
|
+
borderLeftRadius="md"
|
|
389
|
+
borderRightWidth={0}
|
|
390
|
+
borderRighttRadius={0}
|
|
391
|
+
bg={styles.FORM_DATE_ICON_BG}
|
|
392
|
+
_hover={{
|
|
393
|
+
bg: styles.FORM_DATE_ICON_BG_HOVER,
|
|
394
|
+
}}
|
|
395
|
+
/>
|
|
396
|
+
<Pressable
|
|
397
|
+
onPress={togglePicker}
|
|
398
|
+
flex={1}
|
|
399
|
+
>
|
|
400
|
+
<Text
|
|
401
|
+
flex={1}
|
|
402
|
+
h="100%"
|
|
403
|
+
numberOfLines={1}
|
|
404
|
+
ellipsizeMode="head"
|
|
405
|
+
m={0}
|
|
406
|
+
p={2}
|
|
407
|
+
borderWidth={1}
|
|
408
|
+
borderColor="trueGray.400"
|
|
409
|
+
borderLeftWidth={0}
|
|
410
|
+
borderLeftRadius={0}
|
|
411
|
+
borderRightRadius="md"
|
|
412
|
+
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
413
|
+
color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
|
|
414
|
+
bg={styles.FORM_DATE_INPUT_BG}
|
|
415
|
+
_focus={{
|
|
416
|
+
bg: styles.FORM_DATE_INPUT_FOCUS_BG,
|
|
417
|
+
}}
|
|
418
|
+
>{_.isEmpty(textInputValue) ? placeholder : textInputValue}</Text>
|
|
419
|
+
</Pressable>
|
|
420
|
+
</>;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (isPickerShown) {
|
|
424
|
+
if (UiGlobals.mode === UI_MODE_WEB) {
|
|
425
|
+
|
|
426
|
+
// place the picker in a convenient spot
|
|
427
|
+
const
|
|
428
|
+
translateParts = [],
|
|
429
|
+
translateProps = {};
|
|
430
|
+
if (isTranslateX) {
|
|
431
|
+
translateParts.push('translateX(-100%)');
|
|
432
|
+
}
|
|
433
|
+
if (isTranslateY) {
|
|
434
|
+
translateParts.push('translateY(-100%)');
|
|
435
|
+
}
|
|
436
|
+
if (!_.isEmpty(translateParts)) {
|
|
437
|
+
translateProps.style = {
|
|
438
|
+
transform: translateParts.join(' '),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
dropdownMenu = <Popover
|
|
442
|
+
isOpen={isPickerShown}
|
|
443
|
+
onClose={() => {
|
|
444
|
+
hidePicker();
|
|
445
|
+
}}
|
|
446
|
+
trigger={emptyFn}
|
|
447
|
+
trapFocus={false}
|
|
448
|
+
placement={'auto'}
|
|
449
|
+
{...props}
|
|
450
|
+
>
|
|
451
|
+
<Popover.Content
|
|
452
|
+
position="absolute"
|
|
453
|
+
top={top + 'px'}
|
|
454
|
+
left={left + 'px'}
|
|
455
|
+
w={width + 'px'}
|
|
456
|
+
minWidth={menuMinWidth}
|
|
457
|
+
overflow="auto"
|
|
458
|
+
bg="#fff"
|
|
459
|
+
{...translateProps}
|
|
460
|
+
>
|
|
461
|
+
<Popover.Body
|
|
462
|
+
ref={pickerRef}
|
|
463
|
+
borderWidth={1}
|
|
464
|
+
borderColor='trueGray.400'
|
|
465
|
+
borderTopWidth={0}
|
|
466
|
+
p={0}
|
|
467
|
+
>
|
|
468
|
+
<Datetime
|
|
469
|
+
open={true}
|
|
470
|
+
input={false}
|
|
471
|
+
closeOnClickOutside={false}
|
|
472
|
+
value={pickerValue}
|
|
473
|
+
dateFormat={mode === DATE || mode === DATETIME ? 'YYYY-MM-DD' : false}
|
|
474
|
+
timeFormat={mode === TIME || mode === DATETIME ? 'HH:mm:ss' : false}
|
|
475
|
+
onChange={onPickerChange}
|
|
476
|
+
/>
|
|
477
|
+
</Popover.Body>
|
|
478
|
+
</Popover.Content>
|
|
479
|
+
</Popover>;
|
|
480
|
+
}
|
|
481
|
+
if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
|
|
482
|
+
const inputAndTriggerClone = // for RN, this is the actual input and trigger, as we need them to appear up above in the modal
|
|
483
|
+
<Row h={10}>
|
|
484
|
+
<IconButton
|
|
485
|
+
_icon={{
|
|
486
|
+
as: Calendar,
|
|
487
|
+
color: styles.FORM_DATE_ICON_COLOR,
|
|
488
|
+
size: 'sm',
|
|
270
489
|
}}
|
|
271
490
|
isDisabled={isDisabled}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
491
|
+
onPress={() => hidePicker()}
|
|
492
|
+
h="100%"
|
|
493
|
+
w={10}
|
|
494
|
+
borderWidth={1}
|
|
495
|
+
borderColor="#bbb"
|
|
496
|
+
borderLeftRadius="md"
|
|
497
|
+
borderRightWidth={0}
|
|
498
|
+
borderRighttRadius={0}
|
|
499
|
+
bg={styles.FORM_DATE_ICON_BG}
|
|
500
|
+
_hover={{
|
|
501
|
+
bg: styles.FORM_DATE_ICON_BG_HOVER,
|
|
283
502
|
}}
|
|
284
|
-
w={props.w || null}
|
|
285
503
|
/>
|
|
286
|
-
{
|
|
287
|
-
flex={1}
|
|
288
|
-
h="100%"
|
|
289
|
-
onPress={showPicker}
|
|
290
|
-
>
|
|
504
|
+
{disableDirectEntry ?
|
|
291
505
|
<Text
|
|
506
|
+
ref={inputRef}
|
|
292
507
|
flex={1}
|
|
293
508
|
h="100%"
|
|
294
|
-
ml={1}
|
|
295
|
-
p={2}
|
|
296
|
-
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
297
|
-
borderWidth={1}
|
|
298
|
-
borderColor="trueGray.300"
|
|
299
|
-
borderRadius={4}
|
|
300
509
|
numberOfLines={1}
|
|
301
510
|
ellipsizeMode="head"
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
511
|
+
m={0}
|
|
512
|
+
p={2}
|
|
513
|
+
borderWidth={1}
|
|
514
|
+
borderColor="trueGray.400"
|
|
515
|
+
borderLeftWidth={0}
|
|
516
|
+
borderLeftRadius={0}
|
|
517
|
+
borderRightRadius="md"
|
|
518
|
+
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
519
|
+
color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
|
|
520
|
+
bg={styles.FORM_DATE_INPUT_BG}
|
|
521
|
+
_focus={{
|
|
522
|
+
bg: styles.FORM_DATE_INPUT_FOCUS_BG,
|
|
523
|
+
}}
|
|
524
|
+
>{textInputValue}</Text> :
|
|
525
|
+
<Input
|
|
526
|
+
ref={inputRef}
|
|
527
|
+
value={textInputValue}
|
|
528
|
+
autoSubmit={true}
|
|
529
|
+
isDisabled={isDisabled}
|
|
530
|
+
onChangeValue={onInputChangeText}
|
|
531
|
+
onKeyPress={onInputKeyPress}
|
|
532
|
+
onFocus={onInputFocus}
|
|
533
|
+
onBlur={onInputBlur}
|
|
534
|
+
flex={1}
|
|
535
|
+
h="100%"
|
|
536
|
+
m={0}
|
|
537
|
+
autoSubmitDelay={1000}
|
|
538
|
+
borderTopRightRadius={0}
|
|
539
|
+
borderBottomRightRadius={0}
|
|
540
|
+
fontSize={styles.FORM_DATE_READOUT_FONTSIZE}
|
|
541
|
+
color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
|
|
542
|
+
bg={styles.FORM_DATE_INPUT_BG}
|
|
543
|
+
_focus={{
|
|
544
|
+
bg: styles.FORM_DATE_INPUT_FOCUS_BG,
|
|
545
|
+
}}
|
|
546
|
+
placeholder={placeholder}
|
|
547
|
+
{..._input}
|
|
548
|
+
/>}
|
|
549
|
+
</Row>;
|
|
550
|
+
dropdownMenu = <Modal
|
|
551
|
+
isOpen={true}
|
|
552
|
+
safeAreaTop={true}
|
|
553
|
+
onClose={() => setIsPickerShown(false)}
|
|
554
|
+
mt="auto"
|
|
555
|
+
mb="auto"
|
|
556
|
+
w="100%"
|
|
557
|
+
h={400}
|
|
558
|
+
p={5}
|
|
325
559
|
>
|
|
326
|
-
|
|
560
|
+
{inputAndTriggerClone}
|
|
561
|
+
{/* <Datetime
|
|
327
562
|
open={true}
|
|
328
563
|
input={false}
|
|
564
|
+
mode={mode === DATE ? 'date' : mode === TIME ? 'time' : mode === DATETIME ? 'datetime' : null}
|
|
329
565
|
closeOnClickOutside={false}
|
|
330
566
|
value={pickerValue}
|
|
331
567
|
dateFormat={mode === DATE || mode === DATETIME ? 'YYYY-MM-DD' : false}
|
|
332
568
|
timeFormat={mode === TIME || mode === DATETIME ? 'HH:mm:ss' : false}
|
|
333
569
|
onChange={onPickerChange}
|
|
334
|
-
/>
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
570
|
+
/> */}
|
|
571
|
+
<Box bg="#fff">
|
|
572
|
+
<Datetime
|
|
573
|
+
selectedStartDate={moment(value).toDate()}
|
|
574
|
+
onDateChange={onPickerChange}
|
|
575
|
+
todayBackgroundColor="#eee"
|
|
576
|
+
selectedDayColor="#f00"
|
|
577
|
+
selectedDayTextColor="#fff"
|
|
578
|
+
/>
|
|
579
|
+
</Box>
|
|
580
|
+
</Modal>;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
340
583
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
// }}
|
|
352
|
-
// {...propsToPass}
|
|
353
|
-
// />}
|
|
354
|
-
// </Row>;
|
|
584
|
+
const refProps = {};
|
|
585
|
+
if (tooltipRef) {
|
|
586
|
+
refProps.ref = tooltipRef;
|
|
587
|
+
}
|
|
588
|
+
assembledComponents = <Row {...refProps} justifyContent="center" alignItems="center" h={styles.FORM_COMBO_HEIGHT} flex={1} onLayout={() => setIsRendered(true)}>
|
|
589
|
+
{xButton}
|
|
590
|
+
{inputAndTrigger}
|
|
591
|
+
{additionalButtons}
|
|
592
|
+
{dropdownMenu}
|
|
593
|
+
</Row>;
|
|
355
594
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
// mode="date"
|
|
365
|
-
// onConfirm={handleConfirm}
|
|
366
|
-
// onCancel={hidePicker}
|
|
367
|
-
// {...propsToPass}
|
|
368
|
-
// />
|
|
369
|
-
// </Box>;
|
|
595
|
+
if (tooltip) {
|
|
596
|
+
assembledComponents = <Tooltip label={tooltip} placement={tooltipPlacement}>
|
|
597
|
+
{assembledComponents}
|
|
598
|
+
</Tooltip>;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
return assembledComponents;
|
|
602
|
+
|
|
370
603
|
};
|
|
371
604
|
|
|
372
605
|
export default withComponent(withValue(DateElement));
|
|
@@ -265,48 +265,12 @@ export default function withEditor(WrappedComponent, isTree = false) {
|
|
|
265
265
|
setIsEditorShown(true);
|
|
266
266
|
},
|
|
267
267
|
onRemoteDuplicate = async () => {
|
|
268
|
-
|
|
269
|
-
// Call /duplicate on server
|
|
270
|
-
const
|
|
271
|
-
Model = Repository.getSchema().name,
|
|
268
|
+
const
|
|
272
269
|
entity = selection[0],
|
|
273
|
-
|
|
274
|
-
const result = await Repository._send('POST', Model + '/duplicate', { id });
|
|
275
|
-
if (!result) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const {
|
|
279
|
-
root,
|
|
280
|
-
success,
|
|
281
|
-
total,
|
|
282
|
-
message
|
|
283
|
-
} = Repository._processServerResponse(result);
|
|
284
|
-
|
|
285
|
-
if (!success) {
|
|
286
|
-
throw Error(message);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const duplicateId = root.id;
|
|
290
|
-
|
|
291
|
-
// TODO: I don't like this.
|
|
292
|
-
// Currently, we filter the repository by only the new Entity, then select the entity for editing.
|
|
293
|
-
// There is a 2-second delay between filtering and being able to select, and this is unacceptable.
|
|
294
|
-
// Why do we filter for just the new entity? Because it's not guaranteed to show up in the grid based on sorting.
|
|
295
|
-
// Can't we just manually add this record to the repository at the top and then edit it?
|
|
296
|
-
|
|
297
|
-
// Filter the grid with only the duplicate's ID, and open it for editing.
|
|
298
|
-
self.filterById(duplicateId, () => { // because of the way useFilters is made, we have to use a callback, not await a Promise.
|
|
299
|
-
|
|
300
|
-
// Select the only node
|
|
301
|
-
const duplicateEntity = Repository.getById(duplicateId);
|
|
302
|
-
setTimeout(() => {
|
|
303
|
-
setSelection([duplicateEntity]);
|
|
304
|
-
|
|
305
|
-
onEdit();
|
|
306
|
-
}, 2000); // we need this delay!
|
|
307
|
-
|
|
308
|
-
});
|
|
270
|
+
duplicateEntity = await Repository.remoteDuplicate(entity);
|
|
309
271
|
|
|
272
|
+
setSelection([duplicateEntity]);
|
|
273
|
+
onEdit();
|
|
310
274
|
},
|
|
311
275
|
onEditorSave = async (data, e) => {
|
|
312
276
|
const
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
Row,
|
|
3
3
|
Spinner,
|
|
4
4
|
} from 'native-base';
|
|
5
|
-
|
|
5
|
+
import ScreenContainer from '../Container/ScreenContainer.js';
|
|
6
6
|
|
|
7
7
|
export default function Loading(props) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if (props.isScreen) {
|
|
9
|
+
return <ScreenContainer {...props}>
|
|
10
|
+
<Spinner flex={1} color="primary.500" />
|
|
11
|
+
</ScreenContainer>;
|
|
12
|
+
}
|
|
13
13
|
return <Row justifyContent="center" minHeight={100} {...props}>
|
|
14
14
|
<Spinner flex={1} color="primary.500" />
|
|
15
15
|
</Row>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as ImageManipulator from 'expo-image-manipulator';
|
|
2
2
|
|
|
3
|
-
export default async function processImage(uri) {
|
|
3
|
+
export default async function processImage(uri, width = 1000) {
|
|
4
4
|
const file = await ImageManipulator.manipulateAsync(uri,
|
|
5
5
|
[{
|
|
6
6
|
resize: {
|
|
7
|
-
width
|
|
7
|
+
width,
|
|
8
8
|
}
|
|
9
9
|
}],
|
|
10
10
|
{
|
|
@@ -2,6 +2,7 @@ import UiGlobals from '../UiGlobals.js';
|
|
|
2
2
|
import Datetime from '../PlatformImports/ReactNative/Datetime';
|
|
3
3
|
import Draggable from '../PlatformImports/ReactNative/Draggable';
|
|
4
4
|
import ScreenContainer from '../Components/Container/ScreenContainer';
|
|
5
|
+
import useWindowSize from '../PlatformImports/ReactNative/useWindowSize.js';
|
|
5
6
|
import _ from 'lodash';
|
|
6
7
|
|
|
7
8
|
export default function registerReactNativeComponents() {
|
|
@@ -9,5 +10,6 @@ export default function registerReactNativeComponents() {
|
|
|
9
10
|
Datetime,
|
|
10
11
|
Draggable,
|
|
11
12
|
ScreenContainer,
|
|
13
|
+
useWindowSize,
|
|
12
14
|
});
|
|
13
15
|
}
|
|
@@ -4,6 +4,7 @@ import Attachments from '../PlatformImports/Web/Attachments.js';
|
|
|
4
4
|
import Datetime from '../PlatformImports/Web/Datetime.js';
|
|
5
5
|
import Draggable from '../PlatformImports/Web/Draggable.js';
|
|
6
6
|
// import File from '../PlatformImports/Web/Attachments.js';
|
|
7
|
+
import useWindowSize from '../PlatformImports/Web/useWindowSize.js';
|
|
7
8
|
import _ from 'lodash';
|
|
8
9
|
|
|
9
10
|
export default function registerWebComponents() {
|
|
@@ -13,5 +14,6 @@ export default function registerWebComponents() {
|
|
|
13
14
|
Datetime,
|
|
14
15
|
Draggable,
|
|
15
16
|
// File,
|
|
17
|
+
useWindowSize,
|
|
16
18
|
});
|
|
17
19
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import getComponentFromType from '../Functions/getComponentFromType.js';
|
|
2
2
|
|
|
3
3
|
// This hook takes the submitted window size and adjusts it
|
|
4
4
|
// to fit the actual screen size
|
|
5
5
|
|
|
6
6
|
export default function(width, height, percentage = 1) {
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const
|
|
9
|
+
useWindowSize = getComponentFromType('useWindowSize'),
|
|
10
|
+
windowSize = useWindowSize();
|
|
9
11
|
|
|
10
12
|
if (width > windowSize.width) {
|
|
11
13
|
width = windowSize.width * percentage;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// import DateTimePickerModal from 'react-native-modal-datetime-picker'; // https://github.com/mmazzarolo/react-native-modal-datetime-picker
|
|
2
|
-
import Datetime from '@react-native-community/datetimepicker'; // https://github.com/react-native-datetimepicker/datetimepicker
|
|
2
|
+
// import Datetime from '@react-native-community/datetimepicker'; // https://github.com/react-native-datetimepicker/datetimepicker
|
|
3
|
+
import CalendarPicker from 'react-native-calendar-picker'; // https://www.npmjs.com/package/react-native-calendar-picker
|
|
3
4
|
|
|
4
|
-
export default
|
|
5
|
+
export default CalendarPicker.default || CalendarPicker;
|