@axinom/mosaic-ui 0.35.0-rc.9 → 0.36.0-rc.0
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/dist/components/Buttons/Button/Button.d.ts.map +1 -1
- package/dist/components/Buttons/Button/Button.model.d.ts +2 -2
- package/dist/components/Buttons/Button/Button.model.d.ts.map +1 -1
- package/dist/components/Buttons/Button.model.d.ts +5 -0
- package/dist/components/Buttons/Button.model.d.ts.map +1 -1
- package/dist/components/Buttons/CompositeButton/CompositeButton.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicDataList.d.ts +3 -1
- package/dist/components/DynamicDataList/DynamicDataList.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicDataList.model.d.ts +6 -1
- package/dist/components/DynamicDataList/DynamicDataList.model.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.d.ts +7 -3
- package/dist/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListRow/DynamicListRow.d.ts +4 -1
- package/dist/components/DynamicDataList/DynamicListRow/DynamicListRow.d.ts.map +1 -1
- package/dist/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.d.ts.map +1 -1
- package/dist/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.types.d.ts +7 -1
- package/dist/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.types.d.ts.map +1 -1
- package/dist/components/DynamicDataList/helpers/useDataHandler.d.ts +1 -0
- package/dist/components/DynamicDataList/helpers/useDataHandler.d.ts.map +1 -1
- package/dist/components/DynamicDataList/helpers/useRowEditing.d.ts +8 -0
- package/dist/components/DynamicDataList/helpers/useRowEditing.d.ts.map +1 -0
- package/dist/index.es.js +4 -4
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/Buttons/Button/Button.model.ts +2 -2
- package/src/components/Buttons/Button/Button.spec.tsx +56 -0
- package/src/components/Buttons/Button/Button.tsx +6 -2
- package/src/components/Buttons/Button.model.ts +5 -0
- package/src/components/Buttons/CompositeButton/CompositeButton.spec.tsx +56 -1
- package/src/components/Buttons/CompositeButton/CompositeButton.tsx +9 -2
- package/src/components/DynamicDataList/DynamicDataList.model.ts +7 -2
- package/src/components/DynamicDataList/DynamicDataList.spec.tsx +5 -0
- package/src/components/DynamicDataList/DynamicDataList.stories.tsx +37 -0
- package/src/components/DynamicDataList/DynamicDataList.tsx +58 -28
- package/src/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.scss +0 -1
- package/src/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.spec.tsx +2 -44
- package/src/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.tsx +36 -28
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.scss +12 -0
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.tsx +23 -12
- package/src/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.spec.ts +26 -1
- package/src/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.ts +8 -0
- package/src/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.types.ts +8 -0
- package/src/components/DynamicDataList/helpers/useDataHandler.ts +11 -1
- package/src/components/DynamicDataList/helpers/useRowEditing.ts +30 -0
- package/src/components/FormStation/FormStation.scss +4 -0
- package/src/components/FormStation/FormStation.tsx +2 -2
- package/src/styles/variables.scss +1 -1
|
@@ -45,7 +45,6 @@ const defaultProps: DynamicListDataEntryProps<TestData> = {
|
|
|
45
45
|
verticalTextAlign: 'center',
|
|
46
46
|
positionKey: 'position',
|
|
47
47
|
allowReordering: false,
|
|
48
|
-
allowAdd: false,
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
const MockRenderer: DynamicListDataEntryRenderer = (
|
|
@@ -139,9 +138,7 @@ describe('DynamicListDataEntry', () => {
|
|
|
139
138
|
});
|
|
140
139
|
|
|
141
140
|
it(`Button component should have type of 'button'`, () => {
|
|
142
|
-
const wrapper = mount(
|
|
143
|
-
<DynamicListDataEntry {...defaultProps} allowAdd={true} />,
|
|
144
|
-
);
|
|
141
|
+
const wrapper = mount(<DynamicListDataEntry {...defaultProps} />);
|
|
145
142
|
|
|
146
143
|
const button = wrapper.find(Button);
|
|
147
144
|
|
|
@@ -220,40 +217,9 @@ describe('DynamicListDataEntry', () => {
|
|
|
220
217
|
expect(dragIcon.exists()).toBe(false);
|
|
221
218
|
});
|
|
222
219
|
|
|
223
|
-
it(`doesn't display an action button by default`, () => {
|
|
224
|
-
const wrapper = shallow(
|
|
225
|
-
<DynamicListDataEntry
|
|
226
|
-
columns={defaultColumns}
|
|
227
|
-
columnSizes={defaultProps.columnSizes}
|
|
228
|
-
/>,
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
const button = wrapper.find(Button);
|
|
232
|
-
|
|
233
|
-
expect(button.exists()).toBe(false);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it(`displays an action button if 'allowAdd' is set to true`, () => {
|
|
237
|
-
const wrapper = shallow(
|
|
238
|
-
<DynamicListDataEntry
|
|
239
|
-
columns={defaultColumns}
|
|
240
|
-
columnSizes={defaultProps.columnSizes}
|
|
241
|
-
allowAdd={true}
|
|
242
|
-
/>,
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
const button = wrapper.find(Button);
|
|
246
|
-
|
|
247
|
-
expect(button.exists()).toBe(true);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
220
|
it(`renders "disabled" attribute for action button when set`, () => {
|
|
251
221
|
const wrapper = mount(
|
|
252
|
-
<DynamicListDataEntry
|
|
253
|
-
{...defaultProps}
|
|
254
|
-
allowAdd={true}
|
|
255
|
-
disabled={true}
|
|
256
|
-
/>,
|
|
222
|
+
<DynamicListDataEntry {...defaultProps} disabled={true} />,
|
|
257
223
|
);
|
|
258
224
|
|
|
259
225
|
const button = wrapper.find(Button);
|
|
@@ -307,7 +273,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
307
273
|
<DynamicListDataEntry
|
|
308
274
|
columns={defaultColumns}
|
|
309
275
|
columnSizes={defaultProps.columnSizes}
|
|
310
|
-
allowAdd={true}
|
|
311
276
|
defaultValuesForNewData={defaultData}
|
|
312
277
|
onActionClicked={spy}
|
|
313
278
|
/>,
|
|
@@ -332,7 +297,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
332
297
|
<DynamicListDataEntry
|
|
333
298
|
columns={defaultColumns}
|
|
334
299
|
columnSizes={defaultProps.columnSizes}
|
|
335
|
-
allowAdd={true}
|
|
336
300
|
onActionClicked={spy}
|
|
337
301
|
rowValidationSchema={Yup.object<ObjectSchemaDefinition<TestData>>({
|
|
338
302
|
id: Yup.number().required(),
|
|
@@ -364,7 +328,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
364
328
|
<DynamicListDataEntry
|
|
365
329
|
columns={columnWithRenderer}
|
|
366
330
|
columnSizes={defaultProps.columnSizes}
|
|
367
|
-
allowAdd={true}
|
|
368
331
|
onActionClicked={spy}
|
|
369
332
|
/>,
|
|
370
333
|
);
|
|
@@ -401,7 +364,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
401
364
|
<DynamicListDataEntry
|
|
402
365
|
columns={[...columnWithRenderer, { propertyName: mockPosKey }]}
|
|
403
366
|
columnSizes={defaultProps.columnSizes}
|
|
404
|
-
allowAdd={true}
|
|
405
367
|
onActionClicked={spy}
|
|
406
368
|
positionKey={mockPosKey}
|
|
407
369
|
allowReordering={true}
|
|
@@ -445,7 +407,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
445
407
|
<DynamicListDataEntry
|
|
446
408
|
columns={[...columnWithRenderer, { propertyName: mockPosKey }]}
|
|
447
409
|
columnSizes={defaultProps.columnSizes}
|
|
448
|
-
allowAdd={true}
|
|
449
410
|
onActionClicked={spy}
|
|
450
411
|
positionKey={mockPosKey}
|
|
451
412
|
allowReordering={false}
|
|
@@ -486,7 +447,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
486
447
|
<DynamicListDataEntry
|
|
487
448
|
columns={[...columnWithRenderer, { propertyName: mockPosKey }]}
|
|
488
449
|
columnSizes={defaultProps.columnSizes}
|
|
489
|
-
allowAdd={true}
|
|
490
450
|
onActionClicked={spy}
|
|
491
451
|
positionKey={mockPosKey}
|
|
492
452
|
allowReordering={true}
|
|
@@ -529,7 +489,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
529
489
|
<DynamicListDataEntry
|
|
530
490
|
columns={[...columnWithRenderer, { propertyName: mockPosKey }]}
|
|
531
491
|
columnSizes={defaultProps.columnSizes}
|
|
532
|
-
allowAdd={true}
|
|
533
492
|
onActionClicked={spy}
|
|
534
493
|
allowReordering={true}
|
|
535
494
|
newDataPosition={mockNewPos}
|
|
@@ -578,7 +537,6 @@ describe('DynamicListDataEntry', () => {
|
|
|
578
537
|
<DynamicListDataEntry
|
|
579
538
|
columns={mockColumns}
|
|
580
539
|
columnSizes={defaultProps.columnSizes}
|
|
581
|
-
allowAdd={true}
|
|
582
540
|
onActionClicked={spy}
|
|
583
541
|
/>,
|
|
584
542
|
);
|
|
@@ -15,7 +15,10 @@ import { IconName, Icons } from '../../Icons';
|
|
|
15
15
|
import { DynamicListColumn } from '../DynamicDataList.model';
|
|
16
16
|
import classes from './DynamicListDataEntry.scss';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
export enum DynamicListDataEntryMode {
|
|
19
|
+
Add,
|
|
20
|
+
Edit,
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
export interface DynamicListDataEntryProps<T extends Data> {
|
|
21
24
|
/** The column definition */
|
|
@@ -34,8 +37,6 @@ export interface DynamicListDataEntryProps<T extends Data> {
|
|
|
34
37
|
verticalTextAlign?: 'start' | 'center' | 'end';
|
|
35
38
|
/** Property name that is used to determine data position (default: undefined) */
|
|
36
39
|
positionKey?: keyof T;
|
|
37
|
-
/** If set to true, the add action button will be rendered (default: undefined) */
|
|
38
|
-
allowAdd?: boolean;
|
|
39
40
|
/** Whether add new item button should be disabled */
|
|
40
41
|
disabled?: boolean;
|
|
41
42
|
/** If set to true, rows can be be repositioned using the input field (default: undefined) */
|
|
@@ -58,6 +59,8 @@ export interface DynamicListDataEntryProps<T extends Data> {
|
|
|
58
59
|
showHeader?: boolean;
|
|
59
60
|
/** If set to true, the position column will be shown (default: false) */
|
|
60
61
|
showPositionColumn?: boolean;
|
|
62
|
+
/** Determines if the component is in Add or Edit mode (default: Add) */
|
|
63
|
+
mode?: DynamicListDataEntryMode;
|
|
61
64
|
/** Emits when the action button is clicked. Data is supplied as a parameter */
|
|
62
65
|
onActionClicked?: (data: T) => void;
|
|
63
66
|
/** override default add button (+) */
|
|
@@ -73,7 +76,6 @@ export const DynamicListDataEntry = <T extends Data>({
|
|
|
73
76
|
horizontalTextAlign,
|
|
74
77
|
verticalTextAlign,
|
|
75
78
|
positionKey,
|
|
76
|
-
allowAdd,
|
|
77
79
|
disabled = false,
|
|
78
80
|
allowReordering,
|
|
79
81
|
allowDragging,
|
|
@@ -85,6 +87,7 @@ export const DynamicListDataEntry = <T extends Data>({
|
|
|
85
87
|
sticky = true,
|
|
86
88
|
showHeader,
|
|
87
89
|
showPositionColumn = false,
|
|
90
|
+
mode = DynamicListDataEntryMode.Add,
|
|
88
91
|
onActionClicked = noop,
|
|
89
92
|
customAddButton,
|
|
90
93
|
}: PropsWithChildren<DynamicListDataEntryProps<T>>): JSX.Element => {
|
|
@@ -221,29 +224,31 @@ export const DynamicListDataEntry = <T extends Data>({
|
|
|
221
224
|
)}
|
|
222
225
|
</div>
|
|
223
226
|
))}
|
|
224
|
-
{
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
227
|
+
<div className={clsx(classes.actionButtonContainer)}>
|
|
228
|
+
{(customAddButton && customAddButton(onAddItemHandler)) || (
|
|
229
|
+
<Button
|
|
230
|
+
type="button"
|
|
231
|
+
className={clsx(classes.actionButton)}
|
|
232
|
+
icon={
|
|
233
|
+
mode === DynamicListDataEntryMode.Add
|
|
234
|
+
? IconName.Plus
|
|
235
|
+
: IconName.Checkmark
|
|
236
|
+
}
|
|
237
|
+
buttonContext={
|
|
238
|
+
actionButtonContext === undefined
|
|
239
|
+
? isDirty
|
|
240
|
+
? ButtonContext.Active
|
|
241
|
+
: ButtonContext.Icon
|
|
242
|
+
: actionButtonContext
|
|
243
|
+
}
|
|
244
|
+
height={actionSize}
|
|
245
|
+
width={actionSize}
|
|
246
|
+
onButtonClicked={onAddItemHandler}
|
|
247
|
+
dataTestId="dynamic-list-add-button"
|
|
248
|
+
disabled={disabled}
|
|
249
|
+
/>
|
|
250
|
+
)}
|
|
251
|
+
</div>
|
|
247
252
|
</div>
|
|
248
253
|
);
|
|
249
254
|
};
|
|
@@ -254,8 +259,11 @@ const renderField = function <T extends Data>(
|
|
|
254
259
|
error: string | undefined,
|
|
255
260
|
onValueChanged: (value: unknown) => void,
|
|
256
261
|
disabled = false,
|
|
262
|
+
mode: DynamicListDataEntryMode = DynamicListDataEntryMode.Add,
|
|
257
263
|
): React.ReactNode {
|
|
258
|
-
if (column.
|
|
264
|
+
if (mode === DynamicListDataEntryMode.Edit && column.dataEditRender) {
|
|
265
|
+
return column.dataEditRender(currentValue, error, onValueChanged, disabled);
|
|
266
|
+
} else if (column.dataEntryRender) {
|
|
259
267
|
return column.dataEntryRender(
|
|
260
268
|
currentValue,
|
|
261
269
|
error,
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
justify-items: left;
|
|
22
22
|
align-items: center;
|
|
23
23
|
|
|
24
|
+
.wrapper {
|
|
25
|
+
min-height: 50px;
|
|
26
|
+
min-width: 100%;
|
|
27
|
+
display: grid;
|
|
28
|
+
align-items: center;
|
|
29
|
+
border: 1px solid transparent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:hover .editable {
|
|
33
|
+
border: 1px solid var(--input-hover-color, $input-hover-color);
|
|
34
|
+
}
|
|
35
|
+
|
|
24
36
|
.column {
|
|
25
37
|
max-width: 100%;
|
|
26
38
|
max-height: 100%;
|
|
@@ -11,8 +11,6 @@ import { InlineMenu } from '../../InlineMenu';
|
|
|
11
11
|
import { DynamicListColumn } from '../DynamicDataList.model';
|
|
12
12
|
import classes from './DynamicListRow.scss';
|
|
13
13
|
|
|
14
|
-
// TODO: Add sizing for DragIcon and Input container. Similar to ActionButton sizing
|
|
15
|
-
|
|
16
14
|
export interface DynamicListRowProps<T extends Data> {
|
|
17
15
|
/** The column definition */
|
|
18
16
|
columns: DynamicListColumn<T>[];
|
|
@@ -32,6 +30,8 @@ export interface DynamicListRowProps<T extends Data> {
|
|
|
32
30
|
verticalTextAlign?: 'start' | 'center' | 'end';
|
|
33
31
|
/** If set to true, the remove action button will be rendered (default: undefined) */
|
|
34
32
|
allowRemove?: boolean;
|
|
33
|
+
/** If set to true, editable fields will be highlighted and row click events will be fired (default: false) */
|
|
34
|
+
allowEditing?: boolean;
|
|
35
35
|
/** Property name that is used to determine data position (default: undefined) */
|
|
36
36
|
positionKey?: keyof T;
|
|
37
37
|
/** If set to true, this component can be dragged (default: undefined) */
|
|
@@ -49,6 +49,7 @@ export interface DynamicListRowProps<T extends Data> {
|
|
|
49
49
|
currenPosition: number,
|
|
50
50
|
newPosition: number,
|
|
51
51
|
) => void;
|
|
52
|
+
onRowClicked?: (data: T) => void;
|
|
52
53
|
/** Emits when the action button is clicked. Data is supplied as a parameter */
|
|
53
54
|
onActionClicked?: (data: T) => void;
|
|
54
55
|
/** CSS Class name for additional styles */
|
|
@@ -75,6 +76,7 @@ export const DynamicListRow = <T extends Data>({
|
|
|
75
76
|
disabled,
|
|
76
77
|
provided,
|
|
77
78
|
onPositionInputChanged = noop,
|
|
79
|
+
onRowClicked = noop,
|
|
78
80
|
onActionClicked = noop,
|
|
79
81
|
className = '',
|
|
80
82
|
rowClassNameProvider,
|
|
@@ -82,6 +84,7 @@ export const DynamicListRow = <T extends Data>({
|
|
|
82
84
|
dragging = false,
|
|
83
85
|
showPositionColumn = false,
|
|
84
86
|
showActionColumn = false,
|
|
87
|
+
allowEditing = false,
|
|
85
88
|
}: PropsWithChildren<DynamicListRowProps<T>>): JSX.Element => {
|
|
86
89
|
const customStyles = {
|
|
87
90
|
gridAutoRows: `minmax(50px, ${rowHeight})`,
|
|
@@ -130,6 +133,7 @@ export const DynamicListRow = <T extends Data>({
|
|
|
130
133
|
ref={provided?.innerRef}
|
|
131
134
|
{...provided?.draggableProps}
|
|
132
135
|
style={customStyles}
|
|
136
|
+
onClick={() => allowEditing && onRowClicked(data)}
|
|
133
137
|
>
|
|
134
138
|
{showPositionColumn && (
|
|
135
139
|
<div className={classes.position}>
|
|
@@ -169,18 +173,25 @@ export const DynamicListRow = <T extends Data>({
|
|
|
169
173
|
|
|
170
174
|
return (
|
|
171
175
|
<div
|
|
176
|
+
className={clsx(classes.wrapper, {
|
|
177
|
+
[classes.editable]:
|
|
178
|
+
column.dataEntryRender !== undefined && allowEditing,
|
|
179
|
+
})}
|
|
172
180
|
key={column.propertyName as string}
|
|
173
|
-
className={classes.column}
|
|
174
|
-
title={
|
|
175
|
-
column.tooltip !== false
|
|
176
|
-
? getTooltipText(data[column.propertyName])
|
|
177
|
-
: undefined
|
|
178
|
-
}
|
|
179
|
-
data-test-id={`dynamic-list-property:${
|
|
180
|
-
column.propertyName as string
|
|
181
|
-
}`}
|
|
182
181
|
>
|
|
183
|
-
|
|
182
|
+
<div
|
|
183
|
+
className={classes.column}
|
|
184
|
+
title={
|
|
185
|
+
column.tooltip !== false
|
|
186
|
+
? getTooltipText(data[column.propertyName])
|
|
187
|
+
: undefined
|
|
188
|
+
}
|
|
189
|
+
data-test-id={`dynamic-list-property:${
|
|
190
|
+
column.propertyName as string
|
|
191
|
+
}`}
|
|
192
|
+
>
|
|
193
|
+
{columnData}
|
|
194
|
+
</div>
|
|
184
195
|
</div>
|
|
185
196
|
);
|
|
186
197
|
})}
|
package/src/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.spec.ts
CHANGED
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
} from './DynamicListReducer.types';
|
|
8
8
|
|
|
9
9
|
jest.mock('./DynamicListReducer.init');
|
|
10
|
-
jest.mock('./DynamicListReducer.actions')
|
|
10
|
+
jest.mock('./DynamicListReducer.actions', () => ({
|
|
11
|
+
addItem: jest.fn(),
|
|
12
|
+
removeItem: jest.fn().mockReturnValue([]),
|
|
13
|
+
}));
|
|
11
14
|
|
|
12
15
|
interface Data {
|
|
13
16
|
position?: number;
|
|
@@ -69,6 +72,28 @@ describe('Dynamic List Reducer', () => {
|
|
|
69
72
|
expect(DynamicListReducerInit).toHaveBeenCalledTimes(1);
|
|
70
73
|
});
|
|
71
74
|
|
|
75
|
+
it('calls removeItem, addItem and DynamicListReducerInit when action is update', () => {
|
|
76
|
+
DynamicListReducer(initialState, {
|
|
77
|
+
type: DynamicListReducerActionType.Update,
|
|
78
|
+
currentItem: { position: 20, id: 20 },
|
|
79
|
+
newItem: { id: 10, position: 11 },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(removeItem).toHaveBeenCalledTimes(1);
|
|
83
|
+
expect(removeItem).toHaveBeenCalledWith(
|
|
84
|
+
{ position: 20, id: 20 },
|
|
85
|
+
dataSet,
|
|
86
|
+
'position',
|
|
87
|
+
);
|
|
88
|
+
expect(addItem).toHaveBeenCalledTimes(1);
|
|
89
|
+
expect(addItem).toHaveBeenCalledWith(
|
|
90
|
+
{ id: 10, position: 11 },
|
|
91
|
+
[],
|
|
92
|
+
'position',
|
|
93
|
+
);
|
|
94
|
+
expect(DynamicListReducerInit).toHaveBeenCalledTimes(1);
|
|
95
|
+
});
|
|
96
|
+
|
|
72
97
|
it('calls DynamicListReducerInit with new items when action is reset', () => {
|
|
73
98
|
DynamicListReducer(initialState, {
|
|
74
99
|
type: DynamicListReducerActionType.Reset,
|
|
@@ -22,6 +22,14 @@ export const DynamicListReducer = <T extends Data>(
|
|
|
22
22
|
case DynamicListReducerActionType.Remove:
|
|
23
23
|
newItems = removeItem(action.item, state.items, positionPropertyName);
|
|
24
24
|
break;
|
|
25
|
+
case DynamicListReducerActionType.Update:
|
|
26
|
+
newItems = removeItem(
|
|
27
|
+
action.currentItem,
|
|
28
|
+
state.items,
|
|
29
|
+
positionPropertyName,
|
|
30
|
+
);
|
|
31
|
+
newItems = addItem(action.newItem, newItems, positionPropertyName);
|
|
32
|
+
break;
|
|
25
33
|
case DynamicListReducerActionType.Reset:
|
|
26
34
|
newItems = action.items;
|
|
27
35
|
positionPropertyName = action.positionPropertyName;
|
package/src/components/DynamicDataList/helpers/DynamicListReducer/DynamicListReducer.types.ts
CHANGED
|
@@ -10,12 +10,14 @@ export interface DynamicListReducerInitArgs<T extends Data> {
|
|
|
10
10
|
export enum DynamicListReducerActionType {
|
|
11
11
|
Add = 'add',
|
|
12
12
|
Remove = 'remove',
|
|
13
|
+
Update = 'update',
|
|
13
14
|
Reset = 'reset',
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export type DynamicListReducerAction<T extends Data> =
|
|
17
18
|
| DynamicListReducerAddAction<T>
|
|
18
19
|
| DynamicListReducerRemoveAction<T>
|
|
20
|
+
| DynamicListReducerUpdateAction<T>
|
|
19
21
|
| DynamicListReducerResetAction<T>;
|
|
20
22
|
|
|
21
23
|
interface DynamicListReducerAddAction<T extends Data> {
|
|
@@ -28,6 +30,12 @@ interface DynamicListReducerRemoveAction<T extends Data> {
|
|
|
28
30
|
item: T;
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
interface DynamicListReducerUpdateAction<T extends Data> {
|
|
34
|
+
type: DynamicListReducerActionType.Update;
|
|
35
|
+
currentItem: T;
|
|
36
|
+
newItem: T;
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
interface DynamicListReducerResetAction<T extends Data> {
|
|
32
40
|
type: DynamicListReducerActionType.Reset;
|
|
33
41
|
items: T[];
|
|
@@ -22,6 +22,7 @@ export const useDataHandler = <T extends Data>(
|
|
|
22
22
|
readonly canAddItems: boolean;
|
|
23
23
|
readonly addItem: (item: T) => void;
|
|
24
24
|
readonly removeItem: (item: T) => void;
|
|
25
|
+
readonly updateItem: (currentItem: T, newItem: T) => void;
|
|
25
26
|
} => {
|
|
26
27
|
const [shouldTriggerOnChange, setShouldTriggerOnChange] = useState(false);
|
|
27
28
|
|
|
@@ -71,7 +72,16 @@ export const useDataHandler = <T extends Data>(
|
|
|
71
72
|
setShouldTriggerOnChange(true);
|
|
72
73
|
};
|
|
73
74
|
|
|
75
|
+
const updateItem = (currentItem: T, newItem: T): void => {
|
|
76
|
+
dispatch({
|
|
77
|
+
type: DynamicListReducerActionType.Update,
|
|
78
|
+
currentItem,
|
|
79
|
+
newItem,
|
|
80
|
+
});
|
|
81
|
+
setShouldTriggerOnChange(true);
|
|
82
|
+
};
|
|
83
|
+
|
|
74
84
|
const { items, nextPosition, canAddItems } = state;
|
|
75
85
|
|
|
76
|
-
return { items, nextPosition, canAddItems, addItem, removeItem };
|
|
86
|
+
return { items, nextPosition, canAddItems, addItem, removeItem, updateItem };
|
|
77
87
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Data } from '../../../types';
|
|
3
|
+
|
|
4
|
+
export const useRowEditing = <T extends Data>(
|
|
5
|
+
allowEditing: boolean,
|
|
6
|
+
updateItem: (currentItem: T, newItem: T) => void,
|
|
7
|
+
): {
|
|
8
|
+
readonly editingRow: T | undefined;
|
|
9
|
+
readonly isEditing: boolean;
|
|
10
|
+
readonly startEditing: (item: T) => void;
|
|
11
|
+
readonly finishEditing: (item: T) => void;
|
|
12
|
+
} => {
|
|
13
|
+
const [editingRow, setEditingRow] = useState<T>();
|
|
14
|
+
|
|
15
|
+
const startEditing = (item: T): void => {
|
|
16
|
+
allowEditing && setEditingRow(item);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const finishEditing = (item: T): void => {
|
|
20
|
+
updateItem(editingRow as T, item);
|
|
21
|
+
setEditingRow(undefined);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
editingRow,
|
|
26
|
+
isEditing: !!editingRow,
|
|
27
|
+
startEditing,
|
|
28
|
+
finishEditing,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -246,8 +246,8 @@ export const FormStation = <TValues extends Data, TSubmitResponse = unknown>({
|
|
|
246
246
|
<MessageBar {...stationMessage}>{stationMessage.body}</MessageBar>
|
|
247
247
|
)}
|
|
248
248
|
<div
|
|
249
|
-
className={clsx({
|
|
250
|
-
[classes.
|
|
249
|
+
className={clsx(classes.formContainer, {
|
|
250
|
+
[classes.paddedContent]: !edgeToEdgeContent,
|
|
251
251
|
})}
|
|
252
252
|
>
|
|
253
253
|
<Form>
|
|
@@ -223,7 +223,7 @@ $calendar-container-bg-color: $blue;
|
|
|
223
223
|
|
|
224
224
|
/* Dynamic Data List */
|
|
225
225
|
$dynamic-list-row-bg-color: white;
|
|
226
|
-
$dynamic-list-row-hover-bg-color: $
|
|
226
|
+
$dynamic-list-row-hover-bg-color: rgba($blue, 0.1);
|
|
227
227
|
$dynamic-list-row-height: 50px;
|
|
228
228
|
$dynamic-list-column-gap: 20px;
|
|
229
229
|
$dynamic-list-row-gap: 0px;
|