orc-shared 5.10.0-dev.2 → 5.10.0-dev.21

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 (186) hide show
  1. package/dist/actions/metadata.js +30 -11
  2. package/dist/actions/requestsApi.js +10 -1
  3. package/dist/components/AppFrame/About.js +136 -100
  4. package/dist/components/AppFrame/Anchor.js +45 -21
  5. package/dist/components/AppFrame/AppFrame.js +53 -31
  6. package/dist/components/AppFrame/Help.js +35 -15
  7. package/dist/components/AppFrame/MenuItem.js +148 -114
  8. package/dist/components/AppFrame/Preferences.js +136 -97
  9. package/dist/components/AppFrame/Sidebar.js +51 -28
  10. package/dist/components/AppFrame/Topbar.js +61 -36
  11. package/dist/components/ColumnWrapper.js +28 -5
  12. package/dist/components/Culture.js +33 -14
  13. package/dist/components/DropMenu/Menu.js +79 -45
  14. package/dist/components/DropMenu/index.js +34 -29
  15. package/dist/components/Form/Combination.js +45 -16
  16. package/dist/components/Form/Field.js +57 -38
  17. package/dist/components/Form/FieldElements.js +0 -11
  18. package/dist/components/Form/Fieldset.js +47 -19
  19. package/dist/components/Form/Form.js +22 -9
  20. package/dist/components/Form/FormElement.js +40 -7
  21. package/dist/components/Form/Inputs/Button.js +63 -18
  22. package/dist/components/Form/Inputs/ReadOnly.js +50 -27
  23. package/dist/components/{AppFrame/ApplicationSelector/Header.js → Form/Inputs/Selector.js} +30 -31
  24. package/dist/components/Form/Inputs/Text.js +20 -37
  25. package/dist/components/Form/Inputs/Toggles.js +39 -40
  26. package/dist/components/Form/Inputs/index.js +2 -13
  27. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.js +31 -11
  28. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/SectionToolbar.js +89 -0
  29. package/dist/components/MaterialUI/DataDisplay/Table.js +109 -18
  30. package/dist/components/MaterialUI/DataDisplay/TableProps.js +5 -1
  31. package/dist/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.js +198 -0
  32. package/dist/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.js +4 -1
  33. package/dist/components/MaterialUI/Inputs/DatePicker.js +14 -14
  34. package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -0
  35. package/dist/components/MaterialUI/Inputs/Select.js +2 -0
  36. package/dist/components/MaterialUI/Inputs/SelectProps.js +2 -0
  37. package/dist/components/MaterialUI/Inputs/Switch.js +17 -1
  38. package/dist/components/MaterialUI/Inputs/SwitchProps.js +2 -0
  39. package/dist/components/MaterialUI/Inputs/TimePicker.js +14 -21
  40. package/dist/components/MaterialUI/hocs/withDeferredTooltip.js +3 -1
  41. package/dist/components/MaterialUI/muiThemes.js +2 -1
  42. package/dist/components/Provision.js +1 -1
  43. package/dist/constants.js +2 -1
  44. package/dist/content/iconsSheet.svg +740 -116
  45. package/dist/hocs/withScrollBox.js +27 -12
  46. package/dist/hooks/useDaysAndMonthsLocalization.js +77 -0
  47. package/dist/hooks/useInMemoryPaging.js +135 -0
  48. package/dist/hooks/useMultipleFieldEditState.js +12 -3
  49. package/dist/reducers/metadata.js +6 -0
  50. package/dist/schemas/metadata.js +9 -1
  51. package/dist/selectors/locale.js +1 -0
  52. package/dist/selectors/metadata.js +14 -11
  53. package/dist/sharedMessages.js +184 -0
  54. package/dist/utils/ListHelper.js +271 -0
  55. package/dist/utils/comparisonHelper.js +185 -0
  56. package/dist/utils/propertyBagHelper.js +3 -1
  57. package/dist/utils/timezoneHelper.js +18 -31
  58. package/package.json +4 -3
  59. package/src/actions/metadata.js +11 -0
  60. package/src/actions/metadata.test.js +27 -0
  61. package/src/actions/requestsApi.js +6 -0
  62. package/src/components/AppFrame/About.js +97 -117
  63. package/src/components/AppFrame/About.test.js +128 -90
  64. package/src/components/AppFrame/Anchor.js +34 -36
  65. package/src/components/AppFrame/Anchor.test.js +5 -68
  66. package/src/components/AppFrame/AppFrame.js +31 -40
  67. package/src/components/AppFrame/AppFrame.test.js +424 -445
  68. package/src/components/AppFrame/Help.js +23 -20
  69. package/src/components/AppFrame/Help.test.js +3 -3
  70. package/src/components/AppFrame/MenuItem.js +106 -126
  71. package/src/components/AppFrame/MenuItem.test.js +78 -169
  72. package/src/components/AppFrame/Preferences.js +110 -98
  73. package/src/components/AppFrame/Preferences.test.js +115 -219
  74. package/src/components/AppFrame/Sidebar.js +39 -41
  75. package/src/components/AppFrame/Sidebar.test.js +88 -168
  76. package/src/components/AppFrame/Topbar.js +59 -52
  77. package/src/components/AppFrame/Topbar.test.js +31 -39
  78. package/src/components/ColumnWrapper.js +18 -9
  79. package/src/components/Culture.js +20 -10
  80. package/src/components/Culture.test.js +27 -16
  81. package/src/components/DropMenu/DropMenu.test.js +185 -224
  82. package/src/components/DropMenu/Menu.js +73 -80
  83. package/src/components/DropMenu/Menu.test.js +35 -86
  84. package/src/components/DropMenu/index.js +19 -15
  85. package/src/components/Form/Combination.js +35 -28
  86. package/src/components/Form/Combination.test.js +6 -19
  87. package/src/components/Form/Field.js +53 -66
  88. package/src/components/Form/Field.test.js +29 -51
  89. package/src/components/Form/FieldElements.js +0 -14
  90. package/src/components/Form/FieldElements.test.js +104 -111
  91. package/src/components/Form/Fieldset.js +42 -37
  92. package/src/components/Form/Fieldset.test.js +14 -7
  93. package/src/components/Form/Form.js +11 -7
  94. package/src/components/Form/Form.test.js +75 -56
  95. package/src/components/Form/FormElement.js +24 -16
  96. package/src/components/Form/InputField.test.js +24 -30
  97. package/src/components/Form/Inputs/Button.js +58 -14
  98. package/src/components/Form/Inputs/Button.test.js +32 -7
  99. package/src/components/Form/Inputs/Inputs.test.js +0 -7
  100. package/src/components/Form/Inputs/ReadOnly.js +34 -28
  101. package/src/components/Form/Inputs/ReadOnly.test.js +45 -7
  102. package/src/components/Form/Inputs/Selector.js +22 -0
  103. package/src/components/Form/Inputs/Selector.test.js +105 -0
  104. package/src/components/Form/Inputs/Text.js +15 -44
  105. package/src/components/Form/Inputs/Text.test.js +20 -29
  106. package/src/components/Form/Inputs/Toggles.js +27 -26
  107. package/src/components/Form/Inputs/Toggles.test.js +22 -28
  108. package/src/components/Form/Inputs/index.js +4 -15
  109. package/src/components/MaterialUI/DataDisplay/PredefinedElements/InformationItem.test.js +1 -4
  110. package/src/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.js +32 -6
  111. package/src/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.test.js +3 -1
  112. package/src/components/MaterialUI/DataDisplay/PredefinedElements/SectionToolbar.js +39 -0
  113. package/src/components/MaterialUI/DataDisplay/Table.js +190 -114
  114. package/src/components/MaterialUI/DataDisplay/Table.test.js +246 -1
  115. package/src/components/MaterialUI/DataDisplay/TableProps.js +4 -0
  116. package/src/components/MaterialUI/DataDisplay/TableProps.test.js +2 -0
  117. package/src/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.js +145 -0
  118. package/src/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.test.js +457 -0
  119. package/src/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.js +5 -1
  120. package/src/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.test.js +7 -1
  121. package/src/components/MaterialUI/Inputs/DatePicker.js +19 -20
  122. package/src/components/MaterialUI/Inputs/DatePicker.test.js +11 -6
  123. package/src/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -0
  124. package/src/components/MaterialUI/Inputs/Select.js +2 -0
  125. package/src/components/MaterialUI/Inputs/SelectProps.js +2 -0
  126. package/src/components/MaterialUI/Inputs/SelectProps.test.js +2 -0
  127. package/src/components/MaterialUI/Inputs/Switch.js +22 -1
  128. package/src/components/MaterialUI/Inputs/Switch.test.js +23 -0
  129. package/src/components/MaterialUI/Inputs/SwitchProps.js +2 -0
  130. package/src/components/MaterialUI/Inputs/SwitchProps.test.js +2 -0
  131. package/src/components/MaterialUI/Inputs/TimePicker.js +10 -19
  132. package/src/components/MaterialUI/Inputs/TimePicker.test.js +278 -117
  133. package/src/components/MaterialUI/hocs/withDeferredTooltip.js +4 -1
  134. package/src/components/MaterialUI/hocs/withDeferredTooltip.test.js +27 -0
  135. package/src/components/MaterialUI/muiThemes.js +1 -0
  136. package/src/components/Navigation/Bar.test.js +92 -87
  137. package/src/components/Provision.js +1 -1
  138. package/src/components/TaskDetailsModal.test.js +1 -3
  139. package/src/constants.js +1 -0
  140. package/src/content/iconsSheet.svg +740 -116
  141. package/src/hocs/withScrollBox.js +32 -19
  142. package/src/hocs/withScrollBox.test.js +15 -3
  143. package/src/hooks/useDaysAndMonthsLocalization.js +79 -0
  144. package/src/hooks/useDaysAndMonthsLocalization.test.js +107 -0
  145. package/src/hooks/useInMemoryPaging.js +78 -0
  146. package/src/hooks/useInMemoryPaging.test.js +515 -0
  147. package/src/hooks/useMultipleFieldEditState.js +11 -4
  148. package/src/hooks/useMultipleFieldEditState.test.js +49 -1
  149. package/src/reducers/metadata.js +6 -1
  150. package/src/reducers/metadata.test.js +31 -0
  151. package/src/requests +1 -0
  152. package/src/schemas/metadata.js +3 -0
  153. package/src/selectors/locale.js +1 -1
  154. package/src/selectors/metadata.js +12 -9
  155. package/src/selectors/metadata.test.js +92 -11
  156. package/src/sharedMessages.js +184 -0
  157. package/src/timezones.json +883 -0
  158. package/src/translations/en-US.json +46 -0
  159. package/src/translations/fr-CA.json +46 -0
  160. package/src/utils/ListHelper.js +203 -0
  161. package/src/utils/ListHelper.test.js +710 -0
  162. package/src/utils/comparisonHelper.js +135 -0
  163. package/src/utils/comparisonHelper.test.js +334 -0
  164. package/src/utils/propertyBagHelper.js +2 -0
  165. package/src/utils/propertyBagHelper.test.js +6 -0
  166. package/src/utils/timezoneHelper.js +10 -135
  167. package/src/utils/timezoneHelper.test.js +7 -7
  168. package/dist/components/Form/FieldList.js +0 -270
  169. package/dist/components/Form/Inputs/FieldButtons.js +0 -66
  170. package/dist/components/Form/Inputs/Number.js +0 -117
  171. package/dist/components/Form/Inputs/SmallButton.js +0 -91
  172. package/dist/components/Form/Inputs/Time.js +0 -86
  173. package/dist/components/Form/Inputs/Translation.js +0 -169
  174. package/src/components/AppFrame/ApplicationSelector/Header.js +0 -34
  175. package/src/components/AppFrame/ApplicationSelector/Header.test.js +0 -23
  176. package/src/components/Form/FieldList.js +0 -210
  177. package/src/components/Form/FieldList.test.js +0 -558
  178. package/src/components/Form/Inputs/FieldButtons.js +0 -90
  179. package/src/components/Form/Inputs/Number.js +0 -60
  180. package/src/components/Form/Inputs/Number.test.js +0 -435
  181. package/src/components/Form/Inputs/SmallButton.js +0 -37
  182. package/src/components/Form/Inputs/SmallButton.test.js +0 -65
  183. package/src/components/Form/Inputs/Time.js +0 -32
  184. package/src/components/Form/Inputs/Time.test.js +0 -41
  185. package/src/components/Form/Inputs/Translation.js +0 -93
  186. package/src/components/Form/Inputs/Translation.test.js +0 -204
