@dhis2-ui/organisation-unit-tree 10.16.1 → 10.16.3-alpha.1

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 (142) hide show
  1. package/package.json +8 -7
  2. package/src/__e2e__/children_as_child_nodes.js +23 -0
  3. package/src/__e2e__/common.js +70 -0
  4. package/src/__e2e__/controlled_expanded.js +89 -0
  5. package/src/__e2e__/displaying_loading_error.js +45 -0
  6. package/src/__e2e__/expanded.js +42 -0
  7. package/src/__e2e__/force_reload.js +66 -0
  8. package/src/__e2e__/get-organisation-unit-data.js +119 -0
  9. package/src/__e2e__/highlight.js +23 -0
  10. package/src/__e2e__/loading_state.js +37 -0
  11. package/src/__e2e__/multi_selection.js +24 -0
  12. package/src/__e2e__/namespace.js +1 -0
  13. package/src/__e2e__/no_selection.js +32 -0
  14. package/src/__e2e__/path_based_filtering.js +49 -0
  15. package/src/__e2e__/single_selection.js +46 -0
  16. package/src/__e2e__/sub_unit_as_root.js +28 -0
  17. package/src/__e2e__/tree_api.js +55 -0
  18. package/src/__stories__/collapsed.js +11 -0
  19. package/src/__stories__/custom-expanded-imperative-open.js +181 -0
  20. package/src/__stories__/custom-node-label.js +19 -0
  21. package/src/__stories__/development-stories.js +86 -0
  22. package/src/__stories__/expanded.js +12 -0
  23. package/src/__stories__/filtered-root.js +15 -0
  24. package/src/__stories__/filtered.js +13 -0
  25. package/src/__stories__/force-reload-all.js +46 -0
  26. package/src/__stories__/force-reload-one-unit.js +36 -0
  27. package/src/__stories__/highlighted.js +13 -0
  28. package/src/__stories__/indeterminate.js +13 -0
  29. package/src/__stories__/loading-error-grandchild.js +39 -0
  30. package/src/__stories__/loading.js +27 -0
  31. package/src/__stories__/multiple-roots.js +20 -0
  32. package/src/__stories__/no-selection.js +16 -0
  33. package/src/__stories__/replace-roots.js +28 -0
  34. package/src/__stories__/root-error.js +36 -0
  35. package/src/__stories__/root-loading.js +34 -0
  36. package/src/__stories__/rtl.js +14 -0
  37. package/src/__stories__/selected-multiple.js +18 -0
  38. package/src/__stories__/shared.js +192 -0
  39. package/src/__stories__/single-selection.js +16 -0
  40. package/src/features/children_as_child_nodes/index.js +29 -0
  41. package/src/features/children_as_child_nodes.feature +6 -0
  42. package/src/features/controlled_expanded/index.js +86 -0
  43. package/src/features/controlled_expanded.feature +11 -0
  44. package/src/features/displaying_loading_error/index.js +46 -0
  45. package/src/features/displaying_loading_error.feature +24 -0
  46. package/src/features/expanded/index.js +87 -0
  47. package/src/features/expanded.feature +27 -0
  48. package/src/features/force_reload/index.js +36 -0
  49. package/src/features/force_reload.feature +7 -0
  50. package/src/features/highlight/index.js +9 -0
  51. package/src/features/highlight.feature +5 -0
  52. package/src/features/loading_state/index.js +26 -0
  53. package/src/features/loading_state.feature +7 -0
  54. package/src/features/multi_selection/index.js +94 -0
  55. package/src/features/multi_selection.feature +31 -0
  56. package/src/features/no_selection/index.js +41 -0
  57. package/src/features/no_selection.feature +13 -0
  58. package/src/features/path_based_filtering/index.js +97 -0
  59. package/src/features/path_based_filtering.feature +24 -0
  60. package/src/features/single_selection/index.js +41 -0
  61. package/src/features/single_selection.feature +20 -0
  62. package/src/features/sub_unit_as_root/index.js +83 -0
  63. package/src/features/sub_unit_as_root.feature +34 -0
  64. package/src/features/tree_api/index.js +121 -0
  65. package/src/features/tree_api.feature +37 -0
  66. package/src/get-all-expanded-paths/get-all-expanded-paths.js +32 -0
  67. package/src/get-all-expanded-paths/get-all-expanded-paths.test.js +22 -0
  68. package/src/get-all-expanded-paths/index.js +1 -0
  69. package/src/helpers/index.js +3 -0
  70. package/src/helpers/is-path-included.js +15 -0
  71. package/src/helpers/left-trim-to-root-id.js +3 -0
  72. package/src/helpers/sort-node-children-alphabetically.js +5 -0
  73. package/src/index.js +6 -0
  74. package/src/locales/ar/translations.json +5 -0
  75. package/src/locales/cs/translations.json +5 -0
  76. package/src/locales/en/translations.json +5 -0
  77. package/src/locales/es/translations.json +5 -0
  78. package/src/locales/es_419/translations.json +5 -0
  79. package/src/locales/fr/translations.json +5 -0
  80. package/src/locales/index.js +50 -0
  81. package/src/locales/lo/translations.json +5 -0
  82. package/src/locales/nb/translations.json +5 -0
  83. package/src/locales/nl/translations.json +5 -0
  84. package/src/locales/pt/translations.json +5 -0
  85. package/src/locales/ru/translations.json +5 -0
  86. package/src/locales/uk/translations.json +5 -0
  87. package/src/locales/uz_Latn/translations.json +5 -0
  88. package/src/locales/uz_UZ_Cyrl/translations.json +5 -0
  89. package/src/locales/uz_UZ_Latn/translations.json +5 -0
  90. package/src/locales/vi/translations.json +5 -0
  91. package/src/locales/zh/translations.json +5 -0
  92. package/src/locales/zh_CN/translations.json +5 -0
  93. package/src/organisation-unit-node/compute-child-nodes.js +27 -0
  94. package/src/organisation-unit-node/compute-child-nodes.test.js +85 -0
  95. package/src/organisation-unit-node/error-message.js +23 -0
  96. package/src/organisation-unit-node/has-descendant-selected-paths.js +15 -0
  97. package/src/organisation-unit-node/has-descendant-selected-paths.test.js +30 -0
  98. package/src/organisation-unit-node/index.js +1 -0
  99. package/src/organisation-unit-node/label/disabled-selection-label.js +26 -0
  100. package/src/organisation-unit-node/label/icon-empty.js +31 -0
  101. package/src/organisation-unit-node/label/icon-folder-closed.js +38 -0
  102. package/src/organisation-unit-node/label/icon-folder-open.js +49 -0
  103. package/src/organisation-unit-node/label/icon-single.js +41 -0
  104. package/src/organisation-unit-node/label/icon.js +35 -0
  105. package/src/organisation-unit-node/label/iconized-checkbox.js +67 -0
  106. package/src/organisation-unit-node/label/index.js +1 -0
  107. package/src/organisation-unit-node/label/label-container.js +36 -0
  108. package/src/organisation-unit-node/label/label.js +146 -0
  109. package/src/organisation-unit-node/label/single-selection-label.js +60 -0
  110. package/src/organisation-unit-node/loading-spinner.js +22 -0
  111. package/src/organisation-unit-node/organisation-unit-node-children.js +123 -0
  112. package/src/organisation-unit-node/organisation-unit-node.js +190 -0
  113. package/src/organisation-unit-node/use-open-state.js +37 -0
  114. package/src/organisation-unit-node/use-open-state.test.js +111 -0
  115. package/src/organisation-unit-node/use-org-children.js +63 -0
  116. package/src/organisation-unit-node/use-org-children.test.js +314 -0
  117. package/src/organisation-unit-node/use-org-data/index.js +1 -0
  118. package/src/organisation-unit-node/use-org-data/use-org-data.js +40 -0
  119. package/src/organisation-unit-node/use-org-data/use-org-data.test.js +137 -0
  120. package/src/organisation-unit-tree/default-render-node-label/default-render-node-label.js +1 -0
  121. package/src/organisation-unit-tree/default-render-node-label/index.js +1 -0
  122. package/src/organisation-unit-tree/filter-root-ids.js +9 -0
  123. package/src/organisation-unit-tree/index.js +3 -0
  124. package/src/organisation-unit-tree/organisation-unit-tree-root-error.js +20 -0
  125. package/src/organisation-unit-tree/organisation-unit-tree-root-loading.js +22 -0
  126. package/src/organisation-unit-tree/organisation-unit-tree.js +253 -0
  127. package/src/organisation-unit-tree/organisation-unit-tree.test.js +77 -0
  128. package/src/organisation-unit-tree/use-expanded/create-expand-handlers.js +45 -0
  129. package/src/organisation-unit-tree/use-expanded/create-expand-handlers.test.js +54 -0
  130. package/src/organisation-unit-tree/use-expanded/index.js +1 -0
  131. package/src/organisation-unit-tree/use-expanded/use-expanded.js +42 -0
  132. package/src/organisation-unit-tree/use-expanded/use-expanded.test.js +73 -0
  133. package/src/organisation-unit-tree/use-force-reload.js +22 -0
  134. package/src/organisation-unit-tree/use-force-reload.test.js +43 -0
  135. package/src/organisation-unit-tree/use-root-org-data/index.js +1 -0
  136. package/src/organisation-unit-tree/use-root-org-data/patch-missing-display-name.js +20 -0
  137. package/src/organisation-unit-tree/use-root-org-data/patch-missing-display-name.test.js +24 -0
  138. package/src/organisation-unit-tree/use-root-org-data/use-root-org-data.js +60 -0
  139. package/src/organisation-unit-tree/use-root-org-data/use-root-org-unit.test.js +184 -0
  140. package/src/organisation-unit-tree.e2e.stories.js +28 -0
  141. package/src/organisation-unit-tree.prod.stories.js +70 -0
  142. package/src/prop-types.js +33 -0
