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

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 (168) 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/DropMenu/Menu.js +79 -45
  13. package/dist/components/DropMenu/index.js +34 -29
  14. package/dist/components/Form/Combination.js +45 -16
  15. package/dist/components/Form/Field.js +57 -38
  16. package/dist/components/Form/FieldElements.js +0 -11
  17. package/dist/components/Form/Fieldset.js +47 -19
  18. package/dist/components/Form/Form.js +22 -9
  19. package/dist/components/Form/FormElement.js +40 -7
  20. package/dist/components/Form/Inputs/Button.js +63 -18
  21. package/dist/components/Form/Inputs/ReadOnly.js +50 -27
  22. package/dist/components/{AppFrame/ApplicationSelector/Header.js → Form/Inputs/Selector.js} +30 -31
  23. package/dist/components/Form/Inputs/Text.js +20 -37
  24. package/dist/components/Form/Inputs/Toggles.js +39 -40
  25. package/dist/components/Form/Inputs/index.js +2 -13
  26. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.js +31 -11
  27. package/dist/components/MaterialUI/DataDisplay/PredefinedElements/SectionToolbar.js +89 -0
  28. package/dist/components/MaterialUI/DataDisplay/Table.js +109 -18
  29. package/dist/components/MaterialUI/DataDisplay/TableProps.js +5 -1
  30. package/dist/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.js +198 -0
  31. package/dist/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.js +4 -1
  32. package/dist/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -0
  33. package/dist/components/MaterialUI/Inputs/Select.js +2 -0
  34. package/dist/components/MaterialUI/Inputs/SelectProps.js +2 -0
  35. package/dist/components/MaterialUI/Inputs/Switch.js +17 -1
  36. package/dist/components/MaterialUI/Inputs/SwitchProps.js +2 -0
  37. package/dist/components/MaterialUI/hocs/withDeferredTooltip.js +3 -1
  38. package/dist/components/MaterialUI/muiThemes.js +2 -1
  39. package/dist/constants.js +2 -1
  40. package/dist/content/iconsSheet.svg +740 -116
  41. package/dist/hocs/withScrollBox.js +27 -12
  42. package/dist/hooks/useInMemoryPaging.js +135 -0
  43. package/dist/hooks/useMultipleFieldEditState.js +12 -3
  44. package/dist/reducers/metadata.js +6 -0
  45. package/dist/schemas/metadata.js +9 -1
  46. package/dist/selectors/locale.js +1 -0
  47. package/dist/selectors/metadata.js +14 -11
  48. package/dist/sharedMessages.js +4 -0
  49. package/dist/utils/ListHelper.js +271 -0
  50. package/dist/utils/comparisonHelper.js +185 -0
  51. package/dist/utils/propertyBagHelper.js +3 -1
  52. package/package.json +1 -1
  53. package/src/actions/metadata.js +11 -0
  54. package/src/actions/metadata.test.js +27 -0
  55. package/src/actions/requestsApi.js +6 -0
  56. package/src/components/AppFrame/About.js +97 -117
  57. package/src/components/AppFrame/About.test.js +128 -90
  58. package/src/components/AppFrame/Anchor.js +34 -36
  59. package/src/components/AppFrame/Anchor.test.js +5 -68
  60. package/src/components/AppFrame/AppFrame.js +31 -40
  61. package/src/components/AppFrame/AppFrame.test.js +424 -445
  62. package/src/components/AppFrame/Help.js +23 -20
  63. package/src/components/AppFrame/Help.test.js +3 -3
  64. package/src/components/AppFrame/MenuItem.js +106 -126
  65. package/src/components/AppFrame/MenuItem.test.js +78 -169
  66. package/src/components/AppFrame/Preferences.js +110 -98
  67. package/src/components/AppFrame/Preferences.test.js +115 -219
  68. package/src/components/AppFrame/Sidebar.js +39 -41
  69. package/src/components/AppFrame/Sidebar.test.js +88 -168
  70. package/src/components/AppFrame/Topbar.js +59 -52
  71. package/src/components/AppFrame/Topbar.test.js +31 -39
  72. package/src/components/ColumnWrapper.js +18 -9
  73. package/src/components/DropMenu/DropMenu.test.js +185 -224
  74. package/src/components/DropMenu/Menu.js +73 -80
  75. package/src/components/DropMenu/Menu.test.js +35 -86
  76. package/src/components/DropMenu/index.js +19 -15
  77. package/src/components/Form/Combination.js +35 -28
  78. package/src/components/Form/Combination.test.js +6 -19
  79. package/src/components/Form/Field.js +53 -66
  80. package/src/components/Form/Field.test.js +29 -51
  81. package/src/components/Form/FieldElements.js +0 -14
  82. package/src/components/Form/FieldElements.test.js +104 -111
  83. package/src/components/Form/Fieldset.js +42 -37
  84. package/src/components/Form/Fieldset.test.js +14 -7
  85. package/src/components/Form/Form.js +11 -7
  86. package/src/components/Form/Form.test.js +75 -56
  87. package/src/components/Form/FormElement.js +24 -16
  88. package/src/components/Form/InputField.test.js +24 -30
  89. package/src/components/Form/Inputs/Button.js +58 -14
  90. package/src/components/Form/Inputs/Button.test.js +32 -7
  91. package/src/components/Form/Inputs/Inputs.test.js +0 -7
  92. package/src/components/Form/Inputs/ReadOnly.js +34 -28
  93. package/src/components/Form/Inputs/ReadOnly.test.js +45 -7
  94. package/src/components/Form/Inputs/Selector.js +22 -0
  95. package/src/components/Form/Inputs/Selector.test.js +105 -0
  96. package/src/components/Form/Inputs/Text.js +15 -44
  97. package/src/components/Form/Inputs/Text.test.js +20 -29
  98. package/src/components/Form/Inputs/Toggles.js +27 -26
  99. package/src/components/Form/Inputs/Toggles.test.js +22 -28
  100. package/src/components/Form/Inputs/index.js +4 -15
  101. package/src/components/MaterialUI/DataDisplay/PredefinedElements/InformationItem.test.js +1 -4
  102. package/src/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.js +32 -6
  103. package/src/components/MaterialUI/DataDisplay/PredefinedElements/Placeholder.test.js +3 -1
  104. package/src/components/MaterialUI/DataDisplay/PredefinedElements/SectionToolbar.js +39 -0
  105. package/src/components/MaterialUI/DataDisplay/Table.js +190 -114
  106. package/src/components/MaterialUI/DataDisplay/Table.test.js +246 -1
  107. package/src/components/MaterialUI/DataDisplay/TableProps.js +4 -0
  108. package/src/components/MaterialUI/DataDisplay/TableProps.test.js +2 -0
  109. package/src/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.js +145 -0
  110. package/src/components/MaterialUI/DataDisplay/TableWithInMemoryPaging.test.js +457 -0
  111. package/src/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.js +5 -1
  112. package/src/components/MaterialUI/DataDisplay/TooltippedElements/MultipleLinesText.test.js +7 -1
  113. package/src/components/MaterialUI/Inputs/PredefinedElements/SearchControl.js +1 -0
  114. package/src/components/MaterialUI/Inputs/Select.js +2 -0
  115. package/src/components/MaterialUI/Inputs/SelectProps.js +2 -0
  116. package/src/components/MaterialUI/Inputs/SelectProps.test.js +2 -0
  117. package/src/components/MaterialUI/Inputs/Switch.js +22 -1
  118. package/src/components/MaterialUI/Inputs/Switch.test.js +23 -0
  119. package/src/components/MaterialUI/Inputs/SwitchProps.js +2 -0
  120. package/src/components/MaterialUI/Inputs/SwitchProps.test.js +2 -0
  121. package/src/components/MaterialUI/hocs/withDeferredTooltip.js +4 -1
  122. package/src/components/MaterialUI/hocs/withDeferredTooltip.test.js +27 -0
  123. package/src/components/MaterialUI/muiThemes.js +1 -0
  124. package/src/components/Navigation/Bar.test.js +92 -87
  125. package/src/components/TaskDetailsModal.test.js +1 -3
  126. package/src/constants.js +1 -0
  127. package/src/content/iconsSheet.svg +740 -116
  128. package/src/hocs/withScrollBox.js +32 -19
  129. package/src/hocs/withScrollBox.test.js +15 -3
  130. package/src/hooks/useInMemoryPaging.js +78 -0
  131. package/src/hooks/useInMemoryPaging.test.js +515 -0
  132. package/src/hooks/useMultipleFieldEditState.js +11 -4
  133. package/src/hooks/useMultipleFieldEditState.test.js +49 -1
  134. package/src/reducers/metadata.js +6 -1
  135. package/src/reducers/metadata.test.js +31 -0
  136. package/src/requests +1 -0
  137. package/src/schemas/metadata.js +3 -0
  138. package/src/selectors/locale.js +1 -1
  139. package/src/selectors/metadata.js +12 -9
  140. package/src/selectors/metadata.test.js +92 -11
  141. package/src/sharedMessages.js +4 -0
  142. package/src/translations/en-US.json +1 -0
  143. package/src/translations/fr-CA.json +1 -0
  144. package/src/utils/ListHelper.js +203 -0
  145. package/src/utils/ListHelper.test.js +710 -0
  146. package/src/utils/comparisonHelper.js +135 -0
  147. package/src/utils/comparisonHelper.test.js +334 -0
  148. package/src/utils/propertyBagHelper.js +2 -0
  149. package/src/utils/propertyBagHelper.test.js +6 -0
  150. package/dist/components/Form/FieldList.js +0 -270
  151. package/dist/components/Form/Inputs/FieldButtons.js +0 -66
  152. package/dist/components/Form/Inputs/Number.js +0 -117
  153. package/dist/components/Form/Inputs/SmallButton.js +0 -91
  154. package/dist/components/Form/Inputs/Time.js +0 -86
  155. package/dist/components/Form/Inputs/Translation.js +0 -169
  156. package/src/components/AppFrame/ApplicationSelector/Header.js +0 -34
  157. package/src/components/AppFrame/ApplicationSelector/Header.test.js +0 -23
  158. package/src/components/Form/FieldList.js +0 -210
  159. package/src/components/Form/FieldList.test.js +0 -558
  160. package/src/components/Form/Inputs/FieldButtons.js +0 -90
  161. package/src/components/Form/Inputs/Number.js +0 -60
  162. package/src/components/Form/Inputs/Number.test.js +0 -435
  163. package/src/components/Form/Inputs/SmallButton.js +0 -37
  164. package/src/components/Form/Inputs/SmallButton.test.js +0 -65
  165. package/src/components/Form/Inputs/Time.js +0 -32
  166. package/src/components/Form/Inputs/Time.test.js +0 -41
  167. package/src/components/Form/Inputs/Translation.js +0 -93
  168. 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
- };