@@ -1,558 +0,0 @@
1
- import React from "react";
2
- import Immutable from "immutable";
3
- import { Provider } from "react-redux";
4
- import sinon from "sinon";
5
- import { IntlProvider } from "react-intl";
6
- import { getStyledClassSelector } from "../../utils/testUtils";
7
- import FieldElements from "./FieldElements";
8
- import Field from "./Field";
9
- import { RoundButton } from "./Inputs/SmallButton";
10
- import { FormInput } from "./Inputs/Text";
11
- import { FormContext } from "./Form";
12
- import FieldList, { List, ListControlButton, REMOVE_ROW } from "./FieldList";
13
-
14
- describe("FieldList", () => {
15
- let state, store, clock;
16
- beforeEach(() => {
17
- state = Immutable.fromJS({});
18
- store = {
19
- subscribe: () => {},
20
- dispatch: () => {},
21
- getState: () => state,
22
- };
23
- clock = sinon.useFakeTimers();
24
- });
25
- afterEach(() => {
26
- clock.restore();
27
- });
28
-
29
- it("renders a minimal fixed-length list", () => {
30
- const update = sinon.spy().named("update");
31
- const getUpdater = name => value => update(name, value);
32
- return expect(
33
- <Provider store={store}>
34
- <IntlProvider locale="en">
35
- <FormContext.Provider value={{ values: {} }}>
36
- <FieldList
37
- name="testlistminfixed"
38
- rowField={{ type: "TextInput", name: "data" }}
39
- getUpdater={getUpdater}
40
- rowCount={1}
41
- />
42
- </FormContext.Provider>
43
- </IntlProvider>
44
- </Provider>,
45
- "when mounted",
46
- "to satisfy",
47
- <Provider store={store}>
48
- <FormContext.Provider value={{ values: {} }}>
49
- <List>
50
- <IntlProvider locale="en">
51
- <FieldElements fields={[{ type: "TextInput", name: "data" }]} labelOnly />
52
- </IntlProvider>
53
- <IntlProvider locale="en">
54
- <FieldElements fields={[{ type: "TextInput", name: "data[0]" }]} />
55
- </IntlProvider>
56
- </List>
57
- </FormContext.Provider>
58
- </Provider>,
59
- );
60
- });
61
-
62
- it("renders an empty fixed-length list", () => {
63
- const update = sinon.spy().named("update");
64
- const getUpdater = name => value => update(name, value);
65
- return expect(
66
- <Provider store={store}>
67
- <IntlProvider locale="en">
68
- <FormContext.Provider value={{ values: {} }}>
69
- <FieldList
70
- name="testlistminfixed"
71
- rowField={{ type: "TextInput", name: "data" }}
72
- getUpdater={getUpdater}
73
- rowCount={0}
74
- values={{}}
75
- />
76
- </FormContext.Provider>
77
- </IntlProvider>
78
- </Provider>,
79
- "when mounted",
80
- "to satisfy",
81
- <Provider store={store}>
82
- <List>
83
- <IntlProvider locale="en">
84
- <FormContext.Provider value={{ values: {} }}>
85
- <FieldElements fields={[{ type: "TextInput", name: "data" }]} labelOnly />
86
- </FormContext.Provider>
87
- </IntlProvider>
88
- </List>
89
- </Provider>,
90
- );
91
- });
92
-
93
- it("renders a fixed-length list with static values", () => {
94
- const update = sinon.spy().named("update");
95
- const getUpdater = name => value => update(name, value);
96
- return expect(
97
- <Provider store={store}>
98
- <IntlProvider locale="en">
99
- <FormContext.Provider
100
- value={{
101
- values: {
102
- testlistfixedstat: [
103
- { id: 4, data: "foo" },
104
- { id: 5, data: "bar" },
105
- ],
106
- },
107
- }}
108
- >
109
- <FieldList
110
- name="testlistfixedstat"
111
- rowField={{ type: "TextInput", name: "data", label: "A label" }}
112
- getUpdater={getUpdater}
113
- rowCount={3}
114
- staticValues={[{ stat: true }, { stat: false }, { stat: true }]}
115
- />
116
- </FormContext.Provider>
117
- </IntlProvider>
118
- </Provider>,
119
- "when mounted",
120
- "to satisfy",
121
- <Provider store={store}>
122
- <List>
123
- <IntlProvider locale="en">
124
- <FormContext.Provider value={{ values: {} }}>
125
- <FieldElements fields={[{ type: "TextInput", name: "data", label: "A label" }]} labelOnly />
126
- </FormContext.Provider>
127
- </IntlProvider>
128
- <IntlProvider locale="en">
129
- <FormContext.Provider
130
- value={{
131
- values: { id: 4, data: "foo", stat: true },
132
- listIndex: 0,
133
- }}
134
- >
135
- <FieldElements fields={[{ type: "TextInput", name: "data" }]} />
136
- </FormContext.Provider>
137
- </IntlProvider>
138
- <IntlProvider locale="en">
139
- <FormContext.Provider
140
- value={{
141
- values: { id: 5, data: "bar", stat: false },
142
- listIndex: 1,
143
- }}
144
- >
145
- <FieldElements fields={[{ type: "TextInput", name: "data" }]} />
146
- </FormContext.Provider>
147
- </IntlProvider>
148
- <IntlProvider locale="en">
149
- <FormContext.Provider
150
- value={{
151
- values: {
152
- id: expect.it("to be a number").and("to be greater than", 5),
153
- stat: true,
154
- },
155
- listIndex: 2,
156
- }}
157
- >
158
- <FieldElements fields={[{ type: "TextInput", name: "data" }]} />
159
- </FormContext.Provider>
160
- </IntlProvider>
161
- </List>
162
- </Provider>,
163
- );
164
- });
165
-
166
- it("renders a fixed-length list with tall rows", () => {
167
- const update = sinon.spy().named("update");
168
- const getUpdater = name => value => update(name, value);
169
- return expect(
170
- <Provider store={store}>
171
- <IntlProvider locale="en">
172
- <FormContext.Provider
173
- value={{
174
- values: {
175
- testlisttallrows: [
176
- { id: 4, data: "foo" },
177
- { id: 5, data: "bar" },
178
- ],
179
- },
180
- }}
181
- >
182
- <FieldList
183
- name="testlisttallrows"
184
- rowField={{ type: "TextInput", name: "data", label: "A label" }}
185
- getUpdater={getUpdater}
186
- rowCount={3}
187
- tallRows
188
- staticValues={[{ stat: true }, { stat: false }, { stat: true }]}
189
- />
190
- </FormContext.Provider>
191
- </IntlProvider>
192
- </Provider>,
193
- "when mounted",
194
- "to satisfy",
195
- <Provider store={store}>
196
- <List tallRows>
197
- <IntlProvider locale="en">
198
- <FormContext.Provider
199
- value={{
200
- values: { id: 4, data: "foo", stat: true },
201
- listIndex: 0,
202
- }}
203
- >
204
- <FieldElements fields={[{ type: "TextInput", name: "data", label: "A label" }]} />
205
- </FormContext.Provider>
206
- </IntlProvider>
207
- <IntlProvider locale="en">
208
- <FormContext.Provider
209
- value={{
210
- values: { id: 5, data: "bar", stat: false },
211
- listIndex: 1,
212
- }}
213
- >
214
- <FieldElements fields={[{ type: "TextInput", name: "data", label: "A label" }]} />
215
- </FormContext.Provider>
216
- </IntlProvider>
217
- <IntlProvider locale="en">
218
- <FormContext.Provider
219
- value={{
220
- values: {
221
- id: expect.it("to be a number").and("to be greater than", 5),
222
- stat: true,
223
- },
224
- listIndex: 2,
225
- }}
226
- >
227
- <FieldElements fields={[{ type: "TextInput", name: "data", label: "A label" }]} />
228
- </FormContext.Provider>
229
- </IntlProvider>
230
- </List>
231
- </Provider>,
232
- );
233
- });
234
-
235
- it("can edit values", () => {
236
- const update = sinon.spy().named("update");
237
- const getUpdater = name => value => update(name, value);
238
- return expect(
239
- <Provider store={store}>
240
- <IntlProvider locale="en">
241
- <FormContext.Provider
242
- value={{
243
- values: {
244
- testlistedit: [
245
- { id: 4, data: "foo" },
246
- { id: 5, data: "bar" },
247
- { id: 6, data: "feep" },
248
- ],
249
- },
250
- }}
251
- >
252
- <FieldList
253
- name="testlistedit"
254
- rowField={{ type: "TextInput", name: "data" }}
255
- getUpdater={getUpdater}
256
- rowCount={3}
257
- staticValues={[{ stat: true }, { stat: false }, { stat: true }]}
258
- />
259
- </FormContext.Provider>
260
- </IntlProvider>
261
- </Provider>,
262
- "when mounted",
263
- "with event",
264
- {
265
- type: "change",
266
- value: "New Value",
267
- target: `${getStyledClassSelector(<List />)} > :nth-child(3) ${getStyledClassSelector(FormInput)}`,
268
- },
269
- ).then(() =>
270
- expect(update, "to have calls satisfying", [
271
- {
272
- args: [
273
- "testlistedit",
274
- [
275
- { id: 4, data: "foo" },
276
- { id: 5, data: "New Value" },
277
- { id: 6, data: "feep" },
278
- ],
279
- ],
280
- },
281
- ]),
282
- );
283
- });
284
-
285
- it("renders a minimal variable-length list", () => {
286
- const update = sinon.spy().named("update");
287
- const getUpdater = name => value => update(name, value);
288
- return expect(
289
- <Provider store={store}>
290
- <IntlProvider locale="en">
291
- <FormContext.Provider value={{ values: {} }}>
292
- <FieldList
293
- name="testlistminvar"
294
- rowField={{ type: "TextInput", name: "data" }}
295
- getUpdater={getUpdater}
296
- values={{}}
297
- />
298
- </FormContext.Provider>
299
- </IntlProvider>
300
- </Provider>,
301
- "when mounted",
302
- "to satisfy",
303
- <Provider store={store}>
304
- <IntlProvider locale="en">
305
- <FormContext.Provider value={{ values: {} }}>
306
- <List>
307
- <FieldElements
308
- fields={[
309
- {
310
- type: "Combination",
311
- name: "rowField",
312
- proportions: [100, "30px"],
313
- fields: [
314
- { type: "TextInput", name: "data" },
315
- {
316
- type: "SmallButton",
317
- name: REMOVE_ROW,
318
- primary: true,
319
- icon: "cross",
320
- },
321
- ],
322
- },
323
- ]}
324
- labelOnly
325
- />
326
- <Field>
327
- <ListControlButton>[add]</ListControlButton>
328
- </Field>
329
- </List>
330
- </FormContext.Provider>
331
- </IntlProvider>
332
- </Provider>,
333
- );
334
- });
335
-
336
- it("renders a variable-length list, with values and row addition", () => {
337
- const update = sinon.spy().named("update");
338
- const getUpdater = name => value => update(name, value);
339
- return expect(
340
- <Provider store={store}>
341
- <IntlProvider locale="en">
342
- <FormContext.Provider
343
- value={{
344
- values: {
345
- testlistvaradd: [
346
- { id: 101, data: "foo", num: 55 },
347
- { id: 102, data: "bar", num: 81 },
348
- ],
349
- },
350
- }}
351
- >
352
- <FieldList
353
- name="testlistvaradd"
354
- rowField={{
355
- type: "Combination",
356
- name: "rowField",
357
- proportions: [50, 50],
358
- fields: [
359
- { type: "TextInput", name: "data" },
360
- {
361
- type: "NumberInput",
362
- name: "num",
363
- },
364
- ],
365
- }}
366
- getUpdater={getUpdater}
367
- />
368
- </FormContext.Provider>
369
- </IntlProvider>
370
- </Provider>,
371
- "when mounted",
372
- "to satisfy",
373
- expect
374
- .it(
375
- "to satisfy",
376
- <Provider store={store}>
377
- <IntlProvider locale="en">
378
- <List>
379
- <FormContext.Provider value={{ values: {} }}>
380
- <FieldElements
381
- fields={[
382
- {
383
- type: "Combination",
384
- name: "rowField",
385
- proportions: [50, 50, "30px"],
386
- fields: [
387
- { type: "TextInput", name: "data" },
388
- {
389
- type: "NumberInput",
390
- name: "num",
391
- },
392
- {
393
- type: "SmallButton",
394
- name: REMOVE_ROW,
395
- primary: true,
396
- icon: "cross",
397
- altText: "[remove]",
398
- },
399
- ],
400
- },
401
- ]}
402
- labelOnly
403
- />
404
- </FormContext.Provider>
405
- <FormContext.Provider
406
- value={{
407
- values: { id: 101, data: "foo", num: 55 },
408
- listIndex: 0,
409
- }}
410
- >
411
- <FieldElements
412
- fields={[
413
- {
414
- type: "Combination",
415
- name: "rowField",
416
- proportions: [50, 50, "30px"],
417
- fields: [
418
- { type: "TextInput", name: "data" },
419
- {
420
- type: "NumberInput",
421
- name: "num",
422
- },
423
- {
424
- type: "SmallButton",
425
- name: REMOVE_ROW,
426
- primary: true,
427
- icon: "cross",
428
- altText: "[remove]",
429
- },
430
- ],
431
- },
432
- ]}
433
- />
434
- </FormContext.Provider>
435
- <FormContext.Provider
436
- value={{
437
- values: { id: 102, data: "bar", num: 81 },
438
- listIndex: 1,
439
- }}
440
- >
441
- <FieldElements
442
- fields={[
443
- {
444
- type: "Combination",
445
- name: "rowField",
446
- proportions: [50, 50, "30px"],
447
- fields: [
448
- { type: "TextInput", name: "data" },
449
- {
450
- type: "NumberInput",
451
- name: "num",
452
- },
453
- {
454
- type: "SmallButton",
455
- name: REMOVE_ROW,
456
- primary: true,
457
- icon: "cross",
458
- altText: "[remove]",
459
- },
460
- ],
461
- },
462
- ]}
463
- />
464
- </FormContext.Provider>
465
- <Field>
466
- <ListControlButton>[add]</ListControlButton>
467
- </Field>
468
- </List>
469
- </IntlProvider>
470
- </Provider>,
471
- )
472
- .and("with event", {
473
- type: "click",
474
- target: getStyledClassSelector(ListControlButton),
475
- }),
476
- ).then(() =>
477
- expect(update, "to have calls satisfying", [
478
- {
479
- args: [
480
- "testlistvaradd",
481
- [
482
- { id: 101, data: "foo", num: 55 },
483
- { id: 102, data: "bar", num: 81 },
484
- {
485
- id: expect.it("to be a number").and("to be greater than", 2),
486
- },
487
- ],
488
- ],
489
- },
490
- ]),
491
- );
492
- });
493
-
494
- it("can delete rows", () => {
495
- const update = sinon.spy().named("update");
496
- const getUpdater = name => value => update(name, value);
497
- return expect(
498
- <Provider store={store}>
499
- <IntlProvider locale="en">
500
- <FormContext.Provider
501
- value={{
502
- values: {
503
- testlistrowdel: [
504
- { id: 8, data: "bar" },
505
- { id: 9, data: "foo" },
506
- ],
507
- },
508
- }}
509
- >
510
- <FieldList name="testlistrowdel" rowField={{ type: "TextInput", name: "data" }} getUpdater={getUpdater} />
511
- </FormContext.Provider>
512
- </IntlProvider>
513
- </Provider>,
514
- "when mounted",
515
- "with event",
516
- {
517
- type: "click",
518
- target: `${getStyledClassSelector(<List />)} > :nth-child(2) ${getStyledClassSelector(RoundButton)}`,
519
- },
520
- )
521
- .then(() => clock.tick(1))
522
- .then(() =>
523
- expect(update, "to have calls satisfying", [
524
- {
525
- args: ["testlistrowdel", [{ id: 9, data: "foo" }]],
526
- },
527
- ]),
528
- );
529
- });
530
-
531
- it("will not render inside another list", () =>
532
- expect(
533
- <FormContext.Provider value={{ values: {}, listIndex: 0 }}>
534
- <FieldList listIndex={0} getUpdater={() => () => {}} />
535
- </FormContext.Provider>,
536
- "when mounted",
537
- "to satisfy",
538
- "Cannot render list inside list",
539
- ));
540
- });
541
-
542
- describe("List", () => {
543
- it("sets layout for fieldboxes under it", () =>
544
- expect(
545
- <List />,
546
- "when mounted",
547
- "to have style rules satisfying",
548
- expect.it("to contain", "> .Field__FieldBox").and("to contain", "margin-top: 20px"),
549
- ));
550
-
551
- it("sets layout for fieldboxes under it with tall rows", () =>
552
- expect(
553
- <List tallRows />,
554
- "when mounted",
555
- "to have style rules satisfying",
556
- expect.it("to contain", "> .Field__FieldBox").and("to contain", "border-bottom: 1px solid"),
557
- ));
558
- });
@@ -1,90 +0,0 @@
1
- import styled, { css } from "styled-components";
2
- import Button from "../../Button";
3
- import { ifFlag, getThemeProp } from "../../../utils";
4
-
5
- export const ButtonWrapper = styled.div`
6
- box-sizing: border-box;
7
- display: flex;
8
- align-items: stretch;
9
- height: 30px;
10
- flex: 0 1 auto;
11
- border-radius: 4px;
12
- border: 1px solid ${getThemeProp(["colors", "borderLight"], "#cccccc")};
13
-
14
- & > * {
15
- box-sizing: border-box;
16
- height: 28px;
17
- border: 0 none transparent;
18
- border-radius: 0;
19
- flex: 0 1 100%;
20
- box-shadow: none;
21
- }
22
-
23
- & > :first-child {
24
- border-top-left-radius: 4px;
25
- border-bottom-left-radius: 4px;
26
- }
27
- & > :last-child {
28
- border-top-right-radius: 4px;
29
- border-bottom-right-radius: 4px;
30
- }
31
-
32
- ${ifFlag(
33
- "invalid",
34
- css`
35
- border-color: ${getThemeProp(["colors", "error"], "#ce4844")};
36
-
37
- &:hover,
38
- &:active {
39
- box-shadow: 0 0 4px ${getThemeProp(["colors", "error"], "#ce4844")};
40
- }
41
- `,
42
- )}
43
- `;
44
-
45
- export const Spinners = styled.div`
46
- display: flex;
47
- flex-direction: column;
48
- height: 30px;
49
- flex: 0 0 auto;
50
- margin-top: -1px;
51
- margin-bottom: -1px;
52
-
53
- &:first-child > * {
54
- margin-left: -1px;
55
- }
56
- &:last-child > * {
57
- margin-right: -1px;
58
- }
59
- `;
60
-
61
- export const InputButton = styled(Button)`
62
- padding: 2px 7px;
63
- font-size: 8px;
64
- border-radius: 0;
65
- min-width: 0;
66
- min-height: 0;
67
- flex: 0 0 auto;
68
-
69
- &:active,
70
- &:focus,
71
- &:hover {
72
- z-index: 1;
73
- }
74
-
75
- ${Spinners} > & {
76
- flex: 1 1 50%;
77
- }
78
- ${Spinners}:last-child > & {
79
- margin-top: -1px;
80
-
81
- &:first-child {
82
- margin-top: 0;
83
- border-top-right-radius: 4px;
84
- }
85
- &:last-child {
86
- padding-top: 1px;
87
- border-bottom-right-radius: 4px;
88
- }
89
- }
90
- `;
@@ -1,60 +0,0 @@
1
- import React, { useCallback } from "react";
2
- import { FormInput } from "./Text";
3
- import { ButtonWrapper, Spinners, InputButton } from "./FieldButtons";
4
-
5
- export const roundToStep = (num, step) => {
6
- const parsedNum = parseFloat(num);
7
- if (Number.isNaN(parsedNum) || Number.isNaN(parseFloat(step))) {
8
- return "";
9
- }
10
- const factor = 1 / parseFloat(step);
11
- return Math.floor((parsedNum + 0.5 * step) * factor + Number.EPSILON) / factor;
12
- };
13
-
14
- const nullNaN = (num, nil = 0) => (Number.isNaN(num) ? nil : num);
15
-
16
- const containNumber = (number, max = Number.MAX_VALUE, min = -Number.MAX_VALUE) =>
17
- Number.isFinite(number) ? Math.min(max, Math.max(min, number)) : number;
18
-
19
- export const NumberInput = ({ update, min, max, value = "", step, required, ...props }) => {
20
- const onChange = useCallback(
21
- e =>
22
- step
23
- ? update(containNumber(roundToStep(e.target.value, step), max, min))
24
- : update(containNumber(nullNaN(parseFloat(e.target.value), ""), max, min)),
25
- [update, step, min, max],
26
- );
27
- const increment = useCallback(
28
- () =>
29
- step
30
- ? update(containNumber(roundToStep(value + step, step), max, undefined))
31
- : update(containNumber(nullNaN(parseFloat(value)) + 1, max, undefined)),
32
- [update, value, step, max],
33
- );
34
- const decrement = useCallback(
35
- () =>
36
- step
37
- ? update(containNumber(roundToStep(value - step, step), undefined, min))
38
- : update(containNumber(nullNaN(parseFloat(value)) - 1, undefined, min)),
39
- [update, value, step, min],
40
- );
41
- return (
42
- <ButtonWrapper invalid={required && !value}>
43
- <FormInput
44
- type="number"
45
- step={step}
46
- value={step ? roundToStep(value, step) : value}
47
- onChange={onChange}
48
- {...props}
49
- />
50
- <Spinners>
51
- <InputButton onClick={increment} data-test-id="up">
52
-
53
- </InputButton>
54
- <InputButton onClick={decrement} data-test-id="down">
55
-
56
- </InputButton>
57
- </Spinners>
58
- </ButtonWrapper>
59
- );
60
- };