@onehat/ui 0.3.69 → 0.3.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.3.69",
3
+ "version": "0.3.71",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -130,7 +130,6 @@ export default function Accordion(props) {
130
130
  if (!containerInitialHeight) {
131
131
  const { height } = e.nativeEvent.layout;
132
132
  setContainerInitialHeight(height);
133
- console.log('height', height);
134
133
  }
135
134
  if (onLayout) {
136
135
  onLayout(e);
@@ -45,12 +45,6 @@ const
45
45
  const value = editor.getData();
46
46
  debouncedSetValueRef.current(value);
47
47
  }}
48
- // onBlur={(event, editor) => {
49
- // console.log( 'Blur.', editor);
50
- // }}
51
- // onFocus={(event, editor) => {
52
- // console.log( 'Focus.', editor);
53
- // }}
54
48
  />
55
49
  </Row>;
56
50
  },
@@ -21,9 +21,12 @@ import emptyFn from '../../../../Functions/emptyFn.js';
21
21
  import { Grid, WindowedGridEditor } from '../../../Grid/Grid.js';
22
22
  import IconButton from '../../../Buttons/IconButton.js';
23
23
  import CaretDown from '../../../Icons/CaretDown.js';
24
+ import Check from '../../../Icons/Check.js';
24
25
  import Xmark from '../../../Icons/Xmark.js';
25
26
  import _ from 'lodash';
26
27
 