@@ -0,0 +1,314 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime'
2
+ import { renderHook, waitFor } from '@testing-library/react'
3
+ import React from 'react'
4
+ import { useOrgChildren } from './use-org-children.js'
5
+
6
+ describe('OrganisationUnitTree - useOrgChildren', () => {
7
+ const dataProviderData = {
8
+ organisationUnits: jest.fn((type, { id }) => {
9
+ if (id === 'A0000000000') {
10
+ return {
11
+ children: [
12
+ {
13
+ id: 'A0000000001',
14
+ path: '/A0000000000/A0000000001',
15
+ children: [],
16
+ displayName: 'Org Unit 2',
17
+ },
18
+ ],
19
+ }
20
+ }
21
+
22
+ return Promise.reject(`No org unit with id "${id}"`)
23
+ }),
24
+ }
25
+
26
+ const wrapper = ({ children }) => (
27
+ <CustomDataProvider data={dataProviderData}>
28
+ {children}
29
+ </CustomDataProvider>
30
+ )
31
+
32
+ const node = {
33
+ id: 'A0000000000',
34
+ path: '/A0000000000',
35
+ displayName: 'Org Unit 1',
36
+ children: 1,
37
+ }
38
+
39
+ it('should respond with `loading: true`, `error: null` and `data: null` initially', async () => {
40
+ const { result } = renderHook(() => useOrgChildren({ node }), {
41
+ wrapper,
42
+ })
43
+
44
+ expect(result.current).toEqual({
45
+ called: true,
46
+ loading: true,
47
+ error: null,
48
+ data: undefined,
49
+ })
50
+
51
+ // Prevent the following error log with
52
+ // "Warning: An update to TestComponent inside a test was not wrapped
53
+ // in act(...)."
54
+ await waitFor(() => {})
55
+ })
56
+
57
+ it('should provide the org unit data', async () => {
58
+ const { result } = renderHook(() => useOrgChildren({ node }), {
59
+ wrapper,
60
+ })
61
+
62
+ await waitFor(() => {
63
+ expect(result.current).toEqual({
64
+ called: true,
65
+ loading: false,
66
+ error: null,
67
+ data: [
68
+ {
69
+ id: 'A0000000001',
70
+ path: '/A0000000000/A0000000001',
71
+ children: [],
72
+ displayName: 'Org Unit 2',
73
+ },
74
+ ],
75
+ })
76
+ })
77
+ })
78
+
79
+ it('should provide the error', async () => {
80
+ const errorWrapper = ({ children }) => (
81
+ <CustomDataProvider
82
+ data={{
83
+ organisationUnits: async () => {
84
+ throw new Error('Error message')
85
+ },
86
+ }}
87
+ >
88
+ {children}
89
+ </CustomDataProvider>
90
+ )
91
+
92
+ const { result } = renderHook(() => useOrgChildren({ node }), {
93
+ wrapper: errorWrapper,
94
+ })
95
+
96
+ await waitFor(() => {
97
+ expect(result.current).toEqual({
98
+ called: true,
99
+ loading: false,
100
+ error: new Error('Error message'),
101
+ data: undefined,
102
+ })
103
+ })
104
+ })
105
+
106
+ it('should call the onComplete callback', async () => {
107
+ const onComplete = jest.fn()
108
+ const options = { onComplete, node }
109
+
110
+ renderHook(() => useOrgChildren(options), { wrapper })
111
+
112
+ await waitFor(() => {
113
+ expect(onComplete).toHaveBeenCalledWith({
114
+ id: 'A0000000000',
115
+ path: '/A0000000000',
116
+ displayName: 'Org Unit 1',
117
+ children: [
118
+ {
119
+ id: 'A0000000001',
120
+ path: '/A0000000000/A0000000001',
121
+ children: [],
122
+ displayName: 'Org Unit 2',
123
+ },
124
+ ],
125
+ })
126
+ })
127
+ })
128
+
129
+ it("should sort the node's children alphabetically by default", async () => {
130
+ const dataProviderDataWithUnsortedChildren = {
131
+ organisationUnits: jest.fn((type, { id }) => {
132
+ if (id === 'A0000000000') {
133
+ return {
134
+ children: [
135
+ {
136
+ id: 'A0000000002',
137
+ path: '/A0000000000/A0000000002',
138
+ children: [],
139
+ displayName: 'Org Unit 3',
140
+ },
141
+ {
142
+ id: 'A0000000001',
143
+ path: '/A0000000000/A0000000001',
144
+ children: [],
145
+ displayName: 'Org Unit 2',
146
+ },
147
+ ],
148
+ }
149
+ }
150
+
151
+ return Promise.reject(`No org unit with id "${id}"`)
152
+ }),
153
+ }
154
+
155
+ const wrapperWithUnsortedChildren = ({ children }) => (
156
+ <CustomDataProvider data={dataProviderDataWithUnsortedChildren}>
157
+ {children}
158
+ </CustomDataProvider>
159
+ )
160
+
161
+ const { result } = renderHook(
162
+ () => useOrgChildren({ node: { ...node, children: 2 } }),
163
+ { wrapper: wrapperWithUnsortedChildren }
164
+ )
165
+
166
+ await waitFor(() => {
167
+ expect(result.current).toEqual({
168
+ called: true,
169
+ loading: false,
170
+ error: null,
171
+ data: [
172
+ {
173
+ id: 'A0000000001',
174
+ path: '/A0000000000/A0000000001',
175
+ children: [],
176
+ displayName: 'Org Unit 2',
177
+ },
178
+ {
179
+ id: 'A0000000002',
180
+ path: '/A0000000000/A0000000002',
181
+ children: [],
182
+ displayName: 'Org Unit 3',
183
+ },
184
+ ],
185
+ })
186
+ })
187
+ })
188
+
189
+ it(`should not sort the node's children alphabetically when "suppressAlphabeticalSorting" is true`, async () => {
190
+ const dataProviderDataWithUnsortedChildren = {
191
+ organisationUnits: jest.fn((type, { id }) => {
192
+ if (id === 'A0000000000') {
193
+ return {
194
+ children: [
195
+ {
196
+ id: 'A0000000002',
197
+ path: '/A0000000000/A0000000002',
198
+ children: [],
199
+ displayName: 'Org Unit 3',
200
+ },
201
+ {
202
+ id: 'A0000000001',
203
+ path: '/A0000000000/A0000000001',
204
+ children: [],
205
+ displayName: 'Org Unit 2',
206
+ },
207
+ ],
208
+ }
209
+ }
210
+
211
+ return Promise.reject(`No org unit with id "${id}"`)
212
+ }),
213
+ }
214
+
215
+ const wrapperWithUnsortedChildren = ({ children }) => (
216
+ <CustomDataProvider data={dataProviderDataWithUnsortedChildren}>
217
+ {children}
218
+ </CustomDataProvider>
219
+ )
220
+
221
+ const options = {
222
+ node: { ...node, children: 2 },
223
+ suppressAlphabeticalSorting: true,
224
+ }
225
+ const { result } = renderHook(() => useOrgChildren(options), {
226
+ wrapper: wrapperWithUnsortedChildren,
227
+ })
228
+
229
+ await waitFor(() => {
230
+ expect(result.current).toEqual({
231
+ called: true,
232
+ loading: false,
233
+ error: null,
234
+ data: [
235
+ {
236
+ id: 'A0000000002',
237
+ path: '/A0000000000/A0000000002',
238
+ children: [],
239
+ displayName: 'Org Unit 3',
240
+ },
241
+ {
242
+ id: 'A0000000001',
243
+ path: '/A0000000000/A0000000001',
244
+ children: [],
245
+ displayName: 'Org Unit 2',
246
+ },
247
+ ],
248
+ })
249
+ })
250
+ })
251
+
252
+ it(`should not sort the node's children alphabetically when "suppressAlphabeticalSorting" is true`, async () => {
253
+ const dataProviderDataWithUnsortedChildren = {
254
+ organisationUnits: jest.fn((type, { id }) => {
255
+ if (id === 'A0000000000') {
256
+ return {
257
+ children: [
258
+ {
259
+ id: 'A0000000002',
260
+ path: '/A0000000000/A0000000002',
261
+ children: [],
262
+ displayName: 'Org Unit 3',
263
+ },
264
+ {
265
+ id: 'A0000000001',
266
+ path: '/A0000000000/A0000000001',
267
+ children: [],
268
+ displayName: 'Org Unit 2',
269
+ },
270
+ ],
271
+ }
272
+ }
273
+
274
+ return Promise.reject(`No org unit with id "${id}"`)
275
+ }),
276
+ }
277
+
278
+ const wrapperWithUnsortedChildren = ({ children }) => (
279
+ <CustomDataProvider data={dataProviderDataWithUnsortedChildren}>
280
+ {children}
281
+ </CustomDataProvider>
282
+ )
283
+
284
+ const options = {
285
+ node: { ...node, children: 2 },
286
+ suppressAlphabeticalSorting: true,
287
+ }
288
+ const { result } = renderHook(() => useOrgChildren(options), {
289
+ wrapper: wrapperWithUnsortedChildren,
290
+ })
291
+
292
+ await waitFor(() => {
293
+ expect(result.current).toEqual({
294
+ called: true,
295
+ loading: false,
296
+ error: null,
297
+ data: [
298
+ {
299
+ id: 'A0000000002',
300
+ path: '/A0000000000/A0000000002',
301
+ children: [],
302
+ displayName: 'Org Unit 3',
303
+ },
304
+ {
305
+ id: 'A0000000001',
306
+ path: '/A0000000000/A0000000001',
307
+ children: [],
308
+ displayName: 'Org Unit 2',
309
+ },
310
+ ],
311
+ })
312
+ })
313
+ })
314
+ })
@@ -0,0 +1 @@
1
+ export { useOrgData } from './use-org-data.js'
@@ -0,0 +1,40 @@
1
+ import { useDataQuery } from '@dhis2/app-runtime'
2
+
3
+ const ORG_DATA_QUERY = {
4
+ orgUnit: {
5
+ resource: `organisationUnits`,
6
+ id: ({ id }) => id,
7
+ params: ({ isUserDataViewFallback }) => ({
8
+ isUserDataViewFallback,
9
+ fields: ['path', 'children::size'],
10
+ }),
11
+ },
12
+ }
13
+
14
+ /**
15
+ * @param {string[]} ids
16
+ * @param {Object} options
17
+ * @param {string} options.displayName
18
+ * @param {bool} options.isUserDataViewFallback
19
+ * @returns {Object}
20
+ */
21
+ export const useOrgData = (id, { displayName, isUserDataViewFallback }) => {
22
+ if (!displayName) {
23
+ throw new Error('"displayName" is required')
24
+ }
25
+
26
+ const variables = { id, isUserDataViewFallback }
27
+ const {
28
+ loading,
29
+ error,
30
+ data = {},
31
+ } = useDataQuery(ORG_DATA_QUERY, {
32
+ variables,
33
+ })
34
+
35
+ return {
36
+ loading,
37
+ error: error || null,
38
+ data: { id, displayName, ...data.orgUnit },
39
+ }
40
+ }
@@ -0,0 +1,137 @@
1
+ import { CustomDataProvider } from '@dhis2/app-runtime'
2
+ import { renderHook, waitFor } from '@testing-library/react'
3
+ import React from 'react'
4
+ import { useOrgData } from './use-org-data.js'
5
+
6
+ describe('OrganisationUnitTree - useOrgData', () => {
7
+ // @TODO: Figure out why this is necessary at all...
8
+ const origError = console.error
9
+ jest.spyOn(console, 'error').mockImplementation((...args) => {
10
+ const [err] = args
11
+
12
+ if (!err.toString().match(/^Warning: An update to/)) {
13
+ origError(...args)
14
+ }
15
+ })
16
+
17
+ afterAll(() => {
18
+ console.error.mockRestore()
19
+ })
20
+
21
+ const dataProviderData = {
22
+ organisationUnits: jest.fn((type, { id }) => {
23
+ if (id === 'A0000000000') {
24
+ return {
25
+ id: 'A0000000000',
26
+ path: '/A0000000000',
27
+ displayName: 'Org Unit 1',
28
+ }
29
+ }
30
+
31
+ return Promise.reject(`No org unit with id "${id}"`)
32
+ }),
33
+ }
34
+
35
+ const wrapper = ({ children }) => (
36
+ <CustomDataProvider data={dataProviderData}>
37
+ {children}
38
+ </CustomDataProvider>
39
+ )
40
+
41
+ it('should respond with `loading: true`, `error: null` and `data: { displayName, id }` initially', () => {
42
+ const { result } = renderHook(
43
+ () => useOrgData('A0000000000', { displayName: 'Display name' }),
44
+ { wrapper }
45
+ )
46
+
47
+ expect(result.current).toEqual({
48
+ loading: true,
49
+ error: null,
50
+ data: { displayName: 'Display name', id: 'A0000000000' },
51
+ })
52
+ })
53
+
54
+ it('should provide the org unit data', async () => {
55
+ const { result } = renderHook(
56
+ () => useOrgData('A0000000000', { displayName: 'Display name' }),
57
+ { wrapper }
58
+ )
59
+
60
+ await waitFor(() => {
61
+ expect(result.current).toEqual({
62
+ loading: false,
63
+ error: null,
64
+ data: {
65
+ id: 'A0000000000',
66
+ path: '/A0000000000',
67
+ displayName: 'Org Unit 1',
68
+ },
69
+ })
70
+ })
71
+ })
72
+
73
+ it('should provide the error', async () => {
74
+ const errorWrapper = ({ children }) => (
75
+ <CustomDataProvider
76
+ data={{
77
+ organisationUnits: async () => {
78
+ throw new Error('Error message')
79
+ },
80
+ }}
81
+ >
82
+ {children}
83
+ </CustomDataProvider>
84
+ )
85
+
86
+ const { result } = renderHook(
87
+ () => useOrgData('A0000000000', { displayName: 'Display name' }),
88
+ { wrapper: errorWrapper }
89
+ )
90
+
91
+ await waitFor(() => {
92
+ expect(result.current).toEqual({
93
+ loading: false,
94
+ error: new Error('Error message'),
95
+ data: { displayName: 'Display name', id: 'A0000000000' },
96
+ })
97
+ })
98
+ })
99
+
100
+ it('should send the "isUserDataViewFallback" parameter with value "undefined"', async () => {
101
+ const options = { displayName: 'Display name' }
102
+
103
+ renderHook(() => useOrgData('A0000000000', options), { wrapper })
104
+ await waitFor(() => {
105
+ expect(dataProviderData.organisationUnits).toHaveBeenCalledWith(
106
+ 'read',
107
+ expect.objectContaining({
108
+ params: expect.objectContaining({
109
+ isUserDataViewFallback: undefined,
110
+ }),
111
+ }),
112
+ expect.objectContaining({}) // contains the `signal`
113
+ )
114
+ })
115
+ })
116
+
117
+ it('should send the "isUserDataViewFallback" parameter with value "true"', async () => {
118
+ const options = {
119
+ isUserDataViewFallback: true,
120
+ displayName: 'Display name',
121
+ }
122
+
123
+ renderHook(() => useOrgData('A0000000000', options), { wrapper })
124
+
125
+ await waitFor(() => {
126
+ expect(dataProviderData.organisationUnits).toHaveBeenCalledWith(
127
+ 'read',
128
+ expect.objectContaining({
129
+ params: expect.objectContaining({
130
+ isUserDataViewFallback: true,
131
+ }),
132
+ }),
133
+ expect.objectContaining({}) // contains the `signal`
134
+ )
135
+ })
136
+ })
137
+ })
@@ -0,0 +1 @@
1
+ export const defaultRenderNodeLabel = ({ label }) => label
@@ -0,0 +1 @@
1
+ export { defaultRenderNodeLabel } from './default-render-node-label.js'
@@ -0,0 +1,9 @@
1
+ import { isPathIncluded } from '../helpers/index.js'
2
+
3
+ export const filterRootIds = (filter, rootIds) => {
4
+ if (!filter?.length) {
5
+ return rootIds
6
+ }
7
+
8
+ return rootIds.filter((rootId) => isPathIncluded(filter, `/${rootId}`))
9
+ }
@@ -0,0 +1,3 @@
1
+ export { OrganisationUnitTree } from './organisation-unit-tree.js'
2
+ export { OrganisationUnitTreeRootError } from './organisation-unit-tree-root-error.js'
3
+ export { OrganisationUnitTreeRootLoading } from './organisation-unit-tree-root-loading.js'
@@ -0,0 +1,20 @@
1
+ import PropTypes from 'prop-types'
2
+ import React from 'react'
3
+ import i18n from '../locales/index.js'
4
+
5
+ export const OrganisationUnitTreeRootError = ({
6
+ dataTest = 'dhis2-uiwidgets-orgunittree-error',
7
+ error,
8
+ }) => (
9
+ <div data-test={dataTest}>
10
+ {i18n.t('Error: {{ ERRORMESSAGE }}', {
11
+ ERRORMESSAGE: error,
12
+ nsSeparator: '>',
13
+ })}
14
+ </div>
15
+ )
16
+
17
+ OrganisationUnitTreeRootError.propTypes = {
18
+ error: PropTypes.string.isRequired,
19
+ dataTest: PropTypes.string,
20
+ }
@@ -0,0 +1,22 @@
1
+ import { CircularLoader } from '@dhis2-ui/loader'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ export const OrganisationUnitTreeRootLoading = ({
6
+ dataTest = 'dhis2-uiwidgets-orgunittree-loading',
7
+ }) => (
8
+ <div data-test={dataTest}>
9
+ <CircularLoader small />
10
+
11
+ <style jsx>{`
12
+ div {
13
+ display: flex;
14
+ justify-content: center;
15
+ }
16
+ `}</style>
17
+ </div>
18
+ )
19
+
20
+ OrganisationUnitTreeRootLoading.propTypes = {
21
+ dataTest: PropTypes.string,
22
+ }