useChildrenState.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { useCallback, useState } from 'react';
  2. import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
  3. /**
  4. * Children state means whether spans are collapsed or not. Also provides some functions to manipulate that state.
  5. */
  6. export function useChildrenState() {
  7. const [childrenHiddenIDs, setChildrenHiddenIDs] = useState(new Set<string>());
  8. const expandOne = useCallback(
  9. function expandOne(spans: TraceSpan[]) {
  10. if (childrenHiddenIDs.size === 0) {
  11. return;
  12. }
  13. let prevExpandedDepth = -1;
  14. let expandNextHiddenSpan = true;
  15. const newChildrenHiddenIDs = spans.reduce((res, s) => {
  16. if (s.depth <= prevExpandedDepth) {
  17. expandNextHiddenSpan = true;
  18. }
  19. if (expandNextHiddenSpan && res.has(s.spanID)) {
  20. res.delete(s.spanID);
  21. expandNextHiddenSpan = false;
  22. prevExpandedDepth = s.depth;
  23. }
  24. return res;
  25. }, new Set(childrenHiddenIDs));
  26. setChildrenHiddenIDs(newChildrenHiddenIDs);
  27. },
  28. [childrenHiddenIDs]
  29. );
  30. const collapseOne = useCallback(
  31. function collapseOne(spans: TraceSpan[]) {
  32. if (shouldDisableCollapse(spans, childrenHiddenIDs)) {
  33. return;
  34. }
  35. let nearestCollapsedAncestor: TraceSpan | undefined;
  36. const newChildrenHiddenIDs = spans.reduce((res, curSpan) => {
  37. if (nearestCollapsedAncestor && curSpan.depth <= nearestCollapsedAncestor.depth) {
  38. res.add(nearestCollapsedAncestor.spanID);
  39. if (curSpan.hasChildren) {
  40. nearestCollapsedAncestor = curSpan;
  41. }
  42. } else if (curSpan.hasChildren && !res.has(curSpan.spanID)) {
  43. nearestCollapsedAncestor = curSpan;
  44. }
  45. return res;
  46. }, new Set(childrenHiddenIDs));
  47. // The last one
  48. if (nearestCollapsedAncestor) {
  49. newChildrenHiddenIDs.add(nearestCollapsedAncestor.spanID);
  50. }
  51. setChildrenHiddenIDs(newChildrenHiddenIDs);
  52. },
  53. [childrenHiddenIDs]
  54. );
  55. const expandAll = useCallback(function expandAll() {
  56. setChildrenHiddenIDs(new Set<string>());
  57. }, []);
  58. const collapseAll = useCallback(
  59. function collapseAll(spans: TraceSpan[]) {
  60. if (shouldDisableCollapse(spans, childrenHiddenIDs)) {
  61. return;
  62. }
  63. const newChildrenHiddenIDs = spans.reduce((res, s) => {
  64. if (s.hasChildren) {
  65. res.add(s.spanID);
  66. }
  67. return res;
  68. }, new Set<string>());
  69. setChildrenHiddenIDs(newChildrenHiddenIDs);
  70. },
  71. [childrenHiddenIDs]
  72. );
  73. const childrenToggle = useCallback(
  74. function childrenToggle(spanID: string) {
  75. const newChildrenHiddenIDs = new Set(childrenHiddenIDs);
  76. if (childrenHiddenIDs.has(spanID)) {
  77. newChildrenHiddenIDs.delete(spanID);
  78. } else {
  79. newChildrenHiddenIDs.add(spanID);
  80. }
  81. setChildrenHiddenIDs(newChildrenHiddenIDs);
  82. },
  83. [childrenHiddenIDs]
  84. );
  85. return {
  86. childrenHiddenIDs,
  87. expandOne,
  88. collapseOne,
  89. expandAll,
  90. collapseAll,
  91. childrenToggle,
  92. };
  93. }
  94. function shouldDisableCollapse(allSpans: TraceSpan[], hiddenSpansIds: Set<string>) {
  95. const allParentSpans = allSpans.filter((s) => s.hasChildren);
  96. return allParentSpans.length === hiddenSpansIds.size;
  97. }