@dhis2-ui/transfer 10.16.2 → 10.16.3
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 +10 -9
- package/src/__e2e__/add_remove-highlighted-options.e2e.stories.js +30 -0
- package/src/__e2e__/common/options.js +90 -0
- package/src/__e2e__/common/stateful-decorator.js +33 -0
- package/src/__e2e__/common.js +0 -0
- package/src/__e2e__/disabled-transfer-buttons.e2e.stories.js +49 -0
- package/src/__e2e__/disabled-transfer-options.e2e.stories.js +21 -0
- package/src/__e2e__/display-order.e2e.stories.js +24 -0
- package/src/__e2e__/filter-options-list.e2e.stories.js +87 -0
- package/src/__e2e__/highlight-range-of-options.e2e.stories.js +52 -0
- package/src/__e2e__/loading_lists.e2e.stories.js +26 -0
- package/src/__e2e__/notify_at_end_of_list.e2e.stories.js +116 -0
- package/src/__e2e__/reorder-with-buttons.e2e.stories.js +35 -0
- package/src/__e2e__/set_unset-highlighted-option.e2e.stories.js +30 -0
- package/src/__e2e__/transferring-items.e2e.stories.js +27 -0
- package/src/__tests__/common.test.js +131 -0
- package/src/__tests__/helper/add-all-selectable-source-options.test.js +46 -0
- package/src/__tests__/helper/add-individual-source-options.test.js +80 -0
- package/src/__tests__/helper/default-filter-callback.test.js +45 -0
- package/src/__tests__/helper/is-reorder-down-disabled.test.js +96 -0
- package/src/__tests__/helper/is-reorder-up-disabled.test.js +96 -0
- package/src/__tests__/helper/move-highlighted-picked-option-down.test.js +111 -0
- package/src/__tests__/helper/move-highlighted-picked-option-to-bottom.test.js +101 -0
- package/src/__tests__/helper/move-highlighted-picked-option-to-top.test.js +101 -0
- package/src/__tests__/helper/move-highlighted-picked-option-up.test.js +111 -0
- package/src/__tests__/helper/remove-all-picked-options.test.js +29 -0
- package/src/__tests__/helper/remove-individual-picked-options.test.js +38 -0
- package/src/__tests__/helper/use-highlighted-option/create-toggle-highlighted-option.test.js +104 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-add.test.js +84 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-range.test.js +150 -0
- package/src/__tests__/helper/use-highlighted-option/toggle-replace.test.js +39 -0
- package/src/__tests__/helper/use-highlighted-option.test.js +41 -0
- package/src/__tests__/reordering-actions.test.js +165 -0
- package/src/__tests__/transfer.test.js +137 -0
- package/src/actions.js +33 -0
- package/src/add-all.js +27 -0
- package/src/add-individual.js +27 -0
- package/src/common/find-option-index.js +9 -0
- package/src/common/get-mode-by-modifier-key.js +35 -0
- package/src/common/index.js +5 -0
- package/src/common/is-option.js +7 -0
- package/src/common/modes.js +11 -0
- package/src/common/remove-option.js +19 -0
- package/src/common/toggle-value.js +18 -0
- package/src/container.js +23 -0
- package/src/end-intersection-detector.js +37 -0
- package/src/features/add_remove-highlighted-options/index.js +92 -0
- package/src/features/add_remove-highlighted-options.feature +41 -0
- package/src/features/common/index.js +8 -0
- package/src/features/disabled-transfer-buttons/index.js +118 -0
- package/src/features/disabled-transfer-buttons.feature +46 -0
- package/src/features/disabled-transfer-options/index.js +182 -0
- package/src/features/disabled-transfer-options.feature +42 -0
- package/src/features/display-order/index.js +205 -0
- package/src/features/display-order.feature +30 -0
- package/src/features/filter-options-list/index.js +133 -0
- package/src/features/filter-options-list.feature +40 -0
- package/src/features/highlight-range-of-options/index.js +336 -0
- package/src/features/highlight-range-of-options.feature +70 -0
- package/src/features/loading_lists/index.js +43 -0
- package/src/features/loading_lists.feature +19 -0
- package/src/features/notify_at_end_of_list/index.js +125 -0
- package/src/features/notify_at_end_of_list.feature +64 -0
- package/src/features/reorder-with-buttons/index.js +181 -0
- package/src/features/reorder-with-buttons.feature +138 -0
- package/src/features/set_unset-highlighted-option/index.js +121 -0
- package/src/features/set_unset-highlighted-option.feature +42 -0
- package/src/features/transferring-items/index.js +375 -0
- package/src/features/transferring-items.feature +44 -0
- package/src/filter.js +38 -0
- package/src/icons.js +194 -0
- package/src/index.js +2 -0
- package/src/left-footer.js +22 -0
- package/src/left-header.js +22 -0
- package/src/left-side.js +34 -0
- package/src/locales/en/translations.json +7 -0
- package/src/locales/index.js +16 -0
- package/src/options-container.js +127 -0
- package/src/remove-all.js +27 -0
- package/src/remove-individual.js +27 -0
- package/src/reordering-actions.js +136 -0
- package/src/right-footer.js +22 -0
- package/src/right-header.js +22 -0
- package/src/right-side.js +33 -0
- package/src/transfer/add-all-selectable-source-options.js +37 -0
- package/src/transfer/add-individual-source-options.js +61 -0
- package/src/transfer/create-double-click-handlers.js +36 -0
- package/src/transfer/default-filter-callback.js +17 -0
- package/src/transfer/get-highlighted-picked-indices.js +26 -0
- package/src/transfer/get-option-click-handlers.js +19 -0
- package/src/transfer/index.js +17 -0
- package/src/transfer/is-reorder-down-disabled.js +34 -0
- package/src/transfer/is-reorder-up-disabled.js +30 -0
- package/src/transfer/move-highlighted-picked-option-down.js +54 -0
- package/src/transfer/move-highlighted-picked-option-to-bottom.js +44 -0
- package/src/transfer/move-highlighted-picked-option-to-top.js +38 -0
- package/src/transfer/move-highlighted-picked-option-up.js +47 -0
- package/src/transfer/remove-all-picked-options.js +13 -0
- package/src/transfer/remove-individual-picked-options.js +49 -0
- package/src/transfer/use-filter.js +17 -0
- package/src/transfer/use-highlighted-options/create-toggle-highlighted-option.js +64 -0
- package/src/transfer/use-highlighted-options/toggle-add.js +20 -0
- package/src/transfer/use-highlighted-options/toggle-range.js +61 -0
- package/src/transfer/use-highlighted-options/toggle-replace.js +26 -0
- package/src/transfer/use-highlighted-options.js +34 -0
- package/src/transfer/use-options-key-monitor.js +41 -0
- package/src/transfer-option.js +91 -0
- package/src/transfer.js +539 -0
- package/src/transfer.prod.stories.js +621 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
import { parseSelectorWithDataTest } from '../../../../../cypress/support/common/parseSelectorWithDataTest.js'
|
|
3
|
+
import { extractOptionFromElement } from '../common/index.js'
|
|
4
|
+
|
|
5
|
+
Given('some options are selectable', () => {
|
|
6
|
+
cy.visitStory('Transfer Transferring Items', 'Has Options')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
Given('some options are selected', () => {
|
|
10
|
+
cy.visitStory('Transfer Transferring Items', 'Some Selected')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
Given('one or more items in the options list are highlighted', () => {
|
|
14
|
+
cy.get('{transfer-sourceoptions} {transferoption}')
|
|
15
|
+
.filter((index) => index < 3)
|
|
16
|
+
// shuffle order so we can check they're added in the right order
|
|
17
|
+
.then(($options) => cy.wrap([$options[2], $options[0], $options[1]]))
|
|
18
|
+
.each(($option) => cy.wrap($option).clickWith('ctrl'))
|
|
19
|
+
.then(($options) => $options.toArray().map(extractOptionFromElement))
|
|
20
|
+
.as('itemsToBeSelected')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
Given('some items in the options list are highlighted', () => {
|
|
24
|
+
cy.get('{transfer-sourceoptions} {transferoption}')
|
|
25
|
+
.filter((index) => index < 3)
|
|
26
|
+
// shuffle order so we can check they're added in the right order
|
|
27
|
+
.then(($options) => cy.wrap([$options[2], $options[0], $options[1]]))
|
|
28
|
+
.each(($option) => cy.wrap($option).clickWith('ctrl'))
|
|
29
|
+
.then(($options) => $options.toArray().map(extractOptionFromElement))
|
|
30
|
+
.as('itemsToBeSelected')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
Given('some items in the selected list are highlighted', () => {
|
|
34
|
+
cy.get('{transfer-pickedoptions} {transferoption}')
|
|
35
|
+
.filter((index) => index < 3)
|
|
36
|
+
// shuffle order so we can check they're added in the right order
|
|
37
|
+
.then(($options) => cy.wrap([$options[2], $options[0], $options[1]]))
|
|
38
|
+
.each(($option) => cy.wrap($option).clickWith('ctrl'))
|
|
39
|
+
.then(($options) => $options.toArray().map(extractOptionFromElement))
|
|
40
|
+
.as('itemsToBeDeselected')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
When("the user clicks the 'move to selected list' button", () => {
|
|
44
|
+
cy.get('{transfer-actions-addindividual}').click()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
When("the user clicks the 'move to options list' button", () => {
|
|
48
|
+
cy.get('{transfer-actions-removeindividual}').click()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
When("the user clicks the 'move all to selected list' button", () => {
|
|
52
|
+
cy.get('{transfer-sourceoptions} {transferoption}')
|
|
53
|
+
.then(($options) => $options.toArray().map(extractOptionFromElement))
|
|
54
|
+
.as('itemsToBeSelected')
|
|
55
|
+
cy.get('{transfer-actions-addall}').click()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
When("the user clicks the 'move all to options list' button", () => {
|
|
59
|
+
cy.get('{transfer-pickedoptions} {transferoption}')
|
|
60
|
+
.then(($options) => $options.toArray().map(extractOptionFromElement))
|
|
61
|
+
.as('itemsToBeDeselected')
|
|
62
|
+
cy.get('{transfer-actions-removeall}').click()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
When('the user double clicks an item in the options list', () => {
|
|
66
|
+
cy.get('{transfer-sourceoptions} {transferoption}')
|
|
67
|
+
.first()
|
|
68
|
+
.dblclick()
|
|
69
|
+
.then(extractOptionFromElement)
|
|
70
|
+
.as('doubleClickedPlainOption')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
When('the user double clicks an item in the selected list', () => {
|
|
74
|
+
cy.get('{transfer-pickedoptions} {transferoption}')
|
|
75
|
+
.first()
|
|
76
|
+
.dblclick()
|
|
77
|
+
.then(extractOptionFromElement)
|
|
78
|
+
.as('doubleClickedPlainOption')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
Then('the highlighted items should be removed from the options list', () => {
|
|
82
|
+
cy.all(
|
|
83
|
+
() => cy.get('@itemsToBeSelected'),
|
|
84
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}')
|
|
85
|
+
).should(([itemsToBeSelected, $selectableSourceOptions]) => {
|
|
86
|
+
const selectableSourceOptions = $selectableSourceOptions
|
|
87
|
+
.toArray()
|
|
88
|
+
.map(extractOptionFromElement)
|
|
89
|
+
const itemsStillSelectable = itemsToBeSelected.every(
|
|
90
|
+
(itemToBeSelected) => {
|
|
91
|
+
const result = selectableSourceOptions.find(
|
|
92
|
+
({ label, value }) =>
|
|
93
|
+
label === itemToBeSelected.label &&
|
|
94
|
+
value === itemToBeSelected.value
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return result
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
expect(itemsStillSelectable).to.equal(false)
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
Then('the highlighted items should be visible in the selected list', () => {
|
|
106
|
+
cy.all(
|
|
107
|
+
() => cy.get('@itemsToBeSelected'),
|
|
108
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
109
|
+
).should(([itemsToBeSelected, $selectedOptions]) => {
|
|
110
|
+
const selectedOptions = $selectedOptions
|
|
111
|
+
.toArray()
|
|
112
|
+
.map(extractOptionFromElement)
|
|
113
|
+
const itemsSelected = itemsToBeSelected.every((itemToBeSelected) =>
|
|
114
|
+
selectedOptions.find(
|
|
115
|
+
({ label, value }) =>
|
|
116
|
+
label === itemToBeSelected.label &&
|
|
117
|
+
value === itemToBeSelected.value
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
expect(itemsSelected).to.equal(true)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
Then(
|
|
126
|
+
'the highlighted items should be appended to the selected list in the order they were highlighted',
|
|
127
|
+
() => {
|
|
128
|
+
cy.all(
|
|
129
|
+
() => cy.get('@itemsToBeSelected'),
|
|
130
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
131
|
+
).should(([itemsToBeSelected, $selectedOptions]) => {
|
|
132
|
+
const lastNSelectedOptions = $selectedOptions
|
|
133
|
+
.toArray()
|
|
134
|
+
.map(extractOptionFromElement)
|
|
135
|
+
.slice(itemsToBeSelected.length * -1)
|
|
136
|
+
|
|
137
|
+
expect(itemsToBeSelected).to.eql(lastNSelectedOptions)
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
Then('the highlighted items should be removed from the selected list', () => {
|
|
143
|
+
cy.all(
|
|
144
|
+
() => cy.get('@itemsToBeDeselected'),
|
|
145
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
146
|
+
).should(([itemsToBeDeselected, $selectedOptions]) => {
|
|
147
|
+
const selectedOptions = $selectedOptions
|
|
148
|
+
.toArray()
|
|
149
|
+
.map(extractOptionFromElement)
|
|
150
|
+
const itemsStillSelected = itemsToBeDeselected.every(
|
|
151
|
+
(itemToBeSelected) => {
|
|
152
|
+
const result = selectedOptions.find(
|
|
153
|
+
({ label, value }) =>
|
|
154
|
+
label === itemToBeSelected.label &&
|
|
155
|
+
value === itemToBeSelected.value
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return result
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
expect(itemsStillSelected).to.equal(false)
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
Then('the highlighted items should be visible in the options list', () => {
|
|
167
|
+
cy.all(
|
|
168
|
+
() => cy.get('@itemsToBeDeselected'),
|
|
169
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}')
|
|
170
|
+
).should(([itemsToBeDeselected, $selectedOptions]) => {
|
|
171
|
+
const selectedOptions = $selectedOptions
|
|
172
|
+
.toArray()
|
|
173
|
+
.map(extractOptionFromElement)
|
|
174
|
+
const itemsSelectable = itemsToBeDeselected.every(
|
|
175
|
+
(itemToBeSelected) => {
|
|
176
|
+
const result = selectedOptions.find(
|
|
177
|
+
({ label, value }) =>
|
|
178
|
+
label === itemToBeSelected.label &&
|
|
179
|
+
value === itemToBeSelected.value
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return result
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
expect(itemsSelectable).to.equal(true)
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
Then(
|
|
191
|
+
'the highlighted items should be in the original options list ordering',
|
|
192
|
+
() => {
|
|
193
|
+
cy.all(
|
|
194
|
+
() => cy.window(),
|
|
195
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}'),
|
|
196
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
197
|
+
).should(([win, $selectableSourceOptions, $selectedOptions]) => {
|
|
198
|
+
const selectedOptions = $selectedOptions
|
|
199
|
+
.toArray()
|
|
200
|
+
.map(extractOptionFromElement)
|
|
201
|
+
const selectableSourceOptions = $selectableSourceOptions
|
|
202
|
+
.toArray()
|
|
203
|
+
.map(extractOptionFromElement)
|
|
204
|
+
const allOptionsWithoutSelected = win.options.filter((option) => {
|
|
205
|
+
return !selectedOptions.find(
|
|
206
|
+
({ label, value }) =>
|
|
207
|
+
option.label === label && option.value === value
|
|
208
|
+
)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
expect(allOptionsWithoutSelected).to.eql(selectableSourceOptions)
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
Then('all items should be removed from the options list', () => {
|
|
217
|
+
cy.get('{transfer-sourceoptions} {transferoption}').should('not.exist')
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
Then(
|
|
221
|
+
'all items removed from options list should be visible in the selected list',
|
|
222
|
+
() => {
|
|
223
|
+
cy.all(
|
|
224
|
+
() => cy.get('@itemsToBeSelected'),
|
|
225
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
226
|
+
).should(([itemsToBeSelected, $selectedOptions]) => {
|
|
227
|
+
const selectedOptions = $selectedOptions
|
|
228
|
+
.toArray()
|
|
229
|
+
.map(extractOptionFromElement)
|
|
230
|
+
const allSelected = itemsToBeSelected.every((option) => {
|
|
231
|
+
return selectedOptions.find(
|
|
232
|
+
({ label, value }) =>
|
|
233
|
+
option.label === label && option.value === value
|
|
234
|
+
)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
expect(allSelected).to.equal(true)
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
Then('all items should be removed from the selected list', () => {
|
|
243
|
+
cy.get('{transfer-pickedoptions} {transferoption}').should('not.exist')
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
Then(
|
|
247
|
+
'all items removed from selected list should be visible in the options list',
|
|
248
|
+
() => {
|
|
249
|
+
cy.all(
|
|
250
|
+
() => cy.get('@itemsToBeDeselected'),
|
|
251
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}')
|
|
252
|
+
).should(([itemsToBeDeselected, $selectableSourceOptions]) => {
|
|
253
|
+
const selectableSourceOptions = $selectableSourceOptions
|
|
254
|
+
.toArray()
|
|
255
|
+
.map(extractOptionFromElement)
|
|
256
|
+
const allSelectable = itemsToBeDeselected.every((option) => {
|
|
257
|
+
return selectableSourceOptions.find(
|
|
258
|
+
({ label, value }) =>
|
|
259
|
+
option.label === label && option.value === value
|
|
260
|
+
)
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
expect(allSelectable).to.equal(true)
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
Then(
|
|
269
|
+
'the transferred items should be appended to the selected list in the order they were displayed in the options list',
|
|
270
|
+
() => {
|
|
271
|
+
cy.all(
|
|
272
|
+
() => cy.get('@itemsToBeSelected'),
|
|
273
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
274
|
+
).should(([itemsToBeSelected, $selectedOptions]) => {
|
|
275
|
+
const selectedOptions = $selectedOptions
|
|
276
|
+
.toArray()
|
|
277
|
+
.map(extractOptionFromElement)
|
|
278
|
+
const previouslySelectedSubset = selectedOptions.slice(
|
|
279
|
+
-1 * itemsToBeSelected.length
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
expect(itemsToBeSelected).to.eql(previouslySelectedSubset)
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
Then('the options list items should be ordered in the original order', () => {
|
|
288
|
+
cy.all(
|
|
289
|
+
() => cy.window(),
|
|
290
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}'),
|
|
291
|
+
() =>
|
|
292
|
+
cy.get('{transfer-pickedoptions}').then(($pickedOptions) => {
|
|
293
|
+
return $pickedOptions.find(
|
|
294
|
+
parseSelectorWithDataTest('{transferoption}')
|
|
295
|
+
)
|
|
296
|
+
})
|
|
297
|
+
).should(([win, $selectableSourceOptions, $pickedOptions]) => {
|
|
298
|
+
const pickedPlainOptions = $pickedOptions
|
|
299
|
+
.toArray()
|
|
300
|
+
.map(extractOptionFromElement)
|
|
301
|
+
|
|
302
|
+
const originalOrderWithoutSelected = win.options.filter(
|
|
303
|
+
(originalOption) => {
|
|
304
|
+
return !pickedPlainOptions.find(
|
|
305
|
+
(pickedPlainOption) =>
|
|
306
|
+
pickedPlainOption.value === originalOption.value &&
|
|
307
|
+
pickedPlainOption.label === originalOption.label
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
const selectableSourceOptions = $selectableSourceOptions
|
|
313
|
+
.toArray()
|
|
314
|
+
.map(extractOptionFromElement)
|
|
315
|
+
|
|
316
|
+
expect(originalOrderWithoutSelected).to.eql(selectableSourceOptions)
|
|
317
|
+
})
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
Then('the item should be removed from its options list', () => {
|
|
321
|
+
cy.all(
|
|
322
|
+
() => cy.get('@doubleClickedPlainOption'),
|
|
323
|
+
() => cy.get('{transfer-sourceoptions} {transferoption}')
|
|
324
|
+
).should(([doubleClickedPlainOption, $sourceOptions]) => {
|
|
325
|
+
const sourcePlainOptions = $sourceOptions
|
|
326
|
+
.toArray()
|
|
327
|
+
.map(extractOptionFromElement)
|
|
328
|
+
|
|
329
|
+
const found = sourcePlainOptions.find(
|
|
330
|
+
(sourcePlainOption) =>
|
|
331
|
+
sourcePlainOption.value === doubleClickedPlainOption.value &&
|
|
332
|
+
sourcePlainOption.label === doubleClickedPlainOption.label
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
expect(found).to.not.equal(true)
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
Then('the item should be visible at the bottom of the selected list', () => {
|
|
340
|
+
cy.all(
|
|
341
|
+
() => cy.get('@doubleClickedPlainOption'),
|
|
342
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
343
|
+
).should(([doubleClickedPlainOption, $pickedOptions]) => {
|
|
344
|
+
const lastSourcePlainOption = $pickedOptions
|
|
345
|
+
.last()
|
|
346
|
+
.toArray()
|
|
347
|
+
.map(extractOptionFromElement)
|
|
348
|
+
.pop()
|
|
349
|
+
|
|
350
|
+
const doubleClickedOptionIsLast =
|
|
351
|
+
lastSourcePlainOption.value === doubleClickedPlainOption.value &&
|
|
352
|
+
lastSourcePlainOption.label === doubleClickedPlainOption.label
|
|
353
|
+
|
|
354
|
+
expect(doubleClickedOptionIsLast).to.equal(true)
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
Then('the item should be removed from the selected list', () => {
|
|
359
|
+
cy.all(
|
|
360
|
+
() => cy.get('@doubleClickedPlainOption'),
|
|
361
|
+
() => cy.get('{transfer-pickedoptions} {transferoption}')
|
|
362
|
+
).should(([doubleClickedPlainOption, $pickedOptions]) => {
|
|
363
|
+
const pickedPlainOptions = $pickedOptions
|
|
364
|
+
.toArray()
|
|
365
|
+
.map(extractOptionFromElement)
|
|
366
|
+
|
|
367
|
+
const found = pickedPlainOptions.find(
|
|
368
|
+
(sourcePlainOption) =>
|
|
369
|
+
sourcePlainOption.value === doubleClickedPlainOption.value &&
|
|
370
|
+
sourcePlainOption.label === doubleClickedPlainOption.label
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
expect(found).to.not.equal(true)
|
|
374
|
+
})
|
|
375
|
+
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@component-transfer @transferring
|
|
2
|
+
Feature: Transferring items between lists
|
|
3
|
+
|
|
4
|
+
Scenario: The user selects multiple items
|
|
5
|
+
Given some options are selectable
|
|
6
|
+
And some items in the options list are highlighted
|
|
7
|
+
When the user clicks the 'move to selected list' button
|
|
8
|
+
Then the highlighted items should be removed from the options list
|
|
9
|
+
And the highlighted items should be visible in the selected list
|
|
10
|
+
And the highlighted items should be appended to the selected list in the order they were highlighted
|
|
11
|
+
|
|
12
|
+
Scenario: The user deselects multiple items
|
|
13
|
+
Given some options are selected
|
|
14
|
+
And some items in the selected list are highlighted
|
|
15
|
+
When the user clicks the 'move to options list' button
|
|
16
|
+
Then the highlighted items should be removed from the selected list
|
|
17
|
+
And the highlighted items should be visible in the options list
|
|
18
|
+
And the highlighted items should be in the original options list ordering
|
|
19
|
+
|
|
20
|
+
Scenario: The user selects all items
|
|
21
|
+
Given some options are selected
|
|
22
|
+
When the user clicks the 'move all to selected list' button
|
|
23
|
+
Then all items should be removed from the options list
|
|
24
|
+
And all items removed from options list should be visible in the selected list
|
|
25
|
+
And the transferred items should be appended to the selected list in the order they were displayed in the options list
|
|
26
|
+
|
|
27
|
+
Scenario: The user deselects all items
|
|
28
|
+
Given some options are selected
|
|
29
|
+
When the user clicks the 'move all to options list' button
|
|
30
|
+
Then all items should be removed from the selected list
|
|
31
|
+
And all items removed from selected list should be visible in the options list
|
|
32
|
+
And the options list items should be ordered in the original order
|
|
33
|
+
|
|
34
|
+
Scenario: The user double clicks an item in the options list
|
|
35
|
+
Given some options are selectable
|
|
36
|
+
When the user double clicks an item in the options list
|
|
37
|
+
Then the item should be removed from its options list
|
|
38
|
+
And the item should be visible at the bottom of the selected list
|
|
39
|
+
|
|
40
|
+
Scenario: The user double clicks an item in the selected list
|
|
41
|
+
Given some options are selected
|
|
42
|
+
When the user double clicks an item in the selected list
|
|
43
|
+
Then the item should be removed from the selected list
|
|
44
|
+
And the options list items should be ordered in the original order
|
package/src/filter.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { spacers } from '@dhis2/ui-constants'
|
|
2
|
+
import { Field } from '@dhis2-ui/field'
|
|
3
|
+
import { Input } from '@dhis2-ui/input'
|
|
4
|
+
import PropTypes from 'prop-types'
|
|
5
|
+
import React from 'react'
|
|
6
|
+
|
|
7
|
+
export const Filter = ({ dataTest, filter, onChange, label, placeholder }) => (
|
|
8
|
+
<div data-test={dataTest}>
|
|
9
|
+
<Field label={label} name={dataTest} dataTest={`${dataTest}-field`}>
|
|
10
|
+
<Input
|
|
11
|
+
dense
|
|
12
|
+
dataTest={`${dataTest}-input`}
|
|
13
|
+
type="search"
|
|
14
|
+
placeholder={placeholder}
|
|
15
|
+
value={filter}
|
|
16
|
+
onChange={onChange}
|
|
17
|
+
/>
|
|
18
|
+
</Field>
|
|
19
|
+
|
|
20
|
+
<style jsx>{`
|
|
21
|
+
div {
|
|
22
|
+
padding-bottom: ${spacers.dp8};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
div:first-child {
|
|
26
|
+
padding-top: ${spacers.dp8};
|
|
27
|
+
}
|
|
28
|
+
`}</style>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
Filter.propTypes = {
|
|
33
|
+
dataTest: PropTypes.string.isRequired,
|
|
34
|
+
filter: PropTypes.string.isRequired,
|
|
35
|
+
onChange: PropTypes.func.isRequired,
|
|
36
|
+
label: PropTypes.string,
|
|
37
|
+
placeholder: PropTypes.string,
|
|
38
|
+
}
|
package/src/icons.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { colors, theme } from '@dhis2/ui-constants'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import css from 'styled-jsx/css'
|
|
5
|
+
|
|
6
|
+
const centerButtonStyles = css`
|
|
7
|
+
svg {
|
|
8
|
+
min-width: 20px;
|
|
9
|
+
}
|
|
10
|
+
div.centerButton:dir(rtl) {
|
|
11
|
+
transform: rotate(180deg) translateX(4px);
|
|
12
|
+
}
|
|
13
|
+
`
|
|
14
|
+
|
|
15
|
+
export const IconAddAll = ({ dataTest, disabled }) => (
|
|
16
|
+
<div className="centerButton">
|
|
17
|
+
<svg
|
|
18
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
19
|
+
width="16"
|
|
20
|
+
height="16"
|
|
21
|
+
viewBox="0 0 16 16"
|
|
22
|
+
data-test={dataTest}
|
|
23
|
+
fill={disabled ? theme.disabled : colors.grey800}
|
|
24
|
+
>
|
|
25
|
+
<g fillRule="evenodd">
|
|
26
|
+
<polygon
|
|
27
|
+
fillRule="nonzero"
|
|
28
|
+
points="6 2 4.94 3.06 9.13 7.25 0 7.25 0 8.75 9.13 8.75 4.94 12.94 6 14 12 8"
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<polygon
|
|
32
|
+
fillRule="nonzero"
|
|
33
|
+
points="10 2 8.94 3.06 13.13 7.25 13.9 8 13.13 8.75 8.94 12.94 10 14 16 8"
|
|
34
|
+
/>
|
|
35
|
+
</g>
|
|
36
|
+
</svg>
|
|
37
|
+
<style jsx>{centerButtonStyles}</style>
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
IconAddAll.propTypes = {
|
|
42
|
+
dataTest: PropTypes.string.isRequired,
|
|
43
|
+
disabled: PropTypes.bool,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const IconAddIndividual = ({ dataTest, disabled }) => (
|
|
47
|
+
<div className="centerButton">
|
|
48
|
+
<svg
|
|
49
|
+
fill={disabled ? theme.disabled : colors.grey800}
|
|
50
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
51
|
+
width="16"
|
|
52
|
+
height="16"
|
|
53
|
+
viewBox="0 0 16 16"
|
|
54
|
+
data-test={dataTest}
|
|
55
|
+
>
|
|
56
|
+
<polygon points="8 2 6.94 3.06 11.13 7.25 2 7.25 2 8.75 11.13 8.75 6.94 12.94 8 14 14 8" />
|
|
57
|
+
</svg>
|
|
58
|
+
<style jsx>{centerButtonStyles}</style>
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
IconAddIndividual.propTypes = {
|
|
63
|
+
dataTest: PropTypes.string.isRequired,
|
|
64
|
+
disabled: PropTypes.bool,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const IconRemoveAll = ({ dataTest, disabled }) => (
|
|
68
|
+
<div className="centerButton">
|
|
69
|
+
<svg
|
|
70
|
+
fill={disabled ? theme.disabled : colors.grey800}
|
|
71
|
+
width="16px"
|
|
72
|
+
height="16px"
|
|
73
|
+
viewBox="0 0 16 16"
|
|
74
|
+
data-test={dataTest}
|
|
75
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
76
|
+
>
|
|
77
|
+
<g fillRule="evenodd">
|
|
78
|
+
<polygon
|
|
79
|
+
fillRule="nonzero"
|
|
80
|
+
points="10 2 8.94 3.06 13.13 7.25 4 7.25 4 8.75 13.13 8.75 8.94 12.94 10 14 16 8"
|
|
81
|
+
transform="matrix(-1 0 0 1 20 0)"
|
|
82
|
+
/>
|
|
83
|
+
|
|
84
|
+
<polygon
|
|
85
|
+
fillRule="nonzero"
|
|
86
|
+
points="1.06 2 0 3.06 4.19 7.25 4.96 8 4.19 8.75 0 12.94 1.06 14 7.06 8"
|
|
87
|
+
transform="matrix(-1 0 0 1 7.06 0)"
|
|
88
|
+
/>
|
|
89
|
+
</g>
|
|
90
|
+
</svg>
|
|
91
|
+
<style jsx>{centerButtonStyles}</style>
|
|
92
|
+
</div>
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
IconRemoveAll.propTypes = {
|
|
96
|
+
dataTest: PropTypes.string.isRequired,
|
|
97
|
+
disabled: PropTypes.bool,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const IconRemoveIndividual = ({ dataTest, disabled }) => (
|
|
101
|
+
<div className="centerButton">
|
|
102
|
+
<svg
|
|
103
|
+
fill={disabled ? theme.disabled : colors.grey800}
|
|
104
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
105
|
+
width="16"
|
|
106
|
+
height="16"
|
|
107
|
+
viewBox="0 0 16 16"
|
|
108
|
+
data-test={dataTest}
|
|
109
|
+
>
|
|
110
|
+
<polygon
|
|
111
|
+
points="8 2 6.94 3.06 11.13 7.25 2 7.25 2 8.75 11.13 8.75 6.94 12.94 8 14 14 8"
|
|
112
|
+
transform="matrix(-1 0 0 1 16 0)"
|
|
113
|
+
/>
|
|
114
|
+
</svg>
|
|
115
|
+
<style jsx>{centerButtonStyles}</style>
|
|
116
|
+
</div>
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
IconRemoveIndividual.propTypes = {
|
|
120
|
+
dataTest: PropTypes.string.isRequired,
|
|
121
|
+
disabled: PropTypes.bool,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const IconMoveDown = ({ dataTest, disabled }) => (
|
|
125
|
+
<svg
|
|
126
|
+
fill={disabled ? colors.grey500 : colors.grey800}
|
|
127
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
128
|
+
width="16"
|
|
129
|
+
height="16"
|
|
130
|
+
viewBox="0 0 16 16"
|
|
131
|
+
data-test={dataTest}
|
|
132
|
+
>
|
|
133
|
+
<path d="M13.5303 8.53027L12.4697 7.46973L8.75 11.1895V2H7.25V11.1895L3.53027 7.46973L2.46973 8.53027L8 14.0605L13.5303 8.53027Z" />
|
|
134
|
+
</svg>
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
IconMoveDown.propTypes = {
|
|
138
|
+
dataTest: PropTypes.string.isRequired,
|
|
139
|
+
disabled: PropTypes.bool,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const IconMoveUp = ({ dataTest, disabled }) => (
|
|
143
|
+
<svg
|
|
144
|
+
fill={disabled ? colors.grey500 : colors.grey800}
|
|
145
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
146
|
+
width="16"
|
|
147
|
+
height="16"
|
|
148
|
+
viewBox="0 0 16 16"
|
|
149
|
+
data-test={dataTest}
|
|
150
|
+
>
|
|
151
|
+
<path d="M13.5303 7.46973L12.4697 8.53027L8.75 4.81055V14H7.25V4.81055L3.53027 8.53027L2.46973 7.46973L8 1.93945L13.5303 7.46973Z" />
|
|
152
|
+
</svg>
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
IconMoveUp.propTypes = {
|
|
156
|
+
dataTest: PropTypes.string.isRequired,
|
|
157
|
+
disabled: PropTypes.bool,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const IconMoveToTop = ({ dataTest, disabled }) => (
|
|
161
|
+
<svg
|
|
162
|
+
fill={disabled ? colors.grey500 : colors.grey800}
|
|
163
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
164
|
+
width="16"
|
|
165
|
+
height="16"
|
|
166
|
+
viewBox="0 0 16 16"
|
|
167
|
+
data-test={dataTest}
|
|
168
|
+
>
|
|
169
|
+
<path d="M13.5303 10.4697L12.4697 11.5303L8.75 7.81055V14H7.25V7.81055L3.53027 11.5303L2.46973 10.4697L8 4.93945L13.5303 10.4697ZM13.5303 6.46973L12.4697 7.53027L8 3.06055L3.53027 7.53027L2.46973 6.46973L8 0.939453L13.5303 6.46973Z" />
|
|
170
|
+
</svg>
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
IconMoveToTop.propTypes = {
|
|
174
|
+
dataTest: PropTypes.string.isRequired,
|
|
175
|
+
disabled: PropTypes.bool,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export const IconMoveToBottom = ({ dataTest, disabled }) => (
|
|
179
|
+
<svg
|
|
180
|
+
fill={disabled ? colors.grey500 : colors.grey800}
|
|
181
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
182
|
+
width="16"
|
|
183
|
+
height="16"
|
|
184
|
+
viewBox="0 0 16 16"
|
|
185
|
+
data-test={dataTest}
|
|
186
|
+
>
|
|
187
|
+
<path d="M13.5303 5.53027L12.4697 4.46973L8.75 8.18945V2H7.25V8.18945L3.53027 4.46973L2.46973 5.53027L8 11.0605L13.5303 5.53027ZM13.5303 9.53027L12.4697 8.46973L8 12.9395L3.53027 8.46973L2.46973 9.53027L8 15.0605L13.5303 9.53027Z" />
|
|
188
|
+
</svg>
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
IconMoveToBottom.propTypes = {
|
|
192
|
+
dataTest: PropTypes.string.isRequired,
|
|
193
|
+
disabled: PropTypes.bool,
|
|
194
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { colors, spacers } from '@dhis2/ui-constants'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
|
|
5
|
+
export const LeftFooter = ({ children, dataTest }) => (
|
|
6
|
+
<div data-test={dataTest}>
|
|
7
|
+
{children}
|
|
8
|
+
|
|
9
|
+
<style jsx>{`
|
|
10
|
+
div {
|
|
11
|
+
flex-grow: 0;
|
|
12
|
+
border-top: 1px solid ${colors.grey400};
|
|
13
|
+
padding: 0 ${spacers.dp8};
|
|
14
|
+
}
|
|
15
|
+
`}</style>
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
LeftFooter.propTypes = {
|
|
20
|
+
children: PropTypes.node,
|
|
21
|
+
dataTest: PropTypes.string,
|
|
22
|
+
}
|