28
+ const FILTER_NAME = 'q';
29
+
27
30
  export function ComboComponent(props) {
28
31
  const {
29
32
  additionalButtons,
@@ -285,7 +288,11 @@ export function ComboComponent(props) {
285
288
  onClearBtn = () => {
286
289
  setTextInputValue('');
287
290
  setValue(null);
288
- }
291
+ },
292
+ onXBtnPress = () => {
293
+ hideMenu();
294
+ setValue(null);
295
+ },
289
296
  isEventStillInComponent = (e) => {
290
297
  const {
291
298
  relatedTarget
@@ -298,38 +305,38 @@ export function ComboComponent(props) {
298
305
  menuRef.current === relatedTarget ||
299
306
  menuRef.current?.contains(relatedTarget);
300
307
  },
308
+ getFilterName = () => {
309
+ // Only used for remote repositories
310
+ // Gets the filter name of the query, which becomes the condition sent to server
311
+ let filterName = FILTER_NAME;
312
+ if (Repository.isRemote) {
313
+ const
314
+ schema = Repository.getSchema(),
315
+ displayFieldName = schema.model.displayProperty,
316
+ displayFieldDef = schema.getPropertyDefinition(displayFieldName);
317
+
318
+ // Verify displayField is a real field
319
+ if (!displayFieldDef.isVirtual) {
320
+ filterName = displayFieldName + ' LIKE';
321
+ }
322
+ }
323
+ return filterName;
324
+ },
301
325
  clearGridFilters = async () => {
302
326
  if (Repository) {
303
327
  if (Repository.isLoading) {
304
328
  await Repository.waitUntilDoneLoading();
305
329
  }
330
+ const filterName = getFilterName();
331
+ if (Repository.hasFilter(filterName)) {
332
+ Repository.clearFilters(filterName);
333
+ }
306
334
 
307
- // clear filter
308
- if (Repository.isRemote || Repository.remote) {
309
- let searchField = 'q';
310
- const searchValue = null;
311
-
312
- // Check to see if displayField is a real field
313
- const
314
- schema = Repository.getSchema(),
315
- displayFieldName = schema.model.displayProperty,
316
- displayFieldDef = schema.getPropertyDefinition(displayFieldName);
317
- if (!displayFieldDef.isVirtual) {
318
- searchField = displayFieldName + ' LIKE';
319
- }
320
-
321
- if (Repository.hasFilter(searchField)) {
322
- Repository.clear();
323
- await Repository.filter(searchField, searchValue);
324
- if (!this.isAutoLoad) {
325
- await Repository.reload();
326
- }
335
+ if (Repository.isRemote) {
336
+ if (!this.isAutoLoad) {
337
+ await Repository.reload();
327
338
  }
328
-
329
- } else {
330
- throw Error('Not yet implemented');
331
339
  }
332
-
333
340
  } else {
334
341
  setFilteredData(data);
335
342
  }
@@ -343,41 +350,34 @@ export function ComboComponent(props) {
343
350
 
344
351
  let found;
345
352
  if (Repository) {
353
+ if (Repository.isLoading) {
354
+ await Repository.waitUntilDoneLoading();
355
+ }
346
356
 
347
- if (_.isEmpty(value) && Repository.hasFilters) {
348
- Repository.clearFilters();
357
+ if (_.isEmpty(value)) {
358
+ clearGridFilters();
349
359
  return;
350
360
  }
351
361
 
352
- if (Repository.isLoading) {
353
- await Repository.waitUntilDoneLoading();
354
- }
355
-
356
362
  // Set filter
363
+ const filterName = getFilterName();
357
364
  if (Repository.isRemote) {
358
- const
359
- schema = Repository.getSchema(),
360
- displayFieldName = schema.model.displayProperty,
361
- displayFieldDef = schema.getPropertyDefinition(displayFieldName),
362
- searchValue = _.isEmpty(value) ? null : value + '%';
363
- let searchField = 'q';
364
-
365
- // Verify displayField is a real field
366
- if (!displayFieldDef.isVirtual) {
367
- searchField = displayFieldName + ' LIKE';
368
- }
369
-
370
- await Repository.filter(searchField, searchValue);
365
+ // remote
366
+ const filterValue = _.isEmpty(value) ? null : value + '%';
367
+ await Repository.filter(filterName, filterValue);
371
368
  if (!this.isAutoLoad) {
372
369
  await Repository.reload();
373
370
  }
374
371
  } else {
375
- // local filter
376
- Repository.filter((entity) => {
377
- const
378
- displayValue = entity.displayValue,
379
- regex = new RegExp('^' + value);
380
- return displayValue.match(regex);
372
+ // local
373
+ Repository.filter({
374
+ name: filterName,
375
+ fn: (entity) => {
376
+ const
377
+ displayValue = entity.displayValue,
378
+ regex = new RegExp('^' + value);
379
+ return displayValue.match(regex);
380
+ },
381
381
  });
382
382
  }
383
383
 
@@ -405,6 +405,12 @@ export function ComboComponent(props) {
405
405
  inputRef.current.focus();
406
406
  }
407
407
 
408
+ return () => {
409
+ if (Repository && !Repository.isUnique) {
410
+ clearGridFilters();
411
+ }
412
+ };
413
+
408
414
  }, [isRendered]);
409
415
 
410
416
  useEffect(() => {
@@ -427,6 +433,7 @@ export function ComboComponent(props) {
427
433
 
428
434
  let xButton = null,
429
435
  inputAndTrigger = null,
436
+ checkBtn = null,
430
437
  grid = null,
431
438
  dropdownMenu = null,
432
439
  assembledComponents = null;
@@ -439,7 +446,7 @@ export function ComboComponent(props) {
439
446
  size: 'sm',
440
447
  }}
441
448
  isDisabled={isDisabled}
442
- onPress={onClearBtn}
449
+ onPress={onXBtnPress}
443
450
  h="100%"
444
451
  bg={styles.FORM_COMBO_TRIGGER_BG}
445
452
  _hover={{
@@ -478,6 +485,7 @@ export function ComboComponent(props) {
478
485
  </Pressable> :
479
486
  <Input
480
487
  ref={inputRef}
488
+ reference="ComboInput"
481
489
  value={textInputValue}
482
490
  autoSubmit={true}
483
491
  isDisabled={isDisabled}
@@ -485,14 +493,6 @@ export function ComboComponent(props) {
485
493
  onKeyPress={onInputKeyPress}
486
494
  onFocus={onInputFocus}
487
495
  onBlur={onInputBlur}
488
- onLayout={(e) => {
489
- const {
490
- height,
491
- width,
492
- } = e.nativeEvent.layout;
493
- setWidth(Math.round(width));
494
- setTop(Math.round(height));
495
- }}
496
496
  flex={1}
497
497
  h="100%"
498
498
  m={0}
@@ -533,7 +533,8 @@ export function ComboComponent(props) {
533
533
 
534
534
  if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
535
535
  // This input and trigger are for show
536
- // The just show the current value and open the menu
536
+ // The just show the current getDisplayValue and open the menu
537
+ const displayValue = getDisplayValue();
537
538
  inputAndTrigger = <>
538
539
  <Pressable
539
540
  onPress={showMenu}
@@ -550,13 +551,13 @@ export function ComboComponent(props) {
550
551
  borderColor="trueGray.400"
551
552
  borderTopRightRadius={0}
552
553
  borderBottomRightRadius={0}
553
- color={_.isEmpty(textInputValue) ? 'trueGray.400' : '#000'}
554
+ color={_.isEmpty(displayValue) ? 'trueGray.400' : '#000'}
554
555
  fontSize={styles.FORM_COMBO_INPUT_FONTSIZE}
555
556
  bg={styles.FORM_COMBO_INPUT_BG}
556
557
  _focus={{
557
558
  bg: styles.FORM_COMBO_INPUT_FOCUS_BG,
558
559
  }}
559
- >{_.isEmpty(textInputValue) ? placeholder : textInputValue}</Text>
560
+ >{_.isEmpty(displayValue) ? placeholder : displayValue}</Text>
560
561
  </Pressable>
561
562
  <IconButton
562
563
  ref={triggerRef}
@@ -734,8 +735,28 @@ export function ComboComponent(props) {
734
735
  </Popover>;
735
736
  }
736
737
  if (UiGlobals.mode === UI_MODE_REACT_NATIVE) {
738
+ if (isEditor) {
739
+ // 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
740
+ checkBtn = <IconButton
741
+ _icon={{
742
+ as: Check,
743
+ color: 'trueGray.600',
744
+ size: 'sm',
745
+ }}
746
+ onPress={onXBtnPress}
747
+ h="100%"
748
+ borderWidth={1}
749
+ borderColor="#bbb"
750
+ borderRadius="md"
751
+ bg={styles.FORM_COMBO_TRIGGER_BG}
752
+ _hover={{
753
+ bg: styles.FORM_COMBO_TRIGGER_HOVER_BG,
754
+ }}
755
+ />;
756
+ }
737
757
  const inputAndTriggerClone = // for RN, this is the actual input and trigger, as we need them to appear up above in the modal
738
758
  <Row h={10}>
759
+ {xButton}
739
760
  {disableDirectEntry ?
740
761
  <Text
741
762
  ref={inputRef}
@@ -757,6 +778,7 @@ export function ComboComponent(props) {
757
778
  >{textInputValue}</Text> :
758
779
  <Input
759
780
  ref={inputRef}
781
+ reference="ComboInput"
760
782
  value={textInputValue}
761
783
  autoSubmit={true}
762
784
  isDisabled={isDisabled}
@@ -797,6 +819,7 @@ export function ComboComponent(props) {
797
819
  bg: styles.FORM_COMBO_TRIGGER_HOVER_BG,
798
820
  }}
799
821
  />
822
+ {checkBtn}
800
823
  </Row>;
801
824
  dropdownMenu = <Modal
802
825
  isOpen={true}
@@ -290,11 +290,11 @@ export function DateElement(props) {
290
290
  color: styles.FORM_DATE_ICON_COLOR,
291
291
  size: 'sm',
292
292
  }}
293
- isDisabled={isDisabled}
294
293
  onPress={onTriggerPress}
295
294
  onBlur={onTriggerBlur}
296
- h="100%"
295
+ h={10}
297
296
  w={10}
297
+ isDisabled={isDisabled}
298
298
  borderWidth={1}
299
299
  borderColor="#bbb"
300
300
  borderLeftRadius="md"
@@ -334,20 +334,21 @@ export function DateElement(props) {
334
334
  <Input
335
335
  ref={inputRef}
336
336
  value={textInputValue}
337
- autoSubmit={true}
338
- isDisabled={isDisabled}
337
+ // setValue={onInputSetValue}
339
338
  onChangeValue={onInputChangeText}
340
339
  onKeyPress={onInputKeyPress}
341
- onFocus={onInputFocus}
342
340
  onBlur={onInputBlur}
343
- onLayout={(e) => {
344
- const {
345
- height,
346
- width,
347
- } = e.nativeEvent.layout;
348
- setWidth(Math.round(width));
349
- setTop(Math.round(height));
350
- }}
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
+ // }}
351
352
  flex={1}
352
353
  h="100%"
353
354
  m={0}
@@ -455,6 +456,7 @@ export function DateElement(props) {
455
456
  minWidth={menuMinWidth}
456
457
  overflow="auto"
457
458
  bg="#fff"
459
+ {...translateProps}
458
460
  >
459
461
  <Popover.Body
460
462
  ref={pickerRef}
@@ -568,6 +570,7 @@ export function DateElement(props) {
568
570
  /> */}
569
571
  <Box bg="#fff">
570
572
  <Datetime
573
+ initialDate={moment(value).toDate()}
571
574
  selectedStartDate={moment(value).toDate()}
572
575
  onDateChange={onPickerChange}
573
576
  todayBackgroundColor="#eee"
@@ -107,6 +107,7 @@ function Form(props) {
107
107
  onClose,
108
108
  onDelete,
109
109
  editorStateRef,
110
+ disableView,
110
111
 
111
112
  // parent container
112
113
  selectorId,
@@ -696,7 +697,7 @@ function Form(props) {
696
697
  leftIcon={<Icon as={AngleLeft} color="#fff" size="sm" />}
697
698
  color="#fff"
698
699
  >Back</Button>}
699
- {isSingle && editorMode === EDITOR_MODE__EDIT && onViewMode &&
700
+ {isSingle && editorMode === EDITOR_MODE__EDIT && onViewMode && !disableView &&
700
701
  <Button
701
702
  key="viewBtn"
702
703
  onPress={onViewMode}
@@ -736,7 +737,12 @@ function Form(props) {
736
737
  if (isEditorViewOnly) {
737
738
  showCloseBtn = true;
738
739
  } else {
739
- if (formState.isDirty || record?.isPhantom) {
740
+ const
741
+ formIsDirty = formState.isDirty,
742
+ recordIsPhantom = record?.isPhantom;
743
+ // console.log('formIsDirty', formIsDirty);
744
+ // console.log('recordIsPhantom', recordIsPhantom);
745
+ if (formIsDirty || recordIsPhantom) {
740
746
  if (isSingle && onCancel) {
741
747
  showCancelBtn = true;
742
748
  }
@@ -13,7 +13,7 @@ export default function Footer(props) {
13
13
  testID="footer"
14
14
  w="100%"
15
15
  p={2}
16
- safeAreaBottom
16
+ // safeAreaBottom
17
17
  {...props}
18
18
  >
19
19
  {props.children}
@@ -973,7 +973,7 @@ function TreeComponent(props) {
973
973
  setHighlitedDatum(null);
974
974
 
975
975
  } else {
976
- console.log('setDropRowIx', newIx);
976
+ // console.log('setDropRowIx', newIx);
977
977
  setDropRowIx(newIx);
978
978
 
979
979
  // highlight the drop node