@onehat/ui 0.4.7 → 0.4.9

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.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -681,6 +681,7 @@ export function ComboComponent(props) {
681
681
  'disablePrint',
682
682
  'selectorId',
683
683
  'selectorSelected',
684
+ 'selectorSelectedField',
684
685
  'usePermissions',
685
686
  ]);
686
687
  if (!Repository) {
@@ -1012,6 +1013,7 @@ export function ComboComponent(props) {
1012
1013
  Combo-HStack
1013
1014
  flex-1
1014
1015
  h-[40px]
1016
+ min-h-[40px]
1015
1017
  justify-center
1016
1018
  items-center
1017
1019
  `;
@@ -245,6 +245,7 @@ function TagComponent(props) {
245
245
  if (propsToPass.selectorId) {
246
246
  _combo.selectorId = propsToPass.selectorId;
247
247
  _combo.selectorSelected = propsToPass.selectorSelected;
248
+ _combo.selectorSelectedField = propsToPass.selectorSelectedField;
248
249
  }
249
250
 
250
251
  let className = `
@@ -272,8 +273,9 @@ function TagComponent(props) {
272
273
  let valueBoxesClassName = `
273
274
  Tag-valueBoxes-container
274
275
  w-full
275
- flex-wrap
276
+ min-h-[40px]
276
277
  max-h-[200px]
278
+ flex-wrap
277
279
  overflow-auto
278
280
  border
279
281
  border-grey-300
@@ -125,6 +125,7 @@ function Form(props) {
125
125
  // parent container
126
126
  selectorId,
127
127
  selectorSelected,
128
+ selectorSelectedField,
128
129
 
129
130
  // withAlert
130
131
  alert,
@@ -297,7 +298,7 @@ function Form(props) {
297
298
  }
298
299
  }
299
300
 
300
- let elementClassName = '';
301
+ let elementClassName = 'Form-ElementFromColumnsConfig';
301
302
  const
302
303
  boxFlex = configPropsToPass.flex,
303
304
  boxW = configPropsToPass.w;
@@ -365,6 +366,7 @@ function Form(props) {
365
366
 
366
367
  if (useSelectorId) { // This causes the whole form to use selectorId
367
368
  editorTypeProps.selectorId = selectorId;
369
+ editorTypeProps.selectorSelectedField = selectorSelectedField;
368
370
  }
369
371
  if (configPropsToPass.selectorId || editorTypeProps.selectorId) { // editorTypeProps.selectorId causes just this one field to use selectorId
370
372
  if (_.isNil(configPropsToPass.selectorSelected)) {
@@ -376,7 +378,7 @@ function Form(props) {
376
378
  dynamicProps = getDynamicProps({ fieldState, formSetValue, formGetValues, formState });
377
379
  }
378
380
 
379
- let elementClassName = 'Form-Element flex-1';
381
+ let elementClassName = 'Form-Element';
380
382
  if (type.match(/Tag/)) {
381
383
  elementClassName += ' overflow-auto';
382
384
  }
@@ -552,9 +554,9 @@ function Form(props) {
552
554
  }
553
555
  delete itemPropsToPass.w;
554
556
  }
555
- if (!style.flex && !style.width) {
556
- style.flex = 1;
557
- }
557
+ // if (!style.flex && !style.width) {
558
+ // style.flex = 1;
559
+ // }
558
560
  itemPropsToPass.className += ' Column';
559
561
  }
560
562
  if (type === 'Row') {
@@ -565,7 +567,7 @@ function Form(props) {
565
567
  return buildFromItem(item, ix, {...defaults, ...itemDefaults});
566
568
  });
567
569
 
568
- let elementClassName = 'Form-Element';
570
+ let elementClassName = 'Form-ElementFromItem';
569
571
  const defaultsClassName = defaults.className;
570
572
  if (defaultsClassName) {
571
573
  elementClassName += ' ' + defaultsClassName;
@@ -641,16 +643,16 @@ function Form(props) {
641
643
  if (defaults?.labelWidth) {
642
644
  style.width = defaults.labelWidth;
643
645
  }
644
- if (!style.width) {
645
- style.width = '50px';
646
- }
647
646
  if (containerWidth > styles.FORM_STACK_ROW_THRESHOLD) {
648
- element = <HStack className="Form-HStack2 w-full py-1">
647
+ if (!style.width) {
648
+ style.width = '100px';
649
+ }
650
+ element = <HStack className="Form-HStack1 w-full py-1">
649
651
  <Label style={style}>{label}</Label>
650
652
  {element}
651
653
  </HStack>;
652
654
  } else {
653
- element = <VStack className="Form-VStack1 w-full py-1 mt-3">
655
+ element = <VStack className="Form-VStack2 w-full py-1 mt-3">
654
656
  <Label style={style}>{label}</Label>
655
657
  {element}
656
658
  </VStack>;
@@ -710,6 +712,7 @@ function Form(props) {
710
712
 
711
713
  if (useSelectorId) { // This causes the whole form to use selectorId
712
714
  editorTypeProps.selectorId = selectorId;
715
+ editorTypeProps.selectorSelectedField = selectorSelectedField;
713
716
  }
714
717
  if (itemPropsToPass.selectorId || editorTypeProps.selectorId) { // editorTypeProps.selectorId causes just this one field to use selectorId
715
718
  if (_.isNil(itemPropsToPass.selectorSelected)) {
@@ -721,7 +724,7 @@ function Form(props) {
721
724
  dynamicProps = getDynamicProps({ fieldState, formSetValue, formGetValues, formState });
722
725
  }
723
726
 
724
- let elementClassName = 'Form-Element field-' + name + ' flex-1';
727
+ let elementClassName = 'Form-Element field-' + name + ' w-full';
725
728
  const defaultsClassName = defaults.className;
726
729
  if (defaultsClassName) {
727
730
  elementClassName += ' ' + defaultsClassName;
@@ -771,7 +774,7 @@ function Form(props) {
771
774
  if (message) {
772
775
  message = <Text className="text-[#f00]">{message}</Text>;
773
776
  }
774
- element = <VStack className="Form-VStack4 pt-1 flex-1">
777
+ element = <VStack className="Form-VStack4 w-full pt-1">
775
778
  {element}
776
779
  {message}
777
780
  </VStack>;
@@ -779,14 +782,14 @@ function Form(props) {
779
782
  if (item.additionalEditButtons) {
780
783
  const buttons = buildAdditionalButtons(item.additionalEditButtons, self, { fieldState, formSetValue, formGetValues, formState });
781
784
  if (containerWidth > styles.FORM_STACK_ROW_THRESHOLD) {
782
- element = <HStack className="Form-additionalEditButtons flex-1 flex-wrap">
785
+ element = <HStack className="Form-HStack5 w-full flex-wrap">
783
786
  {element}
784
787
  {buttons}
785
788
  </HStack>;
786
789
  } else {
787
- element = <VStack className="Form-additionalEditButtons flex-1 w-full">
790
+ element = <VStack className="Form-VStack6 w-full">
788
791
  {element}
789
- <HStack className="Form-additionalEditButtons-VStack flex-1 w-full mt-1 flex-wrap">
792
+ <HStack className="Form-HStack7-VStack w-full mt-1 flex-wrap">
790
793
  {buttons}
791
794
  </HStack>
792
795
  </VStack>;
@@ -816,22 +819,22 @@ function Form(props) {
816
819
  if (defaults?.labelWidth) {
817
820
  style.width = defaults.labelWidth;
818
821
  }
819
- if (!style.width) {
820
- style.width = '50px';
821
- }
822
822
  if (containerWidth > styles.FORM_STACK_ROW_THRESHOLD) {
823
- element = <HStack className="HStack3 flex-1">
823
+ if (!style.width) {
824
+ style.width = '100px';
825
+ }
826
+ element = <HStack className="Form-HStack8 w-full">
824
827
  <Label style={style}>{requiredIndicator}{label}</Label>
825
828
  {element}
826
829
  </HStack>;
827
830
  } else {
828
- element = <VStack className="VStack3 flex-1 mt-3">
831
+ element = <VStack className="Form-VStack9 w-full mt-3">
829
832
  <Label style={style}>{requiredIndicator}{label}</Label>
830
833
  {element}
831
834
  </VStack>;
832
835
  }
833
836
  } else if (disableLabels && requiredIndicator) {
834
- element = <HStack className="HStack3 flex-1">
837
+ element = <HStack className="Form-HStack10 w-full">
835
838
  {requiredIndicator}
836
839
  {element}
837
840
  </HStack>;
@@ -851,10 +854,11 @@ function Form(props) {
851
854
  return <HStack
852
855
  key={ix}
853
856
  className={`
854
- HStack4
857
+ Form-HStack11
858
+ min-h-[50px]
859
+ w-full
855
860
  flex-none
856
861
  pb-2
857
- h-[50px]
858
862
  ${error ? 'bg-[#fdd]' : ''}
859
863
  `}
860
864
  >
@@ -873,6 +877,7 @@ function Form(props) {
873
877
  title = null,
874
878
  description = null,
875
879
  selectorId,
880
+ selectorSelectedField,
876
881
  ...itemPropsToPass
877
882
  } = item;
878
883
  if (isMultiple && type !== 'Attachments') {
@@ -887,6 +892,7 @@ function Form(props) {
887
892
  element = <Element
888
893
  {...testProps('ancillary-' + type)}
889
894
  selectorId={selectorId}
895
+ selectorSelectedField={selectorSelectedField}
890
896
  selectorSelected={selectorSelected || record}
891
897
  uniqueRepository={true}
892
898
  parent={self}
@@ -898,6 +904,7 @@ function Form(props) {
898
904
  }
899
905
  title = <Text
900
906
  className={`
907
+ Form-Ancillary-Title
901
908
  font-bold
902
909
  ${styles.FORM_ANCILLARY_TITLE_FONTSIZE}
903
910
  `}
@@ -906,6 +913,7 @@ function Form(props) {
906
913
  if (description) {
907
914
  description = <Text
908
915
  className={`
916
+ Form-Ancillary-Description
909
917
  italic
910
918
  ${styles.FORM_ANCILLARY_DESCRIPTION_FONTSIZE}
911
919
  `}
@@ -914,6 +922,7 @@ function Form(props) {
914
922
  components.push(<VStack
915
923
  key={'ancillary-' + ix}
916
924
  className={`
925
+ Form-VStack12
917
926
  mx-1
918
927
  my-3
919
928
  `}
@@ -107,7 +107,6 @@ const
107
107
 
108
108
  function GridComponent(props) {
109
109
  const {
110
-
111
110
  columnsConfig = [], // json configurations for each column
112
111
  columnProps = {},
113
112
  defaultHiddenColumns = [],
@@ -128,7 +127,6 @@ function GridComponent(props) {
128
127
  hideNavColumn = true,
129
128
  noneFoundText,
130
129
  autoAdjustPageSizeToHeight = true,
131
- disableSelectorSelected = false,
132
130
  showRowExpander = false,
133
131
  getExpandedRowContent,
134
132
  showHeaders = true,
@@ -154,6 +152,22 @@ function GridComponent(props) {
154
152
  alternateRowBackgrounds = true,
155
153
  alternatingInterval = 2,
156
154
  defaultRowHeight = 48,
155
+
156
+ // The selectorSelected mechanism allows us to filter results of the primary model, (e.g. WorkOrders)
157
+ // by the selection on the secondary model (e.g. Equipment). It's used on Grids, Trees, Forms, etc.
158
+ // The 'selectorId' is the name of the primary model's filter (e.g. 'WorkOrders.equipment_id').
159
+ // which gets submitted to the server as a condition (e.g. 'conditions[WorkOrders.equipment_id]').
160
+ // The 'selectorSelected' is the Entity on the secondary model which is selected (e.g. Equipment).
161
+ // The 'selectorSelectedField' is the field on the secondary model to use as the value for the filter
162
+ // (e.g. 'fleet_id'). If not given, it defaults to 'id'.
163
+ // It can be disabled altogether for a specific grid ('disableSelectorSelected'), and configured
164
+ // so that no selection means no results ('noSelectorMeansNoResults').
165
+
166
+ selectorId,
167
+ selectorSelected,
168
+ selectorSelectedField = 'id',
169
+ noSelectorMeansNoResults = false,
170
+ disableSelectorSelected = false,
157
171
 
158
172
  // withComponent
159
173
  self,
@@ -201,16 +215,11 @@ function GridComponent(props) {
201
215
  deselectAll,
202
216
  selectRangeTo,
203
217
  isInSelection,
204
- noSelectorMeansNoResults = false,
205
218
  selectNext,
206
219
  selectPrev,
207
220
  addNextToSelection,
208
221
  addPrevToSelection,
209
222
 
210
- // DataMgt
211
- selectorId,
212
- selectorSelected,
213
-
214
223
  // withInlineEditor
215
224
  inlineEditor = null,
216
225
  isInlineEditorShown = false,
@@ -231,6 +240,7 @@ function GridComponent(props) {
231
240
  expandedRowsRef = useRef({}),
232
241
  cachedDragElements = useRef(),
233
242
  dragSelectionRef = useRef([]),
243
+ previousSelectorId = useRef(),
234
244
  [isInited, setIsInited] = useState(false),
235
245
  [isReady, setIsReady] = useState(false),
236
246
  [isLoading, setIsLoading] = useState(false),
@@ -354,7 +364,7 @@ function GridComponent(props) {
354
364
  onPress={() => setIsReorderMode(!isReorderMode)}
355
365
  icon={isReorderMode ? NoReorderRows : ReorderRows}
356
366
  _icon={{
357
- className: styles.GRID_TOOLBAR_ITEMS_COLOR,
367
+ className: styles.TOOLBAR_ITEMS_COLOR,
358
368
  }}
359
369
  tooltip="Reorder Rows"
360
370
  />);
@@ -455,28 +465,36 @@ function GridComponent(props) {
455
465
  onContextMenu(item, e, selection);
456
466
  }
457
467
  }}
458
- className="flex-row grow-1">
468
+ className="flex-row grow">
459
469
  {({
460
470
  hovered,
461
471
  focused,
462
472
  pressed,
463
473
  }) => {
464
474
  if (isHeaderRow) {
465
- return <GridHeaderRow
466
- Repository={Repository}
467
- columnsConfig={localColumnsConfig}
468
- setColumnsConfig={setLocalColumnsConfig}
469
- hideNavColumn={hideNavColumn}
470
- canColumnsSort={canColumnsSort}
471
- canColumnsReorder={canColumnsReorder}
472
- canColumnsResize={canColumnsResize}
473
- setSelection={setSelection}
474
- gridRef={gridRef}
475
- isHovered={hovered}
476
- isInlineEditorShown={isInlineEditorShown}
477
- areRowsDragSource={areRowsDragSource}
478
- showColumnsSelector={showColumnsSelector}
479
- />;
475
+ let headerRow = <GridHeaderRow
476
+ Repository={Repository}
477
+ columnsConfig={localColumnsConfig}
478
+ setColumnsConfig={setLocalColumnsConfig}
479
+ hideNavColumn={hideNavColumn}
480
+ canColumnsSort={canColumnsSort}
481
+ canColumnsReorder={canColumnsReorder}
482
+ canColumnsResize={canColumnsResize}
483
+ setSelection={setSelection}
484
+ gridRef={gridRef}
485
+ isHovered={hovered}
486
+ isInlineEditorShown={isInlineEditorShown}
487
+ areRowsDragSource={areRowsDragSource}
488
+ showColumnsSelector={showColumnsSelector}
489
+ />;
490
+ if (showRowExpander) {
491
+ // align the header row to content rows
492
+ headerRow = <HStack className="">
493
+ <Box className="w-[40px]"></Box>
494
+ {headerRow}
495
+ </HStack>;
496
+ }
497
+ return headerRow;
480
498
  }
481
499
 
482
500
  const
@@ -561,15 +579,29 @@ function GridComponent(props) {
561
579
 
562
580
  if (showRowExpander && !isHeaderRow) {
563
581
  const isExpanded = getIsExpanded(index);
564
- rowComponent = <VStack>
565
- <HStack>
582
+ let className = `
583
+ Grid-rowExpander
584
+ w-full
585
+ flex-none
586
+ `;
587
+ if (rowProps?.className) {
588
+ className += ' ' + rowProps.className;
589
+ }
590
+ rowComponent = <VStack className={className}>
591
+ <HStack
592
+ className={`
593
+ Grid-rowExpander-HStack
594
+ w-full
595
+ grow
596
+ `}
597
+ >
566
598
  <ExpandButton
567
599
  isExpanded={isExpanded}
568
600
  onToggle={() => setIsExpanded(index, !isExpanded)}
569
601
  _icon={{
570
602
  size: 'sm',
571
603
  }}
572
- className="py-0"
604
+ className="Grid-rowExpander-expandBtn py-0"
573
605
  tooltip="Expand/Contract Row"
574
606
  />
575
607
  {rowComponent}
@@ -760,11 +792,23 @@ function GridComponent(props) {
760
792
  if (disableSelectorSelected || !selectorId) {
761
793
  return
762
794
  }
763
- let id = selectorSelected?.id;
764
- if (_.isEmpty(selectorSelected)) {
765
- id = noSelectorMeansNoResults ? 'NO_MATCHES' : null;
795
+
796
+ if (previousSelectorId.current && selectorId !== previousSelectorId.current) {
797
+ Repository.pauseEvents();
798
+ Repository.clearFilters(previousSelectorId.current);
799
+ Repository.resumeEvents();
800
+ }
801
+ previousSelectorId.current = selectorId;
802
+
803
+ let value = null;
804
+ if (selectorSelected) {
805
+ value = selectorSelected[selectorSelectedField];
766
806
  }
767
- Repository.filter(selectorId, id, false); // so it doesn't clear existing filters
807
+ if (noSelectorMeansNoResults && _.isEmpty(selectorSelected)) {
808
+ value = 'NO_MATCHES';
809
+ }
810
+
811
+ Repository.filter(selectorId, value, false); // false so it doesn't clear existing filters
768
812
  },
769
813
  onGridKeyDown = (e) => {
770
814
  if (isInlineEditorShown) {
@@ -1035,7 +1079,7 @@ function GridComponent(props) {
1035
1079
 
1036
1080
  applySelectorSelected();
1037
1081
 
1038
- }, [selectorSelected]);
1082
+ }, [selectorId, selectorSelected]);
1039
1083
 
1040
1084
  if (canUser && !canUser('view')) {
1041
1085
  return <Unauthorized />;
@@ -1205,6 +1249,7 @@ function GridComponent(props) {
1205
1249
  className={`
1206
1250
  gridContainer
1207
1251
  w-full
1252
+ h-full
1208
1253
  flex-1
1209
1254
  min-h-[40px]
1210
1255
  ${gridContainerBorderClassName}
@@ -1221,7 +1266,8 @@ function GridComponent(props) {
1221
1266
  grid = <Box
1222
1267
  ref={dropTargetRef}
1223
1268
  className={`
1224
- dropTarget
1269
+ Grid-dropTarget
1270
+ h-full
1225
1271
  w-full
1226
1272
  border-[#0ff]
1227
1273
  ${canDrop && isOver ? "border-[4px]" : "border-[0px]"}
@@ -315,6 +315,9 @@ function GridRow(props) {
315
315
  } else {
316
316
  rowClassName += ' border-b border-b-grey-100';
317
317
  }
318
+ if (rowProps?.className) {
319
+ rowClassName += ' ' + rowProps.className;
320
+ }
318
321
  return <HStackNative
319
322
  {...testProps('row' + (isSelected ? '-selected' : ''))}
320
323
  {...rowProps}
@@ -337,6 +340,7 @@ function GridRow(props) {
337
340
  isInlineEditorShown,
338
341
  isSelected,
339
342
  isHovered,
343
+ isOver,
340
344
  index,
341
345
  dragSourceRef,
342
346
  dropTargetRef,
@@ -59,6 +59,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
59
59
  // parent container
60
60
  secondarySelectorId,
61
61
  secondarySelectorSelected,
62
+ secondarySelectorSelectedField = 'id',
62
63
 
63
64
  // withSecondaryData
64
65
  SecondaryRepository,
@@ -149,7 +150,7 @@ export default function withSecondaryEditor(WrappedComponent, isTree = false) {
149
150
  }
150
151
 
151
152
  if (secondarySelectorId && !_.isEmpty(secondarySelectorSelected)) {
152
- addValues[secondarySelectorId] = secondarySelectorSelected.id;
153
+ addValues[secondarySelectorId] = secondarySelectorSelected[secondarySelectorSelectedField];
153
154
  }
154
155
 
155
156
  if (getNewEntityDisplayValue()) {
@@ -35,6 +35,7 @@ export default function withSecondarySideEditor(WrappedComponent, isTree = false
35
35
  // pull these out, as we don't want them going to the Editor
36
36
  secondarySelectorId,
37
37
  secondarySelectorSelected,
38
+ secondarySelectorSelectedField,
38
39
 
39
40
  ...propsToPass
40
41
  } = props;
@@ -39,6 +39,7 @@ export default function withSecondaryWindowedEditor(WrappedComponent, isTree = f
39
39
  // pull these out, as we don't want them going to the SecondaryEditor
40
40
  secondarySelectorId,
41
41
  secondarySelectorSelected,
42
+ secondarySelectorSelectedField,
42
43
  h,
43
44
 
44
45
  ...propsToPass
@@ -58,6 +58,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
58
58
  // parent container
59
59
  selectorId,
60
60
  selectorSelected,
61
+ selectorSelectedField = 'id',
61
62
 
62
63
  // withData
63
64
  Repository,
@@ -147,7 +148,7 @@ export default function withEditor(WrappedComponent, isTree = false) {
147
148
  }
148
149
 
149
150
  if (selectorId && !_.isEmpty(selectorSelected)) {
150
- addValues[selectorId] = selectorSelected.id;
151
+ addValues[selectorId] = selectorSelected[selectorSelectedField];
151
152
  }
152
153
 
153
154
  if (getNewEntityDisplayValue()) {
@@ -35,6 +35,7 @@ export default function withInlineEditor(WrappedComponent, skipWrappers = false)
35
35
  // pull these out, as we don't want them going to the Editor
36
36
  selectorId,
37
37
  selectorSelected,
38
+ selectorSelectedField,
38
39
  h,
39
40
 
40
41
  ...propsToPass
@@ -35,6 +35,7 @@ export default function withSideEditor(WrappedComponent, isTree = false) {
35
35
  // pull these out, as we don't want them going to the Editor
36
36
  selectorId,
37
37
  selectorSelected,
38
+ selectorSelectedField,
38
39
  style,
39
40
 
40
41
  ...propsToPass
@@ -56,6 +56,7 @@ export default function withWindowedEditor(WrappedComponent, isTree = false) {
56
56
  // pull these out, as we don't want them going to the Editor
57
57
  selectorId,
58
58
  selectorSelected,
59
+ selectorSelectedField,
59
60
  h,
60
61
 
61
62
  ...propsToPass
@@ -4,8 +4,8 @@ import { Path, Svg } from 'react-native-svg';
4
4
 
5
5
  const SvgComponent = createIcon({
6
6
  Root: Svg,
7
- viewBox: '0 0 10.46 10.46',
8
- path: <Path d="M0 5.23C0 2.34 2.34 0 5.23 0s5.23 2.34 5.23 5.23-2.34 5.23-5.23 5.23S0 8.12 0 5.23zm5.89-3.27c0-.36-.29-.65-.65-.65s-.65.29-.65.65.29.65.65.65.65-.29.65-.65zM5.24 8.5c.72 0 1.31-.59 1.31-1.31 0-.36-.14-.68-.37-.91L7.49 3.3c.11-.25 0-.54-.25-.65s-.54 0-.65.25L5.28 5.88h-.04c-.72 0-1.31.59-1.31 1.31S4.52 8.5 5.24 8.5zM3.6 2.94c0-.36-.29-.65-.65-.65s-.65.29-.65.65.29.65.65.65.65-.29.65-.65zM1.96 5.88c.36 0 .65-.29.65-.65s-.29-.65-.65-.65-.65.29-.65.65.29.65.65.65zm7.19-.65c0-.36-.29-.65-.65-.65s-.65.29-.65.65.29.65.65.65.65-.29.65-.65z" />
7
+ viewBox: '0 0 512 512',
8
+ path: <Path d="M0 256a256 256 0 11512 0 256 256 0 11-512 0zm320 96c0-26.9-16.5-49.9-40-59.3V88c0-13.3-10.7-24-24-24s-24 10.7-24 24v204.7c-23.5 9.5-40 32.5-40 59.3 0 35.3 28.7 64 64 64s64-28.7 64-64zM144 176a32 32 0 100-64 32 32 0 100 64zm-16 80a32 32 0 10-64 0 32 32 0 1064 0zm288 32a32 32 0 100-64 32 32 0 100 64zm-16-144a32 32 0 10-64 0 32 32 0 1064 0z" />,
9
9
  });
10
10
 
11
11
  export default SvgComponent
@@ -61,6 +61,7 @@ export default function Pagination(props) {
61
61
  {...testProps('showMoreBtn')}
62
62
  key="showMoreBtn"
63
63
  reference="showMoreBtn"
64
+ className="Pagination-showMoreBtn"
64
65
  parent={self}
65
66
  onPress={() => Repository.showMore()}
66
67
  isDisabled={isDisabled}
@@ -70,6 +71,7 @@ export default function Pagination(props) {
70
71
  if (!Repository.isLocal) {
71
72
  items.push(<ReloadButton
72
73
  key="reloadPageBtn"
74
+ className="Pagination-reloadPageBtn"
73
75
  _icon={iconProps}
74
76
  Repository={Repository}
75
77
  self={self}
@@ -82,6 +84,7 @@ export default function Pagination(props) {
82
84
  {...testProps('firstPageBtn')}
83
85
  key="firstPageBtn"
84
86
  reference="firstPageBtn"
87
+ className="Pagination-firstPageBtn"
85
88
  parent={self}
86
89
  isDisabled={isDisabled}
87
90
  icon={AnglesLeft}
@@ -93,6 +96,7 @@ export default function Pagination(props) {
93
96
  {...testProps('prevPageBtn')}
94
97
  key="prevPageBtn"
95
98
  reference="prevPageBtn"
99
+ className="Pagination-prevPageBtn"
96
100
  parent={self}
97
101
  isDisabled={isDisabled}
98
102
  icon={AngleLeft}
@@ -101,31 +105,38 @@ export default function Pagination(props) {
101
105
  tooltip="Previous Page"
102
106
  />);
103
107
  if (!minimize) {
104
- items.push(<HStack
105
- key="pageSelector"
106
- className={`
107
- pageSelector
108
- w-[100px]
109
- mx-2
110
- justify-center
111
- items-center
112
- bg-[#f00]
113
- `}>
114
- {/* <Text className="page mr-1">Page</Text>
115
- <Input
116
- {...testProps('pageInput')}
117
- reference="pageInput"
118
- parent={self}
119
- keyboardType="numeric"
120
- value={page?.toString()}
121
- onChangeValue={(value) => Repository.setPage(value)}
122
- maxValue={totalPages}
123
- isDisabled={totalPages === 1}
124
- className="pageInput w-[30px] text-center bg-grey-100"
125
- tooltip="Set Page"
126
- />
127
- <Text className="of ml-1">of {totalPages}</Text> */}
128
- </HStack>);
108
+ items.push(<Text
109
+ key="page"
110
+ className="Pagination-page mx-1"
111
+ >Page</Text>);
112
+ items.push(<Input
113
+ {...testProps('pageInput')}
114
+ key="pageInput"
115
+ reference="pageInput"
116
+ parent={self}
117
+ keyboardType="numeric"
118
+ value={page?.toString()}
119
+ onChangeValue={(value) => Repository.setPage(value)}
120
+ maxValue={totalPages}
121
+ isDisabled={totalPages === 1}
122
+ className={`
123
+ Pagination-pageInput
124
+ min-w-[40px]
125
+ w-[40px]
126
+ text-center
127
+ bg-grey-100
128
+ `}
129
+ tooltip="Set Page"
130
+ />);
131
+ items.push(<Text
132
+ key="totalPages"
133
+ className={`
134
+ Pagination-totalPages
135
+ whitespace-nowrap
136
+ inline-flex
137
+ mx-1
138
+ `}
139
+ >{`of ${totalPages}`}</Text>);
129
140
  }
130
141
 
131
142
  isDisabled = page === totalPages || totalPages <= 1;
@@ -133,6 +144,7 @@ export default function Pagination(props) {
133
144
  {...testProps('nextPageBtn')}
134
145
  key="nextPageBtn"
135
146
  reference="nextPageBtn"
147
+ className="Pagination-nextPageBtn"
136
148
  parent={self}
137
149
  isDisabled={isDisabled}
138
150
  icon={AngleRight}
@@ -144,6 +156,7 @@ export default function Pagination(props) {
144
156
  {...testProps('lastPageBtn')}
145
157
  key="lastPageBtn"
146
158
  reference="lastPageBtn"
159
+ className="Pagination-lastPageBtn"
147
160
  parent={self}
148
161
  isDisabled={isDisabled}
149
162
  icon={AnglesRight}
@@ -156,6 +169,7 @@ export default function Pagination(props) {
156
169
  if (!Repository.isLocal) {
157
170
  items.push(<ReloadButton
158
171
  key="reloadPageBtn"
172
+ className="Pagination-reloadPageBtn"
159
173
  _icon={iconProps}
160
174
  Repository={Repository}
161
175
  self={self}
@@ -178,13 +192,26 @@ export default function Pagination(props) {
178
192
  }
179
193
  items.push(<Text
180
194
  key="pageDisplay"
181
- className="pageDisplay ml-3 min-w-[200px]"
182
- >Displaying {pageSpan} of {total}</Text>);
195
+ className={`
196
+ Pagination-pageDisplay
197
+ whitespace-nowrap
198
+ inline-flex
199
+ mx-1
200
+ `}
201
+ >{`Displaying ${pageSpan} of ${total}`}</Text>);
183
202
  }
184
203
  }
185
204
  return <HStack
186
205
  style={{ userSelect: 'none', }}
187
- className="Pagination justify-start items-center px-2 "
206
+ className={`
207
+ Pagination
208
+ flex-none
209
+ gap-1
210
+ justify-start
211
+ items-center
212
+ px-2
213
+ mr-3
214
+ `}
188
215
  >
189
216
  {items}
190
217
  </HStack>;
@@ -114,6 +114,10 @@ function TreeComponent(props) {
114
114
  initialSelection,
115
115
  canRecordBeEdited,
116
116
  onTreeLoad,
117
+
118
+ selectorId,
119
+ selectorSelected,
120
+ selectorSelectedField = 'id',
117
121
 
118
122
  // withComponent
119
123
  self,
@@ -160,10 +164,6 @@ function TreeComponent(props) {
160
164
  isInSelection,
161
165
  noSelectorMeansNoResults = false,
162
166
 
163
- // DataMgt
164
- selectorId,
165
- selectorSelected,
166
-
167
167
  } = props,
168
168
  styles = UiGlobals.styles,
169
169
  forceUpdate = useForceUpdate(),
@@ -1275,7 +1275,7 @@ function TreeComponent(props) {
1275
1275
  return () => {};
1276
1276
  }
1277
1277
  if (!disableSelectorSelected && selectorId) {
1278
- let id = selectorSelected?.id;
1278
+ let id = selectorSelected?.[selectorSelectedField] ?? null;
1279
1279
  if (_.isEmpty(selectorSelected)) {
1280
1280
  id = noSelectorMeansNoResults ? 'NO_MATCHES' : null;
1281
1281
  }
@@ -62,6 +62,7 @@ function Viewer(props) {
62
62
  // parent container
63
63
  selectorId,
64
64
  selectorSelected,
65
+ selectorSelectedField,
65
66
 
66
67
  } = props,
67
68
  scrollViewRef = useRef(),
@@ -150,9 +151,9 @@ function Viewer(props) {
150
151
  }
151
152
  delete itemPropsToPass.w;
152
153
  }
153
- if (!style.flex && !style.width) {
154
- style.flex = 1;
155
- }
154
+ // if (!style.flex && !style.width) {
155
+ // style.flex = 1;
156
+ // }
156
157
  itemPropsToPass.className += ' Column';
157
158
  // if (containerWidth < styles.FORM_ONE_COLUMN_THRESHOLD) {
158
159
  // // everything is in one column
@@ -310,6 +311,7 @@ function Viewer(props) {
310
311
  {...testProps('ancillary-' + type)}
311
312
  selectorId={selectorId}
312
313
  selectorSelected={selectorSelected || record}
314
+ selectorSelectedField={selectorSelectedField}
313
315
  canEditorViewOnly={true}
314
316
  canCrud={false}
315
317
  uniqueRepository={true}
@@ -89,6 +89,7 @@ function AttachmentsElement(props) {
89
89
 
90
90
  // parentContainer
91
91
  selectorSelected,
92
+ selectorSelectedField = 'id',
92
93
 
93
94
  // withData
94
95
  Repository,
@@ -100,7 +101,7 @@ function AttachmentsElement(props) {
100
101
  } = props,
101
102
  styles = UiGlobals.styles,
102
103
  model = _.isArray(selectorSelected) && selectorSelected[0] ? selectorSelected[0].repository?.name : selectorSelected?.repository?.name,
103
- modelidCalc = _.isArray(selectorSelected) ? _.map(selectorSelected, (entity) => entity.id) : selectorSelected?.id,
104
+ modelidCalc = _.isArray(selectorSelected) ? _.map(selectorSelected, (entity) => entity[selectorSelectedField]) : selectorSelected?.[selectorSelectedField],
104
105
  modelid = useRef(modelidCalc),
105
106
  [isReady, setIsReady] = useState(false),
106
107
  [isUploading, setIsUploading] = useState(false),