@onehat/ui 0.3.379 → 0.3.380

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.379",
3
+ "version": "0.3.380",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -335,24 +335,38 @@ function TreeComponent(props) {
335
335
  buildRowToDatumMap();
336
336
  }
337
337
  },
338
- onToggle = (datum) => {
338
+ onToggle = async (datum, e) => {
339
339
  if (datum.isLoading) {
340
340
  return;
341
341
  }
342
342
 
343
- datum.isExpanded = !datum.isExpanded;
344
-
345
- if (datum.isExpanded && datum.item.repository?.isRemote && datum.item.hasChildren && !datum.item.areChildrenLoaded) {
346
- loadChildren(datum, 1);
347
- return;
348
- }
349
-
350
- if (!datum.isExpanded && datumContainsSelection(datum)) {
351
- deselectAll();
343
+ const
344
+ isExpanded = !datum.isExpanded, // sets new state
345
+ isShiftKey = e.shiftKey; // hold down the shift key to load all children
346
+
347
+ datum.isExpanded = isExpanded;
348
+
349
+ if (isExpanded) {
350
+ // opening
351
+ if (datum.item.repository?.isRemote && datum.item.hasChildren) {
352
+ if (isShiftKey) {
353
+ // load ALL children
354
+ await loadChildren(datum, 'all');
355
+ return;
356
+ } else if (!datum.item.areChildrenLoaded) {
357
+ // load only one level
358
+ await loadChildren(datum, 1);
359
+ return;
360
+ }
361
+ }
362
+ } else {
363
+ // closing
364
+ if (datumContainsSelection(datum)) {
365
+ deselectAll();
366
+ }
352
367
  }
353
368
 
354
369
  forceUpdate();
355
-
356
370
  buildRowToDatumMap();
357
371
  },
358
372
  onCollapseAll = () => {
@@ -435,20 +449,20 @@ function TreeComponent(props) {
435
449
  });
436
450
  return found;
437
451
  },
438
- buildTreeNodeDatum = (treeNode) => {
452
+ buildTreeNodeDatum = (treeNode, defaultToExpanded = false) => {
439
453
  // Build the data-representation of one node and its children,
440
454
  // caching text & icon, keeping track of the state for whole tree
441
455
  // renderTreeNode uses this to render the nodes.
442
456
  const
443
457
  isRoot = treeNode.isRoot,
444
- children = buildTreeNodeData(treeNode.children), // recursively get data for children
458
+ children = buildTreeNodeData(treeNode.children, defaultToExpanded), // recursively get data for children
445
459
  datum = {
446
460
  item: treeNode,
447
461
  text: getNodeText(treeNode),
448
462
  iconCollapsed: getNodeIcon(COLLAPSED, treeNode),
449
463
  iconExpanded: getNodeIcon(EXPANDED, treeNode),
450
464
  iconLeaf: getNodeIcon(LEAF, treeNode),
451
- isExpanded: isRoot, // all non-root treeNodes are collapsed by default
465
+ isExpanded: defaultToExpanded || isRoot, // all non-root treeNodes are collapsed by default
452
466
  isVisible: isRoot ? areRootsVisible : true,
453
467
  isLoading: false,
454
468
  children,
@@ -456,10 +470,10 @@ function TreeComponent(props) {
456
470
 
457
471
  return datum;
458
472
  },
459
- buildTreeNodeData = (treeNodes) => {
473
+ buildTreeNodeData = (treeNodes, defaultToExpanded = false) => {
460
474
  const data = [];
461
475
  _.each(treeNodes, (item) => {
462
- data.push(buildTreeNodeDatum(item));
476
+ data.push(buildTreeNodeDatum(item, defaultToExpanded));
463
477
  });
464
478
  return data;
465
479
  },
@@ -657,12 +671,19 @@ function TreeComponent(props) {
657
671
 
658
672
  try {
659
673
 
674
+ let defaultToExpanded = false;
660
675
  if (depth === 'all') {
676
+ defaultToExpanded = true;
661
677
  depth = 9999;
662
678
  }
663
679
 
664
- const children = await datum.item.loadChildren(depth);
665
- datum.children = buildTreeNodeData(children);
680
+ const
681
+ depthChildren = await datum.item.loadChildren(depth),
682
+ directChildren = _.filter(depthChildren, (child) => { // narrow list to only direct descendants, so buildTreeNodeData can work correctly
683
+ return child.depth === datum.item.depth + 1;
684
+ });
685
+
686
+ datum.children = buildTreeNodeData(directChildren, defaultToExpanded);
666
687
  datum.isExpanded = true;
667
688
 
668
689
  } catch (err) {
@@ -692,23 +713,23 @@ function TreeComponent(props) {
692
713
  });
693
714
  },
694
715
  expandNodes = async (nodes) => {
695
- await expandNodesRecursive(nodes);
716
+
717
+ // load all children of nodes
718
+ for (const node of nodes) {
719
+ await loadChildren(node, 'all');
720
+ }
721
+
722
+ // expand them in UI
723
+ expandNodesRecursive(nodes);
696
724
  buildRowToDatumMap();
697
725
  },
698
- expandNodesRecursive = async (nodes) => {
699
- // TODO: instead of doing everything sequentially,
700
- // load the tree in parallel, using aync functions
701
- // Every time a node loads, it should update the tree.
702
-
703
- for (const node of nodes) {
704
- if (node.item.hasChildren && !node.item.areChildrenLoaded) {
705
- await loadChildren(node, 'all');
706
- }
726
+ expandNodesRecursive = (nodes) => {
727
+ _.each(nodes, (node) => {
707
728
  node.isExpanded = true;
708
729
  if (!_.isEmpty(node.children)) {
709
- await expandNodesRecursive(node.children);
730
+ expandNodesRecursive(node.children);
710
731
  }
711
- }
732
+ });
712
733
  },
713
734
  expandPath = async (cPath, highlight = true) => {
714
735
  // First, close the whole tree.
@@ -56,8 +56,13 @@ export default function TreeNode(props) {
56
56
 
57
57
  {isLoading ?
58
58
  <Spinner px={2} /> :
59
- (hasChildren && !isDragMode ? <IconButton icon={icon} onPress={() => onToggle(datum)} {...testProps('expandBtn')} /> : <Icon as={icon} px={2} />)}
60
-
59
+ (hasChildren && !isDragMode ?
60
+ <IconButton
61
+ icon={icon}
62
+ onPress={(e) => onToggle(datum, e)}
63
+ {...testProps('expandBtn')}
64
+ /> : <Icon as={icon} px={2} />)}
65
+
61
66
  <Text
62
67
  overflow="hidden"
63
68
  textOverflow="ellipsis"
@@ -31,7 +31,7 @@ export default function getIconButtonFromConfig(config, ix, parent) {
31
31
  key={key || ix}
32
32
  parent={parent}
33
33
  reference={key || ix}
34
- onPress={() => handler(parent)}
34
+ onPress={(e) => handler(parent, e)}
35
35
  icon={icon}
36
36
  _icon={_icon}
37
37
  isDisabled={isDisabled}