@dhis2-ui/organisation-unit-tree 7.2.8 → 7.4.2

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.
Files changed (85) hide show
  1. package/build/cjs/__e2e__/common.js +134 -92
  2. package/build/cjs/__e2e__/controlled_expanded.stories.e2e.js +90 -0
  3. package/build/cjs/__e2e__/path_based_filtering.stories.e2e.js +0 -1
  4. package/build/cjs/__e2e__/single_selection.stories.e2e.js +4 -4
  5. package/build/cjs/__e2e__/tree_api.stories.e2e.js +6 -8
  6. package/build/cjs/__stories__/collapsed.js +22 -0
  7. package/build/cjs/__stories__/custom-expanded-imperative-open.js +184 -0
  8. package/build/cjs/__stories__/custom-node-label.js +33 -0
  9. package/build/cjs/__stories__/development-stories.js +96 -0
  10. package/build/cjs/__stories__/expanded.js +23 -0
  11. package/build/cjs/__stories__/filtered-root.js +25 -0
  12. package/build/cjs/__stories__/filtered.js +24 -0
  13. package/build/cjs/__stories__/force-reload-all.js +58 -0
  14. package/build/cjs/__stories__/force-reload-one-unit.js +37 -0
  15. package/build/cjs/__stories__/highlighted.js +24 -0
  16. package/build/cjs/__stories__/indeterminate.js +24 -0
  17. package/build/cjs/__stories__/loading-error-grandchild.js +44 -0
  18. package/build/cjs/__stories__/loading.js +39 -0
  19. package/build/cjs/__stories__/multiple-roots.js +24 -0
  20. package/build/cjs/__stories__/no-selection.js +26 -0
  21. package/build/cjs/__stories__/replace-roots.js +28 -0
  22. package/build/cjs/__stories__/root-error.js +48 -0
  23. package/build/cjs/__stories__/root-loading.js +48 -0
  24. package/build/cjs/__stories__/selected-multiple.js +25 -0
  25. package/build/cjs/__stories__/shared.js +140 -0
  26. package/build/cjs/__stories__/single-selection.js +26 -0
  27. package/build/cjs/features/controlled_expanded/index.js +60 -0
  28. package/build/cjs/features/controlled_expanded.feature +11 -0
  29. package/build/cjs/features/tree_api/index.js +1 -3
  30. package/build/cjs/get-all-expanded-paths/get-all-expanded-paths.js +40 -0
  31. package/build/cjs/get-all-expanded-paths/get-all-expanded-paths.test.js +17 -0
  32. package/build/cjs/get-all-expanded-paths/index.js +13 -0
  33. package/build/cjs/index.js +9 -1
  34. package/build/cjs/organisation-unit-node/use-open-state.js +11 -16
  35. package/build/cjs/organisation-unit-node/use-open-state.test.js +59 -101
  36. package/build/cjs/organisation-unit-tree/organisation-unit-tree.js +35 -20
  37. package/build/cjs/organisation-unit-tree/organisation-unit-tree.test.js +63 -0
  38. package/build/cjs/organisation-unit-tree/use-expanded/{helpers.js → create-expand-handlers.js} +1 -30
  39. package/build/cjs/organisation-unit-tree/use-expanded/{helpers.test.js → create-expand-handlers.test.js} +5 -18
  40. package/build/cjs/organisation-unit-tree/use-expanded/use-expanded.js +23 -4
  41. package/build/cjs/organisation-unit-tree/use-expanded/use-expanded.test.js +42 -8
  42. package/build/cjs/organisation-unit-tree.stories.js +191 -534
  43. package/build/es/__e2e__/common.js +121 -90
  44. package/build/es/__e2e__/controlled_expanded.stories.e2e.js +68 -0
  45. package/build/es/__e2e__/path_based_filtering.stories.e2e.js +0 -1
  46. package/build/es/__e2e__/single_selection.stories.e2e.js +4 -4
  47. package/build/es/__e2e__/tree_api.stories.e2e.js +6 -7
  48. package/build/es/__stories__/collapsed.js +8 -0
  49. package/build/es/__stories__/custom-expanded-imperative-open.js +166 -0
  50. package/build/es/__stories__/custom-node-label.js +19 -0
  51. package/build/es/__stories__/development-stories.js +73 -0
  52. package/build/es/__stories__/expanded.js +9 -0
  53. package/build/es/__stories__/filtered-root.js +11 -0
  54. package/build/es/__stories__/filtered.js +10 -0
  55. package/build/es/__stories__/force-reload-all.js +38 -0
  56. package/build/es/__stories__/force-reload-one-unit.js +25 -0
  57. package/build/es/__stories__/highlighted.js +10 -0
  58. package/build/es/__stories__/indeterminate.js +10 -0
  59. package/build/es/__stories__/loading-error-grandchild.js +29 -0
  60. package/build/es/__stories__/loading.js +24 -0
  61. package/build/es/__stories__/multiple-roots.js +10 -0
  62. package/build/es/__stories__/no-selection.js +12 -0
  63. package/build/es/__stories__/replace-roots.js +16 -0
  64. package/build/es/__stories__/root-error.js +33 -0
  65. package/build/es/__stories__/root-loading.js +33 -0
  66. package/build/es/__stories__/selected-multiple.js +11 -0
  67. package/build/es/__stories__/shared.js +120 -0
  68. package/build/es/__stories__/single-selection.js +12 -0
  69. package/build/es/features/controlled_expanded/index.js +57 -0
  70. package/build/es/features/controlled_expanded.feature +11 -0
  71. package/build/es/features/tree_api/index.js +1 -3
  72. package/build/es/get-all-expanded-paths/get-all-expanded-paths.js +31 -0
  73. package/build/es/get-all-expanded-paths/get-all-expanded-paths.test.js +14 -0
  74. package/build/es/get-all-expanded-paths/index.js +1 -0
  75. package/build/es/index.js +2 -1
  76. package/build/es/organisation-unit-node/use-open-state.js +11 -16
  77. package/build/es/organisation-unit-node/use-open-state.test.js +59 -94
  78. package/build/es/organisation-unit-tree/organisation-unit-tree.js +15 -1
  79. package/build/es/organisation-unit-tree/organisation-unit-tree.test.js +55 -0
  80. package/build/es/organisation-unit-tree/use-expanded/{helpers.js → create-expand-handlers.js} +0 -23
  81. package/build/es/organisation-unit-tree/use-expanded/{helpers.test.js → create-expand-handlers.test.js} +1 -14
  82. package/build/es/organisation-unit-tree/use-expanded/use-expanded.js +21 -3
  83. package/build/es/organisation-unit-tree/use-expanded/use-expanded.test.js +40 -7
  84. package/build/es/organisation-unit-tree.stories.js +23 -465
  85. package/package.json +5 -5
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const Filtered = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ name: "Root org unit",
7
+ roots: ['A0000000000'],
8
+ initiallyExpanded: ['/A0000000000/A0000000001'],
9
+ filter: ['/A0000000000/A0000000001']
10
+ });
@@ -0,0 +1,38 @@
1
+ import _JSXStyle from "styled-jsx/style";
2
+ import { Button } from '@dhis2/ui';
3
+ import React, { useState } from 'react';
4
+ import { OrganisationUnitTree } from '../index.js';
5
+ import { onChange } from './shared.js';
6
+ export const ForceReloadAll = () => {
7
+ const [forceReload, _setForceReload] = useState(false);
8
+
9
+ const setForceReload = v => console.log('setForceReload', v) || _setForceReload(v);
10
+
11
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
12
+ disabled: forceReload,
13
+ onClick: () => setForceReload(true)
14
+ }, "Reload org unit tree"), ' ', /*#__PURE__*/React.createElement("span", {
15
+ className: "jsx-2109967648"
16
+ }, "(Force reload: ", forceReload ? 'true' : 'false', ")"), /*#__PURE__*/React.createElement("div", {
17
+ className: "jsx-2109967648"
18
+ }, /*#__PURE__*/React.createElement(OrganisationUnitTree, {
19
+ onChange: onChange,
20
+ forceReload: forceReload,
21
+ name: "Root org unit",
22
+ roots: ['A0000000000'],
23
+ initiallyExpanded: ['/A0000000000/A0000000001'],
24
+ selected: ['/A0000000000/A0000000001/A0000000003'],
25
+ onChildrenLoaded: data => {
26
+ const {
27
+ id
28
+ } = data;
29
+
30
+ if (id === 'A0000000000') {
31
+ setForceReload(false);
32
+ }
33
+ }
34
+ })), /*#__PURE__*/React.createElement(_JSXStyle, {
35
+ id: "2109967648"
36
+ }, ["div.jsx-2109967648{width:400px;border:1px solid black;margin-top:32px;padding:16px;min-height:200px;}"]));
37
+ };
38
+ ForceReloadAll.storyName = 'Force reload all';
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ export const ForceReloadOneUnit = () => {
3
+ return /*#__PURE__*/React.createElement("p", null, "This is currently not working due to limitations of the data engine in the app runtime."); //const [idsThatShouldBeReloaded, setIdsThatShouldBeReloaded] = useState([])
4
+ //useEffect(() => {
5
+ // setTimeout(() => setIdsThatShouldBeReloaded(['A0000000001']), delay)
6
+ //}, [])
7
+ //return (
8
+ // <OrganisationUnitTree
9
+ // onChange={onChange}
10
+ // idsThatShouldBeReloaded={idsThatShouldBeReloaded}
11
+ // name="Root org unit"
12
+ // roots={['A0000000000']}
13
+ // initiallyExpanded={['/A0000000000', '/A0000000000/A0000000001']}
14
+ // selected={['/A0000000000/A0000000001/A0000000003']}
15
+ // onChildrenLoaded={({ path, forced }) =>
16
+ // console.log(
17
+ // `Unit with path "${path}" loaded, was forced: ${
18
+ // forced ? 'yes' : 'no'
19
+ // }`
20
+ // )
21
+ // }
22
+ // />
23
+ //)
24
+ };
25
+ ForceReloadOneUnit.storyName = 'Force reload one unit';
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const Highlighted = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ highlighted: ['/A0000000000/A0000000001'],
7
+ name: "Root org unit",
8
+ roots: ['A0000000000'],
9
+ initiallyExpanded: ['/A0000000000']
10
+ });
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const Indeterminate = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ name: "Root org unit",
7
+ roots: ['A0000000000'],
8
+ selected: ['/A0000000000/A0000000001'],
9
+ initiallyExpanded: ['/A0000000000']
10
+ });
@@ -0,0 +1,29 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime';
2
+ import React from 'react';
3
+ import { OrganisationUnitTree } from '../index.js';
4
+ import { customData, onChange, onExpand, onCollapse, onChildrenLoaded } from './shared.js';
5
+ export const LoadingErrorGrandchild = () => /*#__PURE__*/React.createElement(CustomDataProvider, {
6
+ data: { ...customData,
7
+ organisationUnits: (...args) => {
8
+ const [, {
9
+ id
10
+ }] = args;
11
+
12
+ if (id === 'A0000000003') {
13
+ return Promise.reject('Loading org unit 4 and 5 failed');
14
+ }
15
+
16
+ return customData.organisationUnits(...args);
17
+ }
18
+ }
19
+ }, /*#__PURE__*/React.createElement(OrganisationUnitTree, {
20
+ autoExpandLoadingError: true,
21
+ name: "Root org unit",
22
+ roots: ['A0000000000'],
23
+ onChange: onChange,
24
+ onExpand: onExpand,
25
+ onCollapse: onCollapse,
26
+ onChildrenLoaded: onChildrenLoaded,
27
+ initiallyExpanded: ['/A0000000000/A0000000001']
28
+ }));
29
+ LoadingErrorGrandchild.storyName = 'Loading error grandchild';
@@ -0,0 +1,24 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime';
2
+ import React from 'react';
3
+ import { OrganisationUnitTree } from '../index.js';
4
+ import { customData, onChange } from './shared.js';
5
+ export const Loading = () => /*#__PURE__*/React.createElement(CustomDataProvider, {
6
+ data: { ...customData,
7
+ organisationUnits: (...args) => {
8
+ const [, {
9
+ id
10
+ }] = args;
11
+
12
+ if (id === 'A0000000001') {
13
+ return new Promise(() => null);
14
+ }
15
+
16
+ return customData.organisationUnits(...args);
17
+ }
18
+ }
19
+ }, /*#__PURE__*/React.createElement(OrganisationUnitTree, {
20
+ onChange: onChange,
21
+ name: "Root org unit",
22
+ roots: ['A0000000000'],
23
+ initiallyExpanded: ['/A0000000000/A0000000001']
24
+ }));
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const MultipleRoots = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ name: "Root org unit",
7
+ roots: ['A0000000000', 'A0000000001'],
8
+ initiallyExpanded: ['/A0000000000/A0000000001']
9
+ });
10
+ MultipleRoots.storyName = 'Multiple roots';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const NoSelection = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ disableSelection: true,
7
+ name: "Root org unit",
8
+ roots: ['A0000000000'],
9
+ selected: ['/A0000000000/A0000000001'],
10
+ initiallyExpanded: ['/A0000000000']
11
+ });
12
+ NoSelection.storyName = 'No selection';
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ export const ReplaceRoots = () => {
3
+ return /*#__PURE__*/React.createElement("p", null, "This is currently not working due to limitations of the data engine in the app runtime. Normally the root unit would've been replaced after 1000 milliseconds."); //const [roots, setRoots] = useState(['A0000000000'])
4
+ //useEffect(() => {
5
+ // setTimeout(() => setRoots(['A0000000001']), delay)
6
+ //}, [])
7
+ //return (
8
+ // <OrganisationUnitTree
9
+ // name="Root org unit"
10
+ // roots={roots}
11
+ // onChange={console.log.bind(null, 'onChange')}
12
+ // initiallyExpanded={['/A0000000001']}
13
+ // />
14
+ //)
15
+ };
16
+ ReplaceRoots.storyName = 'Replace roots';
@@ -0,0 +1,33 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime';
2
+ import React from 'react';
3
+ import { OrganisationUnitTree } from '../index.js';
4
+ import { customData, onChange } from './shared.js';
5
+ export const RootError = () => /*#__PURE__*/React.createElement(CustomDataProvider, {
6
+ data: { ...customData,
7
+ organisationUnits: (...args) => {
8
+ const [, {
9
+ id
10
+ }] = args;
11
+
12
+ if (id === 'A0000000000') {
13
+ return Promise.reject('This is a custom error message, it could be anything');
14
+ }
15
+
16
+ return customData.organisationUnits(...args);
17
+ }
18
+ }
19
+ }, /*#__PURE__*/React.createElement("fieldset", {
20
+ style: {
21
+ maxWidth: 600
22
+ }
23
+ }, /*#__PURE__*/React.createElement("legend", {
24
+ style: {
25
+ padding: '0 10px'
26
+ }
27
+ }, "Custom container (max-width: 600px)"), /*#__PURE__*/React.createElement(OrganisationUnitTree, {
28
+ onChange: onChange,
29
+ name: "Root org unit",
30
+ roots: ['A0000000000'],
31
+ initiallyExpanded: ['/A0000000000/A0000000001']
32
+ })));
33
+ RootError.storyName = 'Root error';
@@ -0,0 +1,33 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime';
2
+ import React from 'react';
3
+ import { OrganisationUnitTree } from '../index.js';
4
+ import { customData, onChange } from './shared.js';
5
+ export const RootLoading = () => /*#__PURE__*/React.createElement(CustomDataProvider, {
6
+ data: { ...customData,
7
+ organisationUnits: (...args) => {
8
+ const [, {
9
+ id
10
+ }] = args;
11
+
12
+ if (id === 'A0000000000') {
13
+ return new Promise(() => null);
14
+ }
15
+
16
+ return customData.organisationUnits(...args);
17
+ }
18
+ }
19
+ }, /*#__PURE__*/React.createElement("fieldset", {
20
+ style: {
21
+ maxWidth: 600
22
+ }
23
+ }, /*#__PURE__*/React.createElement("legend", {
24
+ style: {
25
+ padding: '0 10px'
26
+ }
27
+ }, "Custom container (max-width: 600px)"), /*#__PURE__*/React.createElement(OrganisationUnitTree, {
28
+ onChange: onChange,
29
+ name: "Root org unit",
30
+ roots: ['A0000000000'],
31
+ initiallyExpanded: ['/A0000000000/A0000000001']
32
+ })));
33
+ RootLoading.storyName = 'Root loading';
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const SelectedMultiple = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ name: "Root org unit",
7
+ roots: ['A0000000000'],
8
+ selected: ['/A0000000000/A0000000002', '/A0000000000/A0000000001/A0000000003'],
9
+ initiallyExpanded: ['/A0000000000', '/A0000000000/A0000000001']
10
+ });
11
+ SelectedMultiple.storyName = 'Selected multiple';
@@ -0,0 +1,120 @@
1
+ export const log = true;
2
+ export const onChange = (...args) => log && console.log('onChange', ...args);
3
+ export const onExpand = (...args) => log && console.log('onExpand', ...args);
4
+ export const onCollapse = (...args) => log && console.log('onCollapse', ...args);
5
+ export const onChildrenLoaded = (...args) => log && console.log('onChildrenLoaded', ...args);
6
+ export const customData = {
7
+ organisationUnits: (type, {
8
+ id
9
+ }) => {
10
+ let data;
11
+ let delay = 0;
12
+
13
+ if (id === 'A0000000000') {
14
+ delay = 1000;
15
+ data = {
16
+ id: 'A0000000000',
17
+ path: '/A0000000000',
18
+ displayName: 'Org Unit 1',
19
+ children: [{
20
+ id: 'A0000000001',
21
+ path: '/A0000000000/A0000000001',
22
+ children: [{
23
+ id: 'A0000000003'
24
+ }, {
25
+ id: 'A0000000004'
26
+ }],
27
+ displayName: 'Org Unit 2'
28
+ }, {
29
+ id: 'A0000000002',
30
+ path: '/A0000000000/A0000000002',
31
+ children: [],
32
+ displayName: 'Org Unit 3'
33
+ }, {
34
+ id: 'A0000000006',
35
+ path: '/A0000000000/A0000000006',
36
+ children: [],
37
+ displayName: 'Org Unit 7'
38
+ }]
39
+ };
40
+ }
41
+
42
+ if (id === 'A0000000001') {
43
+ data = {
44
+ id: 'A0000000001',
45
+ path: '/A0000000000/A0000000001',
46
+ displayName: 'Org Unit 2',
47
+ children: [{
48
+ id: 'A0000000003',
49
+ path: '/A0000000000/A0000000001/A0000000003',
50
+ children: [],
51
+ displayName: 'Org Unit 4'
52
+ }, {
53
+ id: 'A0000000004',
54
+ path: '/A0000000000/A0000000001/A0000000004',
55
+ children: [],
56
+ displayName: 'Org Unit 5'
57
+ }]
58
+ };
59
+ }
60
+
61
+ if (id === 'A0000000002') {
62
+ delay = 1000;
63
+ data = {
64
+ displayName: 'Org Unit 3',
65
+ id: 'A0000000002',
66
+ path: '/A0000000000/A0000000002',
67
+ children: []
68
+ };
69
+ }
70
+
71
+ if (id === 'A0000000003') {
72
+ data = {
73
+ displayName: 'Org Unit 4',
74
+ id: 'A0000000003',
75
+ path: '/A0000000000/A0000000001/A0000000003',
76
+ children: [{
77
+ id: 'A0000000007',
78
+ path: '/A0000000000/A0000000001/A0000000003/A0000000007',
79
+ children: [],
80
+ displayName: 'Org Unit 8'
81
+ }]
82
+ };
83
+ }
84
+
85
+ if (id === 'A0000000004') {
86
+ data = {
87
+ displayName: 'Org Unit 5',
88
+ id: 'A0000000004',
89
+ path: '/A0000000000/A0000000001/A0000000004',
90
+ children: []
91
+ };
92
+ }
93
+
94
+ if (id === 'A0000000006') {
95
+ data = {
96
+ displayName: 'Org Unit 7',
97
+ id: 'A0000000006',
98
+ path: '/A0000000000/A0000000006',
99
+ children: []
100
+ };
101
+ }
102
+
103
+ if (id === 'A0000000007') {
104
+ data = {
105
+ displayName: 'Org Unit 8',
106
+ id: 'A0000000007',
107
+ path: '/A0000000000/A0000000001/A0000000003/A0000000007',
108
+ children: []
109
+ };
110
+ }
111
+
112
+ if (!data) {
113
+ return Promise.reject(new Error('404 - Org unit not found'));
114
+ }
115
+
116
+ return new Promise(resolve => {
117
+ setTimeout(() => resolve(data), delay);
118
+ });
119
+ }
120
+ };
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { OrganisationUnitTree } from '../index.js';
3
+ import { onChange } from './shared.js';
4
+ export const SingleSelection = () => /*#__PURE__*/React.createElement(OrganisationUnitTree, {
5
+ onChange: onChange,
6
+ singleSelection: true,
7
+ name: "Root org unit",
8
+ roots: ['A0000000000'],
9
+ selected: ['/A0000000000/A0000000001'],
10
+ initiallyExpanded: ['/A0000000000']
11
+ });
12
+ SingleSelection.storyName = 'Single selection';
@@ -0,0 +1,57 @@
1
+ import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';
2
+ import { getOrganisationUnitData, namespace } from '../../__e2e__/common.js';
3
+
4
+ const expectOrgUnitsToBeDisplayed = ids => {
5
+ const expandedLabels = ids.map(id => getOrganisationUnitData(id).displayName);
6
+ expandedLabels.forEach(label => {
7
+ cy.get(`:contains("${label}")`).should('exist');
8
+ });
9
+ };
10
+
11
+ const expectOrgUnitsToNotBeDisplayed = ids => {
12
+ const expandedLabels = ids.map(id => {
13
+ const data = getOrganisationUnitData(id);
14
+ return data.displayName;
15
+ });
16
+ expandedLabels.forEach(label => {
17
+ cy.get(`:contains("${label}")`).should('not.exist');
18
+ });
19
+ };
20
+
21
+ Given('the initial state of the controlled expanded prop has some paths', () => {
22
+ cy.visitStory(namespace, 'Controlled');
23
+ cy.window().then(win => {
24
+ cy.wrap(win.initiallyExpandedPaths).as('providedPaths');
25
+ });
26
+ });
27
+ When('the org unit tree should is done loading the provided paths', () => {
28
+ cy.window().then(win => {
29
+ const expandedIds = win.initiallyExpandedPaths.map(path => path.match(/[^/]+$/)[0]);
30
+ expectOrgUnitsToBeDisplayed(expandedIds);
31
+ });
32
+ });
33
+ When('the user clicks on a button to collapse one of the opened paths', () => {
34
+ cy.window().then(win => {
35
+ cy.wrap([win.orgUnitPathToExpand]).as('providedPaths');
36
+ });
37
+ cy.get('[data-test="org-unit-toggle"]').click();
38
+ });
39
+ Then('the org unit tree should open the provided paths when done loading', () => {
40
+ cy.get('@providedPaths').then(providedPaths => {
41
+ const providedIds = providedPaths.map(path => path.match(/[^/]+$/)[0]);
42
+ expectOrgUnitsToBeDisplayed(providedIds);
43
+ });
44
+ });
45
+ Then('the path should close', () => {
46
+ cy.get('@providedPaths').then(providedPaths => {
47
+ const providedIds = providedPaths.map(path => path.match(/[^/]+$/)[0]);
48
+ const hiddenChildrenIds = providedIds.reduce((acc, cur) => {
49
+ const curData = getOrganisationUnitData(cur);
50
+ const childrenIds = curData.children.map(({
51
+ id
52
+ }) => id);
53
+ return [...acc, ...childrenIds];
54
+ }, []);
55
+ expectOrgUnitsToNotBeDisplayed(hiddenChildrenIds);
56
+ });
57
+ });
@@ -0,0 +1,11 @@
1
+ Feature: The expanded paths of the org unit tree can be controlled
2
+
3
+ Scenario: The org unit tree expands some paths initially
4
+ Given the initial state of the controlled expanded prop has some paths
5
+ Then the org unit tree should open the provided paths when done loading
6
+
7
+ Scenario: The user collapses a path by pressing a button
8
+ Given the initial state of the controlled expanded prop has some paths
9
+ When the org unit tree should is done loading the provided paths
10
+ When the user clicks on a button to collapse one of the opened paths
11
+ Then the path should close
@@ -98,8 +98,6 @@ Then("the payload contains the loaded children's data", () => {
98
98
  const {
99
99
  args
100
100
  } = calls[calls.length - 1];
101
- expect(args[0]).to.deep.eql(win.dataProviderData.organisationUnits('get', {
102
- id: 'A0000000001'
103
- }));
101
+ expect(args[0].id).to.equal('A0000000001');
104
102
  });
105
103
  });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @template T
3
+ * @param {Array.<T>} arr
4
+ * @returns {Array.<T>}
5
+ */
6
+ const removeDuplicates = arr => Array.from(new Set(arr));
7
+ /**
8
+ * @param {string} path
9
+ * @returns {string[]}
10
+ */
11
+
12
+
13
+ const extractAllPathsFromPath = path => {
14
+ // remove leading slash and split by path delimiter/slashes
15
+ const segments = path.replace(/^\//, '').split('/');
16
+ const withSubPaths = segments.map((segment, index) => {
17
+ // take all segments from 0 to index and join them with the delimiter
18
+ return `/${segments.slice(0, index + 1).join('/')}`;
19
+ });
20
+ return removeDuplicates(withSubPaths);
21
+ };
22
+ /**
23
+ * @param {string[]} initiallyExpanded
24
+ * @returns {string[]}
25
+ */
26
+
27
+
28
+ export const getAllExpandedPaths = initiallyExpanded => initiallyExpanded.reduce((all, curPath) => {
29
+ const allPathsInCurPath = extractAllPathsFromPath(curPath);
30
+ return [...all, ...allPathsInCurPath];
31
+ }, []);
@@ -0,0 +1,14 @@
1
+ import { getAllExpandedPaths } from './get-all-expanded-paths.js';
2
+ describe('OrganisationUnitTree - getAllExpandedPaths', () => {
3
+ const initiallyExpanded = ['/foo/bar/baz', '/foobar/barbaz/bazfoo'];
4
+ it('should include all initiallyExpanded paths in the returned expanded array', () => {
5
+ const actual = getAllExpandedPaths(initiallyExpanded);
6
+ const expected = expect.arrayContaining(initiallyExpanded);
7
+ expect(actual).toEqual(expected);
8
+ });
9
+ it('should include all sub paths of the paths in initiallyExpanded in the returned exanded array', () => {
10
+ const actual = getAllExpandedPaths(initiallyExpanded);
11
+ const expected = expect.arrayContaining(['/foo', '/foo/bar', '/foobar', '/foobar/barbaz']);
12
+ expect(actual).toEqual(expected);
13
+ });
14
+ });
@@ -0,0 +1 @@
1
+ export { getAllExpandedPaths } from './get-all-expanded-paths.js';
package/build/es/index.js CHANGED
@@ -1 +1,2 @@
1
- export { OrganisationUnitTree } from './organisation-unit-tree/index.js';
1
+ export { OrganisationUnitTree } from './organisation-unit-tree/index.js';
2
+ export { getAllExpandedPaths as getAllExpandedOrgUnitPaths } from './get-all-expanded-paths/index.js';
@@ -20,30 +20,25 @@ export const useOpenState = ({
20
20
  }) => {
21
21
  const autoExpand = autoExpandLoadingError && !!errorMessage;
22
22
  const [openedOnceDueToError, setOpenedOnce] = useState(!!errorMessage);
23
- const [open, setOpen] = useState(autoExpand || expanded.includes(path));
24
23
  useEffect(() => {
25
24
  if (autoExpand && !openedOnceDueToError) {
26
- setOpen(true);
25
+ onExpand({
26
+ path
27
+ });
27
28
  setOpenedOnce(true);
28
29
  }
29
30
  }, [autoExpand, openedOnceDueToError]);
31
+ const open = autoExpand && !openedOnceDueToError || !!expanded.includes(path);
30
32
 
31
- const onToggleOpen = () => {
32
- const newOpen = !open;
33
- const payload = {
34
- path
35
- };
36
- setOpen(newOpen);
37
-
38
- if (onExpand && newOpen) {
39
- onExpand(payload);
40
- } else if (onCollapse && !newOpen) {
41
- onCollapse(payload);
42
- }
43
- };
33
+ const onToggleOpen = () => !open ? onExpand({
34
+ path
35
+ }) : onCollapse({
36
+ path
37
+ });
44
38
 
45
39
  return {
46
40
  open,
47
- onToggleOpen
41
+ onToggleOpen,
42
+ openedOnceDueToError
48
43
  };
49
44
  };