@wordpress/dataviews 5.0.1-next.719a03cbe.0 → 6.0.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/CHANGELOG.md +34 -4
- package/README.md +55 -26
- package/build/components/dataviews/index.js +13 -4
- package/build/components/dataviews/index.js.map +1 -1
- package/build/components/dataviews-context/index.js +3 -1
- package/build/components/dataviews-context/index.js.map +1 -1
- package/build/components/dataviews-filters/filter.js +15 -8
- package/build/components/dataviews-filters/filter.js.map +1 -1
- package/build/components/dataviews-filters/index.js +16 -5
- package/build/components/dataviews-filters/index.js.map +1 -1
- package/build/components/dataviews-filters/input-widget.js +7 -1
- package/build/components/dataviews-filters/input-widget.js.map +1 -1
- package/build/components/dataviews-filters/reset-filters.js +2 -2
- package/build/components/dataviews-filters/reset-filters.js.map +1 -1
- package/build/components/dataviews-layout/index.js +5 -2
- package/build/components/dataviews-layout/index.js.map +1 -1
- package/build/components/dataviews-view-config/index.js +4 -3
- package/build/components/dataviews-view-config/index.js.map +1 -1
- package/build/dataform-controls/boolean.js +15 -1
- package/build/dataform-controls/boolean.js.map +1 -1
- package/build/dataform-controls/date.js +385 -0
- package/build/dataform-controls/date.js.map +1 -0
- package/build/dataform-controls/datetime.js +5 -84
- package/build/dataform-controls/datetime.js.map +1 -1
- package/build/dataform-controls/email.js +15 -1
- package/build/dataform-controls/email.js.map +1 -1
- package/build/dataform-controls/index.js +2 -0
- package/build/dataform-controls/index.js.map +1 -1
- package/build/dataform-controls/integer.js +23 -4
- package/build/dataform-controls/integer.js.map +1 -1
- package/build/dataform-controls/relative-date-control.js +109 -0
- package/build/dataform-controls/relative-date-control.js.map +1 -0
- package/build/dataform-controls/select.js +12 -5
- package/build/dataform-controls/select.js.map +1 -1
- package/build/dataform-controls/text.js +15 -1
- package/build/dataform-controls/text.js.map +1 -1
- package/build/dataviews-layouts/grid/index.js +91 -18
- package/build/dataviews-layouts/grid/index.js.map +1 -1
- package/build/dataviews-layouts/grid/preview-size-picker.js +39 -85
- package/build/dataviews-layouts/grid/preview-size-picker.js.map +1 -1
- package/build/dataviews-layouts/list/index.js +7 -3
- package/build/dataviews-layouts/list/index.js.map +1 -1
- package/build/dataviews-layouts/table/column-primary.js +18 -3
- package/build/dataviews-layouts/table/column-primary.js.map +1 -1
- package/build/dataviews-layouts/table/index.js +57 -5
- package/build/dataviews-layouts/table/index.js.map +1 -1
- package/build/field-types/array.js +27 -18
- package/build/field-types/array.js.map +1 -1
- package/build/field-types/boolean.js +11 -7
- package/build/field-types/boolean.js.map +1 -1
- package/build/field-types/date.js +66 -0
- package/build/field-types/date.js.map +1 -0
- package/build/field-types/datetime.js +19 -10
- package/build/field-types/datetime.js.map +1 -1
- package/build/field-types/email.js +22 -18
- package/build/field-types/email.js.map +1 -1
- package/build/field-types/index.js +20 -6
- package/build/field-types/index.js.map +1 -1
- package/build/field-types/integer.js +22 -17
- package/build/field-types/integer.js.map +1 -1
- package/build/field-types/media.js +19 -10
- package/build/field-types/media.js.map +1 -1
- package/build/field-types/text.js +19 -10
- package/build/field-types/text.js.map +1 -1
- package/build/filter-and-sort-data-view.js +28 -14
- package/build/filter-and-sort-data-view.js.map +1 -1
- package/build/normalize-fields.js +4 -5
- package/build/normalize-fields.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build/validation.js +15 -2
- package/build/validation.js.map +1 -1
- package/build-module/components/dataviews/index.js +15 -6
- package/build-module/components/dataviews/index.js.map +1 -1
- package/build-module/components/dataviews-context/index.js +3 -1
- package/build-module/components/dataviews-context/index.js.map +1 -1
- package/build-module/components/dataviews-filters/filter.js +15 -8
- package/build-module/components/dataviews-filters/filter.js.map +1 -1
- package/build-module/components/dataviews-filters/index.js +16 -5
- package/build-module/components/dataviews-filters/index.js.map +1 -1
- package/build-module/components/dataviews-filters/input-widget.js +7 -1
- package/build-module/components/dataviews-filters/input-widget.js.map +1 -1
- package/build-module/components/dataviews-filters/reset-filters.js +2 -2
- package/build-module/components/dataviews-filters/reset-filters.js.map +1 -1
- package/build-module/components/dataviews-layout/index.js +5 -2
- package/build-module/components/dataviews-layout/index.js.map +1 -1
- package/build-module/components/dataviews-view-config/index.js +4 -3
- package/build-module/components/dataviews-view-config/index.js.map +1 -1
- package/build-module/dataform-controls/boolean.js +17 -2
- package/build-module/dataform-controls/boolean.js.map +1 -1
- package/build-module/dataform-controls/date.js +376 -0
- package/build-module/dataform-controls/date.js.map +1 -0
- package/build-module/dataform-controls/datetime.js +3 -84
- package/build-module/dataform-controls/datetime.js.map +1 -1
- package/build-module/dataform-controls/email.js +17 -2
- package/build-module/dataform-controls/email.js.map +1 -1
- package/build-module/dataform-controls/index.js +2 -0
- package/build-module/dataform-controls/index.js.map +1 -1
- package/build-module/dataform-controls/integer.js +24 -5
- package/build-module/dataform-controls/integer.js.map +1 -1
- package/build-module/dataform-controls/relative-date-control.js +100 -0
- package/build-module/dataform-controls/relative-date-control.js.map +1 -0
- package/build-module/dataform-controls/select.js +12 -5
- package/build-module/dataform-controls/select.js.map +1 -1
- package/build-module/dataform-controls/text.js +17 -2
- package/build-module/dataform-controls/text.js.map +1 -1
- package/build-module/dataviews-layouts/grid/index.js +93 -20
- package/build-module/dataviews-layouts/grid/index.js.map +1 -1
- package/build-module/dataviews-layouts/grid/preview-size-picker.js +40 -85
- package/build-module/dataviews-layouts/grid/preview-size-picker.js.map +1 -1
- package/build-module/dataviews-layouts/list/index.js +7 -3
- package/build-module/dataviews-layouts/list/index.js.map +1 -1
- package/build-module/dataviews-layouts/table/column-primary.js +18 -3
- package/build-module/dataviews-layouts/table/column-primary.js.map +1 -1
- package/build-module/dataviews-layouts/table/index.js +58 -6
- package/build-module/dataviews-layouts/table/index.js.map +1 -1
- package/build-module/field-types/array.js +27 -18
- package/build-module/field-types/array.js.map +1 -1
- package/build-module/field-types/boolean.js +11 -7
- package/build-module/field-types/boolean.js.map +1 -1
- package/build-module/field-types/date.js +60 -0
- package/build-module/field-types/date.js.map +1 -0
- package/build-module/field-types/datetime.js +19 -10
- package/build-module/field-types/datetime.js.map +1 -1
- package/build-module/field-types/email.js +22 -18
- package/build-module/field-types/email.js.map +1 -1
- package/build-module/field-types/index.js +20 -6
- package/build-module/field-types/index.js.map +1 -1
- package/build-module/field-types/integer.js +22 -17
- package/build-module/field-types/integer.js.map +1 -1
- package/build-module/field-types/media.js +19 -10
- package/build-module/field-types/media.js.map +1 -1
- package/build-module/field-types/text.js +19 -10
- package/build-module/field-types/text.js.map +1 -1
- package/build-module/filter-and-sort-data-view.js +28 -14
- package/build-module/filter-and-sort-data-view.js.map +1 -1
- package/build-module/normalize-fields.js +4 -5
- package/build-module/normalize-fields.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-module/validation.js +15 -2
- package/build-module/validation.js.map +1 -1
- package/build-style/style-rtl.css +84 -41
- package/build-style/style.css +84 -41
- package/build-types/components/dataform/stories/index.story.d.ts +21 -0
- package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews/index.d.ts +3 -2
- package/build-types/components/dataviews/index.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/fixtures.d.ts +1 -0
- package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/index.story.d.ts +16 -2
- package/build-types/components/dataviews/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews-context/index.d.ts +4 -2
- package/build-types/components/dataviews-context/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/filter.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/index.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/reset-filters.d.ts.map +1 -1
- package/build-types/components/dataviews-layout/index.d.ts.map +1 -1
- package/build-types/components/dataviews-view-config/index.d.ts.map +1 -1
- package/build-types/components/stories/index.story.d.ts +4 -0
- package/build-types/components/stories/index.story.d.ts.map +1 -1
- package/build-types/constants.d.ts +2 -2
- package/build-types/dataform-controls/boolean.d.ts.map +1 -1
- package/build-types/dataform-controls/date.d.ts +3 -0
- package/build-types/dataform-controls/date.d.ts.map +1 -0
- package/build-types/dataform-controls/datetime.d.ts.map +1 -1
- package/build-types/dataform-controls/email.d.ts.map +1 -1
- package/build-types/dataform-controls/index.d.ts.map +1 -1
- package/build-types/dataform-controls/integer.d.ts.map +1 -1
- package/build-types/dataform-controls/relative-date-control.d.ts +46 -0
- package/build-types/dataform-controls/relative-date-control.d.ts.map +1 -0
- package/build-types/dataform-controls/select.d.ts.map +1 -1
- package/build-types/dataform-controls/text.d.ts.map +1 -1
- package/build-types/dataviews-layouts/grid/index.d.ts +1 -1
- package/build-types/dataviews-layouts/grid/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/grid/preview-size-picker.d.ts +0 -1
- package/build-types/dataviews-layouts/grid/preview-size-picker.d.ts.map +1 -1
- package/build-types/dataviews-layouts/index.d.ts +3 -3
- package/build-types/dataviews-layouts/list/index.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/column-primary.d.ts.map +1 -1
- package/build-types/dataviews-layouts/table/index.d.ts +1 -1
- package/build-types/dataviews-layouts/table/index.d.ts.map +1 -1
- package/build-types/field-types/array.d.ts.map +1 -1
- package/build-types/field-types/boolean.d.ts +5 -4
- package/build-types/field-types/boolean.d.ts.map +1 -1
- package/build-types/field-types/date.d.ts +20 -0
- package/build-types/field-types/date.d.ts.map +1 -0
- package/build-types/field-types/datetime.d.ts +4 -3
- package/build-types/field-types/datetime.d.ts.map +1 -1
- package/build-types/field-types/email.d.ts +4 -3
- package/build-types/field-types/email.d.ts.map +1 -1
- package/build-types/field-types/index.d.ts.map +1 -1
- package/build-types/field-types/integer.d.ts +4 -3
- package/build-types/field-types/integer.d.ts.map +1 -1
- package/build-types/field-types/media.d.ts +4 -3
- package/build-types/field-types/media.d.ts.map +1 -1
- package/build-types/field-types/text.d.ts +4 -3
- package/build-types/field-types/text.d.ts.map +1 -1
- package/build-types/filter-and-sort-data-view.d.ts.map +1 -1
- package/build-types/normalize-fields.d.ts.map +1 -1
- package/build-types/types.d.ts +25 -8
- package/build-types/types.d.ts.map +1 -1
- package/build-types/validation.d.ts.map +1 -1
- package/build-wp/index.js +2196 -739
- package/package.json +15 -14
- package/src/components/dataform/stories/index.story.tsx +229 -2
- package/src/components/dataviews/index.tsx +30 -10
- package/src/components/dataviews/stories/fixtures.tsx +82 -59
- package/src/components/dataviews/stories/index.story.tsx +65 -8
- package/src/components/dataviews/stories/style.css +6 -0
- package/src/components/dataviews-context/index.ts +8 -2
- package/src/components/dataviews-filters/filter.tsx +17 -7
- package/src/components/dataviews-filters/index.tsx +17 -2
- package/src/components/dataviews-filters/input-widget.tsx +7 -1
- package/src/components/dataviews-filters/reset-filters.tsx +4 -2
- package/src/components/dataviews-filters/style.scss +8 -2
- package/src/components/dataviews-layout/index.tsx +3 -0
- package/src/components/dataviews-view-config/index.tsx +5 -3
- package/src/components/stories/index.story.tsx +21 -0
- package/src/dataform-controls/boolean.tsx +19 -2
- package/src/dataform-controls/date.tsx +499 -0
- package/src/dataform-controls/datetime.tsx +5 -91
- package/src/dataform-controls/email.tsx +19 -2
- package/src/dataform-controls/index.tsx +2 -0
- package/src/dataform-controls/integer.tsx +30 -4
- package/src/dataform-controls/relative-date-control.tsx +106 -0
- package/src/dataform-controls/select.tsx +23 -13
- package/src/dataform-controls/style.scss +19 -2
- package/src/dataform-controls/text.tsx +19 -2
- package/src/dataviews-layouts/grid/index.tsx +168 -55
- package/src/dataviews-layouts/grid/preview-size-picker.tsx +48 -73
- package/src/dataviews-layouts/grid/style.scss +21 -26
- package/src/dataviews-layouts/list/index.tsx +7 -4
- package/src/dataviews-layouts/list/style.scss +3 -3
- package/src/dataviews-layouts/table/column-primary.tsx +29 -5
- package/src/dataviews-layouts/table/index.tsx +134 -42
- package/src/dataviews-layouts/table/style.scss +45 -1
- package/src/field-types/array.tsx +33 -21
- package/src/field-types/boolean.tsx +15 -9
- package/src/field-types/date.ts +92 -0
- package/src/field-types/datetime.tsx +19 -13
- package/src/field-types/email.tsx +26 -21
- package/src/field-types/index.tsx +23 -8
- package/src/field-types/integer.tsx +26 -22
- package/src/field-types/media.tsx +19 -13
- package/src/field-types/text.tsx +19 -13
- package/src/filter-and-sort-data-view.ts +38 -13
- package/src/normalize-fields.ts +4 -8
- package/src/test/dataviews.tsx +129 -0
- package/src/test/filter-and-sort-data-view.js +150 -31
- package/src/test/validation.ts +4 -15
- package/src/types.ts +34 -8
- package/src/validation.ts +30 -1
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/test/dataviews.tsx
CHANGED
|
@@ -285,6 +285,71 @@ describe( 'DataViews component', () => {
|
|
|
285
285
|
await user.click( titleField );
|
|
286
286
|
expect( onClickItemCallback ).toHaveBeenCalledWith( data[ 0 ] );
|
|
287
287
|
} );
|
|
288
|
+
|
|
289
|
+
it( 'accepts click for single selection', async () => {
|
|
290
|
+
render(
|
|
291
|
+
<DataViewWrapper
|
|
292
|
+
view={ {
|
|
293
|
+
...DEFAULT_VIEW,
|
|
294
|
+
fields: [ 'author' ],
|
|
295
|
+
titleField: 'title',
|
|
296
|
+
} }
|
|
297
|
+
// A bulk action is required for the dataview to be multi-selectable.
|
|
298
|
+
actions={ actions }
|
|
299
|
+
/>
|
|
300
|
+
);
|
|
301
|
+
const firstItemElement = screen.getByText( data[ 0 ].title );
|
|
302
|
+
const thirdItemElement = screen.getByText( data[ 2 ].title );
|
|
303
|
+
const user = userEvent.setup();
|
|
304
|
+
await user.click( firstItemElement );
|
|
305
|
+
|
|
306
|
+
// First item should be selected.
|
|
307
|
+
expect(
|
|
308
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
309
|
+
).toBeChecked();
|
|
310
|
+
await user.click( thirdItemElement );
|
|
311
|
+
|
|
312
|
+
// Third item should be selected. First item was deselected.
|
|
313
|
+
expect(
|
|
314
|
+
screen.getByRole( 'checkbox', { name: data[ 2 ].title } )
|
|
315
|
+
).toBeChecked();
|
|
316
|
+
} );
|
|
317
|
+
|
|
318
|
+
it( 'accepts ctrl/cmd key and click for non-consecutive multi-selection', async () => {
|
|
319
|
+
render(
|
|
320
|
+
<DataViewWrapper
|
|
321
|
+
view={ {
|
|
322
|
+
...DEFAULT_VIEW,
|
|
323
|
+
fields: [ 'author' ],
|
|
324
|
+
titleField: 'title',
|
|
325
|
+
} }
|
|
326
|
+
// A bulk action is required for the dataview to be multi-selectable.
|
|
327
|
+
actions={ actions }
|
|
328
|
+
/>
|
|
329
|
+
);
|
|
330
|
+
const firstItemElement = screen.getByText( data[ 0 ].title );
|
|
331
|
+
const thirdItemElement = screen.getByText( data[ 2 ].title );
|
|
332
|
+
const user = userEvent.setup();
|
|
333
|
+
await user.click( firstItemElement );
|
|
334
|
+
|
|
335
|
+
// First item should be selected.
|
|
336
|
+
expect(
|
|
337
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
338
|
+
).toBeChecked();
|
|
339
|
+
await user.keyboard( '{Control>}' );
|
|
340
|
+
await user.click( thirdItemElement );
|
|
341
|
+
|
|
342
|
+
// Both items should be selected.
|
|
343
|
+
expect(
|
|
344
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
345
|
+
).toBeChecked();
|
|
346
|
+
expect(
|
|
347
|
+
screen.getByRole( 'checkbox', { name: data[ 2 ].title } )
|
|
348
|
+
).toBeChecked();
|
|
349
|
+
|
|
350
|
+
// Don't keep the modifier pressed down, that's just mean.
|
|
351
|
+
await user.keyboard( '{/Control}' );
|
|
352
|
+
} );
|
|
288
353
|
} );
|
|
289
354
|
|
|
290
355
|
describe( 'in grid view', () => {
|
|
@@ -363,6 +428,70 @@ describe( 'DataViews component', () => {
|
|
|
363
428
|
await user.click( imageField );
|
|
364
429
|
expect( mediaClickItemCallback ).toHaveBeenCalledWith( data[ 0 ] );
|
|
365
430
|
} );
|
|
431
|
+
|
|
432
|
+
it( 'accepts click for single selection', async () => {
|
|
433
|
+
render(
|
|
434
|
+
<DataViewWrapper
|
|
435
|
+
view={ {
|
|
436
|
+
...DEFAULT_VIEW,
|
|
437
|
+
fields: [ 'author' ],
|
|
438
|
+
titleField: 'title',
|
|
439
|
+
} }
|
|
440
|
+
// A bulk action is required for the dataview to be multi-selectable.
|
|
441
|
+
actions={ actions }
|
|
442
|
+
/>
|
|
443
|
+
);
|
|
444
|
+
const firstItemElement = screen.getByText( data[ 0 ].title );
|
|
445
|
+
const thirdItemElement = screen.getByText( data[ 2 ].title );
|
|
446
|
+
const user = userEvent.setup();
|
|
447
|
+
await user.click( firstItemElement );
|
|
448
|
+
|
|
449
|
+
// First item should be selected.
|
|
450
|
+
expect(
|
|
451
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
452
|
+
).toBeChecked();
|
|
453
|
+
await user.click( thirdItemElement );
|
|
454
|
+
|
|
455
|
+
// Third item should be selected. First item was deselected.
|
|
456
|
+
expect(
|
|
457
|
+
screen.getByRole( 'checkbox', { name: data[ 2 ].title } )
|
|
458
|
+
).toBeChecked();
|
|
459
|
+
} );
|
|
460
|
+
|
|
461
|
+
it( 'accepts ctrl/cmd key and click for non-consecutive multi-selection', async () => {
|
|
462
|
+
render(
|
|
463
|
+
<DataViewWrapper
|
|
464
|
+
view={ {
|
|
465
|
+
...DEFAULT_VIEW,
|
|
466
|
+
fields: [ 'author' ],
|
|
467
|
+
titleField: 'title',
|
|
468
|
+
} }
|
|
469
|
+
// A bulk action is required for the dataview to be multi-selectable.
|
|
470
|
+
actions={ actions }
|
|
471
|
+
/>
|
|
472
|
+
);
|
|
473
|
+
const firstItemElement = screen.getByText( data[ 0 ].title );
|
|
474
|
+
const thirdItemElement = screen.getByText( data[ 2 ].title );
|
|
475
|
+
const user = userEvent.setup();
|
|
476
|
+
await user.click( firstItemElement );
|
|
477
|
+
|
|
478
|
+
// First item should be selected.
|
|
479
|
+
expect(
|
|
480
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
481
|
+
).toBeChecked();
|
|
482
|
+
await user.keyboard( '{Control>}' );
|
|
483
|
+
await user.click( thirdItemElement );
|
|
484
|
+
|
|
485
|
+
// Both items should be selected.
|
|
486
|
+
expect(
|
|
487
|
+
screen.getByRole( 'checkbox', { name: data[ 0 ].title } )
|
|
488
|
+
).toBeChecked();
|
|
489
|
+
expect(
|
|
490
|
+
screen.getByRole( 'checkbox', { name: data[ 2 ].title } )
|
|
491
|
+
).toBeChecked();
|
|
492
|
+
|
|
493
|
+
await user.keyboard( '{/Control}' );
|
|
494
|
+
} );
|
|
366
495
|
} );
|
|
367
496
|
|
|
368
497
|
describe( 'in list view', () => {
|
|
@@ -49,13 +49,15 @@ describe( 'filters', () => {
|
|
|
49
49
|
const { data: result } = filterSortAndPaginate(
|
|
50
50
|
data,
|
|
51
51
|
{
|
|
52
|
-
search: '
|
|
52
|
+
search: 'earth',
|
|
53
53
|
filters: [],
|
|
54
54
|
},
|
|
55
55
|
fields
|
|
56
56
|
);
|
|
57
|
-
expect( result ).toHaveLength(
|
|
58
|
-
expect( result[ 0 ].description ).toBe(
|
|
57
|
+
expect( result ).toHaveLength( 2 );
|
|
58
|
+
expect( result[ 0 ].description ).toBe(
|
|
59
|
+
'The Moon is Earth’s only natural satellite, orbiting at an average distance of 384,400 kilometers with a synchronous rotation that leads to fixed lunar phases as seen from Earth. Its cratered surface and subtle glow define night skies, inspiring exploration missions and influencing tides and biological rhythms worldwide.'
|
|
60
|
+
);
|
|
59
61
|
} );
|
|
60
62
|
|
|
61
63
|
it( 'should perform case-insensitive and accent-insensitive search', () => {
|
|
@@ -71,6 +73,54 @@ describe( 'filters', () => {
|
|
|
71
73
|
expect( result[ 0 ].description ).toBe( 'La planète Vénus' );
|
|
72
74
|
} );
|
|
73
75
|
|
|
76
|
+
it( 'should search over array fields when enableGlobalSearch is true', () => {
|
|
77
|
+
const fieldsWithArraySearch = fields.map( ( field ) =>
|
|
78
|
+
field.id === 'categories'
|
|
79
|
+
? { ...field, enableGlobalSearch: true }
|
|
80
|
+
: field
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const { data: result } = filterSortAndPaginate(
|
|
84
|
+
data,
|
|
85
|
+
{
|
|
86
|
+
search: 'Moon',
|
|
87
|
+
filters: [],
|
|
88
|
+
},
|
|
89
|
+
fieldsWithArraySearch
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Should find items with "satellite" in categories
|
|
93
|
+
expect( result ).toHaveLength( 3 );
|
|
94
|
+
expect( result.map( ( r ) => r.title ).sort() ).toEqual( [
|
|
95
|
+
'Europa',
|
|
96
|
+
'Io',
|
|
97
|
+
'Moon',
|
|
98
|
+
] );
|
|
99
|
+
} );
|
|
100
|
+
|
|
101
|
+
it( 'should search over array fields case-insensitively', () => {
|
|
102
|
+
const fieldsWithArraySearch = fields.map( ( field ) =>
|
|
103
|
+
field.id === 'categories'
|
|
104
|
+
? { ...field, enableGlobalSearch: true }
|
|
105
|
+
: field
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const { data: result } = filterSortAndPaginate(
|
|
109
|
+
data,
|
|
110
|
+
{
|
|
111
|
+
search: 'planet',
|
|
112
|
+
filters: [],
|
|
113
|
+
},
|
|
114
|
+
fieldsWithArraySearch
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Should find items with "Planet" in categories (case-insensitive)
|
|
118
|
+
expect( result ).toHaveLength( 8 );
|
|
119
|
+
expect( result.map( ( r ) => r.title ) ).toContain( 'Neptune' );
|
|
120
|
+
expect( result.map( ( r ) => r.title ) ).toContain( 'Mercury' );
|
|
121
|
+
expect( result.map( ( r ) => r.title ) ).toContain( 'Earth' );
|
|
122
|
+
} );
|
|
123
|
+
|
|
74
124
|
it( 'should search using IS filter', () => {
|
|
75
125
|
const { data: result } = filterSortAndPaginate(
|
|
76
126
|
data,
|
|
@@ -105,9 +155,9 @@ describe( 'filters', () => {
|
|
|
105
155
|
fields
|
|
106
156
|
);
|
|
107
157
|
expect( result ).toHaveLength( 9 );
|
|
108
|
-
expect( result[ 0 ].title ).toBe( '
|
|
109
|
-
expect( result[ 1 ].title ).toBe( '
|
|
110
|
-
expect( result[ 2 ].title ).toBe( '
|
|
158
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
159
|
+
expect( result[ 1 ].title ).toBe( 'Io' );
|
|
160
|
+
expect( result[ 2 ].title ).toBe( 'Europa' );
|
|
111
161
|
expect( result[ 3 ].title ).toBe( 'Mercury' );
|
|
112
162
|
expect( result[ 4 ].title ).toBe( 'Venus' );
|
|
113
163
|
expect( result[ 5 ].title ).toBe( 'Earth' );
|
|
@@ -150,9 +200,9 @@ describe( 'filters', () => {
|
|
|
150
200
|
fields
|
|
151
201
|
);
|
|
152
202
|
expect( result ).toHaveLength( 3 );
|
|
153
|
-
expect( result[ 0 ].title ).toBe( '
|
|
154
|
-
expect( result[ 1 ].title ).toBe( '
|
|
155
|
-
expect( result[ 2 ].title ).toBe( '
|
|
203
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
204
|
+
expect( result[ 1 ].title ).toBe( 'Io' );
|
|
205
|
+
expect( result[ 2 ].title ).toBe( 'Europa' );
|
|
156
206
|
} );
|
|
157
207
|
|
|
158
208
|
it( 'should search using IS ANY filter for ARRAY values', () => {
|
|
@@ -163,15 +213,15 @@ describe( 'filters', () => {
|
|
|
163
213
|
{
|
|
164
214
|
field: 'categories',
|
|
165
215
|
operator: 'isAny',
|
|
166
|
-
value: [ '
|
|
216
|
+
value: [ 'Earth' ],
|
|
167
217
|
},
|
|
168
218
|
],
|
|
169
219
|
},
|
|
170
220
|
fields
|
|
171
221
|
);
|
|
172
222
|
expect( result ).toHaveLength( 2 );
|
|
173
|
-
expect( result[ 0 ].title ).toBe( '
|
|
174
|
-
expect( result[ 1 ].title ).toBe( '
|
|
223
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
224
|
+
expect( result[ 1 ].title ).toBe( 'Earth' );
|
|
175
225
|
} );
|
|
176
226
|
|
|
177
227
|
it( 'should search using IS NONE filter for ARRAY values', () => {
|
|
@@ -182,14 +232,20 @@ describe( 'filters', () => {
|
|
|
182
232
|
{
|
|
183
233
|
field: 'categories',
|
|
184
234
|
operator: 'isNone',
|
|
185
|
-
value: [ '
|
|
235
|
+
value: [ 'Terrestrial' ],
|
|
186
236
|
},
|
|
187
237
|
],
|
|
188
238
|
},
|
|
189
239
|
fields
|
|
190
240
|
);
|
|
191
|
-
expect( result ).toHaveLength(
|
|
192
|
-
expect( result[ 0 ].title ).toBe( '
|
|
241
|
+
expect( result ).toHaveLength( 7 );
|
|
242
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
243
|
+
expect( result[ 1 ].title ).toBe( 'Io' );
|
|
244
|
+
expect( result[ 2 ].title ).toBe( 'Europa' );
|
|
245
|
+
expect( result[ 3 ].title ).toBe( 'Neptune' );
|
|
246
|
+
expect( result[ 4 ].title ).toBe( 'Jupiter' );
|
|
247
|
+
expect( result[ 5 ].title ).toBe( 'Saturn' );
|
|
248
|
+
expect( result[ 6 ].title ).toBe( 'Uranus' );
|
|
193
249
|
} );
|
|
194
250
|
|
|
195
251
|
it( 'should search using IS ALL filter', () => {
|
|
@@ -206,7 +262,7 @@ describe( 'filters', () => {
|
|
|
206
262
|
},
|
|
207
263
|
fields
|
|
208
264
|
);
|
|
209
|
-
expect( result ).toHaveLength(
|
|
265
|
+
expect( result ).toHaveLength( 8 );
|
|
210
266
|
expect( result[ 0 ].title ).toBe( 'Neptune' );
|
|
211
267
|
expect( result[ 1 ].title ).toBe( 'Mercury' );
|
|
212
268
|
expect( result[ 2 ].title ).toBe( 'Venus' );
|
|
@@ -214,6 +270,7 @@ describe( 'filters', () => {
|
|
|
214
270
|
expect( result[ 4 ].title ).toBe( 'Mars' );
|
|
215
271
|
expect( result[ 5 ].title ).toBe( 'Jupiter' );
|
|
216
272
|
expect( result[ 6 ].title ).toBe( 'Saturn' );
|
|
273
|
+
expect( result[ 7 ].title ).toBe( 'Uranus' );
|
|
217
274
|
} );
|
|
218
275
|
|
|
219
276
|
it( 'should search using IS NOT ALL filter', () => {
|
|
@@ -224,16 +281,16 @@ describe( 'filters', () => {
|
|
|
224
281
|
{
|
|
225
282
|
field: 'categories',
|
|
226
283
|
operator: 'isNotAll',
|
|
227
|
-
value: [ 'Planet'
|
|
284
|
+
value: [ 'Planet' ],
|
|
228
285
|
},
|
|
229
286
|
],
|
|
230
287
|
},
|
|
231
288
|
fields
|
|
232
289
|
);
|
|
233
290
|
expect( result ).toHaveLength( 3 );
|
|
234
|
-
expect( result[ 0 ].title ).toBe( '
|
|
235
|
-
expect( result[ 1 ].title ).toBe( '
|
|
236
|
-
expect( result[ 2 ].title ).toBe( '
|
|
291
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
292
|
+
expect( result[ 1 ].title ).toBe( 'Io' );
|
|
293
|
+
expect( result[ 2 ].title ).toBe( 'Europa' );
|
|
237
294
|
} );
|
|
238
295
|
|
|
239
296
|
it( 'should search using IS filter and return all values if filter.value is undefined', () => {
|
|
@@ -251,9 +308,9 @@ describe( 'filters', () => {
|
|
|
251
308
|
fields
|
|
252
309
|
);
|
|
253
310
|
expect( result ).toHaveLength( 11 );
|
|
254
|
-
expect( result[ 0 ].title ).toBe( '
|
|
255
|
-
expect( result[ 1 ].title ).toBe( '
|
|
256
|
-
expect( result[ 2 ].title ).toBe( '
|
|
311
|
+
expect( result[ 0 ].title ).toBe( 'Moon' );
|
|
312
|
+
expect( result[ 1 ].title ).toBe( 'Io' );
|
|
313
|
+
expect( result[ 2 ].title ).toBe( 'Europa' );
|
|
257
314
|
expect( result[ 3 ].title ).toBe( 'Neptune' );
|
|
258
315
|
expect( result[ 4 ].title ).toBe( 'Mercury' );
|
|
259
316
|
expect( result[ 5 ].title ).toBe( 'Venus' );
|
|
@@ -360,15 +417,16 @@ describe( 'filters', () => {
|
|
|
360
417
|
{
|
|
361
418
|
field: 'description',
|
|
362
419
|
operator: 'notContains',
|
|
363
|
-
value: '
|
|
420
|
+
value: 'Solar system',
|
|
364
421
|
},
|
|
365
422
|
],
|
|
366
423
|
},
|
|
367
424
|
fields
|
|
368
425
|
);
|
|
369
|
-
// Only 'NASA photo' and 'La planète Vénus' do not contain 'description'
|
|
370
426
|
expect( result.map( ( r ) => r.description ) ).toEqual( [
|
|
371
|
-
'
|
|
427
|
+
'The Moon is Earth’s only natural satellite, orbiting at an average distance of 384,400 kilometers with a synchronous rotation that leads to fixed lunar phases as seen from Earth. Its cratered surface and subtle glow define night skies, inspiring exploration missions and influencing tides and biological rhythms worldwide.',
|
|
428
|
+
'Moon of Jupiter',
|
|
429
|
+
'Moon of Jupiter',
|
|
372
430
|
'La planète Vénus',
|
|
373
431
|
] );
|
|
374
432
|
} );
|
|
@@ -740,6 +798,45 @@ describe( 'filters', () => {
|
|
|
740
798
|
} );
|
|
741
799
|
|
|
742
800
|
describe( 'sorting', () => {
|
|
801
|
+
it( 'should sort by groupByField first, then by sort.field', () => {
|
|
802
|
+
const { data: result } = filterSortAndPaginate(
|
|
803
|
+
data,
|
|
804
|
+
{
|
|
805
|
+
sort: { field: 'title', direction: 'desc' },
|
|
806
|
+
groupByField: 'type',
|
|
807
|
+
},
|
|
808
|
+
fields
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
expect( result ).toHaveLength( 11 );
|
|
812
|
+
|
|
813
|
+
expect( result[ 0 ].type ).toBe( 'Gas giant' );
|
|
814
|
+
expect( result[ 0 ].title ).toBe( 'Saturn' );
|
|
815
|
+
expect( result[ 1 ].type ).toBe( 'Gas giant' );
|
|
816
|
+
expect( result[ 1 ].title ).toBe( 'Jupiter' );
|
|
817
|
+
|
|
818
|
+
expect( result[ 2 ].type ).toBe( 'Ice giant' );
|
|
819
|
+
expect( result[ 2 ].title ).toBe( 'Uranus' );
|
|
820
|
+
expect( result[ 3 ].type ).toBe( 'Ice giant' );
|
|
821
|
+
expect( result[ 3 ].title ).toBe( 'Neptune' );
|
|
822
|
+
|
|
823
|
+
expect( result[ 4 ].type ).toBe( 'Satellite' );
|
|
824
|
+
expect( result[ 4 ].title ).toBe( 'Moon' );
|
|
825
|
+
expect( result[ 5 ].type ).toBe( 'Satellite' );
|
|
826
|
+
expect( result[ 5 ].title ).toBe( 'Io' );
|
|
827
|
+
expect( result[ 6 ].type ).toBe( 'Satellite' );
|
|
828
|
+
expect( result[ 6 ].title ).toBe( 'Europa' );
|
|
829
|
+
|
|
830
|
+
expect( result[ 7 ].type ).toBe( 'Terrestrial' );
|
|
831
|
+
expect( result[ 7 ].title ).toBe( 'Venus' );
|
|
832
|
+
expect( result[ 8 ].type ).toBe( 'Terrestrial' );
|
|
833
|
+
expect( result[ 8 ].title ).toBe( 'Mercury' );
|
|
834
|
+
expect( result[ 9 ].type ).toBe( 'Terrestrial' );
|
|
835
|
+
expect( result[ 9 ].title ).toBe( 'Mars' );
|
|
836
|
+
expect( result[ 10 ].type ).toBe( 'Terrestrial' );
|
|
837
|
+
expect( result[ 10 ].title ).toBe( 'Earth' );
|
|
838
|
+
} );
|
|
839
|
+
|
|
743
840
|
it( 'should sort integer field types', () => {
|
|
744
841
|
const { data: result } = filterSortAndPaginate(
|
|
745
842
|
data,
|
|
@@ -784,9 +881,9 @@ describe( 'sorting', () => {
|
|
|
784
881
|
fields
|
|
785
882
|
);
|
|
786
883
|
expect( resultDesc ).toHaveLength( 11 );
|
|
787
|
-
expect( resultDesc[ 0 ].title ).toBe( '
|
|
884
|
+
expect( resultDesc[ 0 ].title ).toBe( 'Europa' );
|
|
788
885
|
expect( resultDesc[ 1 ].title ).toBe( 'Earth' );
|
|
789
|
-
expect( resultDesc[ 9 ].title ).toBe( '
|
|
886
|
+
expect( resultDesc[ 9 ].title ).toBe( 'Io' );
|
|
790
887
|
expect( resultDesc[ 10 ].title ).toBe( 'Jupiter' );
|
|
791
888
|
|
|
792
889
|
const { data: resultAsc } = filterSortAndPaginate(
|
|
@@ -798,9 +895,9 @@ describe( 'sorting', () => {
|
|
|
798
895
|
);
|
|
799
896
|
expect( resultAsc ).toHaveLength( 11 );
|
|
800
897
|
expect( resultAsc[ 0 ].title ).toBe( 'Jupiter' );
|
|
801
|
-
expect( resultAsc[ 1 ].title ).toBe( '
|
|
898
|
+
expect( resultAsc[ 1 ].title ).toBe( 'Io' );
|
|
802
899
|
expect( resultAsc[ 9 ].title ).toBe( 'Earth' );
|
|
803
|
-
expect( resultAsc[ 10 ].title ).toBe( '
|
|
900
|
+
expect( resultAsc[ 10 ].title ).toBe( 'Europa' );
|
|
804
901
|
} );
|
|
805
902
|
|
|
806
903
|
it( 'should sort untyped fields if the value is a number', () => {
|
|
@@ -845,6 +942,28 @@ describe( 'sorting', () => {
|
|
|
845
942
|
expect( result[ 0 ].title ).toBe( 'Uranus' );
|
|
846
943
|
expect( result[ 1 ].title ).toBe( 'Neptune' );
|
|
847
944
|
} );
|
|
945
|
+
|
|
946
|
+
it( 'should sort only by groupByField when sort is not specified', () => {
|
|
947
|
+
const { data: result } = filterSortAndPaginate(
|
|
948
|
+
data,
|
|
949
|
+
{
|
|
950
|
+
groupByField: 'type',
|
|
951
|
+
},
|
|
952
|
+
fields
|
|
953
|
+
);
|
|
954
|
+
|
|
955
|
+
let currentType = result[ 0 ].type;
|
|
956
|
+
let groupCount = 1;
|
|
957
|
+
|
|
958
|
+
for ( let i = 1; i < result.length; i++ ) {
|
|
959
|
+
if ( result[ i ].type !== currentType ) {
|
|
960
|
+
currentType = result[ i ].type;
|
|
961
|
+
groupCount++;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
expect( groupCount ).toBe( 4 );
|
|
966
|
+
} );
|
|
848
967
|
} );
|
|
849
968
|
|
|
850
969
|
describe( 'pagination', () => {
|
|
@@ -859,7 +978,7 @@ describe( 'pagination', () => {
|
|
|
859
978
|
fields
|
|
860
979
|
);
|
|
861
980
|
expect( result ).toHaveLength( 2 );
|
|
862
|
-
expect( result[ 0 ].title ).toBe( '
|
|
981
|
+
expect( result[ 0 ].title ).toBe( 'Europa' );
|
|
863
982
|
expect( result[ 1 ].title ).toBe( 'Neptune' );
|
|
864
983
|
expect( paginationInfo ).toStrictEqual( {
|
|
865
984
|
totalItems: data.length,
|
package/src/test/validation.ts
CHANGED
|
@@ -35,7 +35,7 @@ describe( 'validation', () => {
|
|
|
35
35
|
expect( result ).toBe( true );
|
|
36
36
|
} );
|
|
37
37
|
|
|
38
|
-
it( 'integer field is invalid if value is not integer', () => {
|
|
38
|
+
it( 'integer field is invalid if value is not integer when not empty', () => {
|
|
39
39
|
const item = { id: 1, order: 'd' };
|
|
40
40
|
const fields: Field< {} >[] = [
|
|
41
41
|
{
|
|
@@ -48,19 +48,6 @@ describe( 'validation', () => {
|
|
|
48
48
|
expect( result ).toBe( false );
|
|
49
49
|
} );
|
|
50
50
|
|
|
51
|
-
it( 'integer field is invalid if value is empty', () => {
|
|
52
|
-
const item = { id: 1, order: '' };
|
|
53
|
-
const fields: Field< {} >[] = [
|
|
54
|
-
{
|
|
55
|
-
id: 'order',
|
|
56
|
-
type: 'integer',
|
|
57
|
-
},
|
|
58
|
-
];
|
|
59
|
-
const form = { fields: [ 'order' ] };
|
|
60
|
-
const result = isItemValid( item, fields, form );
|
|
61
|
-
expect( result ).toBe( false );
|
|
62
|
-
} );
|
|
63
|
-
|
|
64
51
|
it( 'integer field is invalid if value is not one of the elements', () => {
|
|
65
52
|
const item = { id: 1, author: 3 };
|
|
66
53
|
const fields: Field< {} >[] = [
|
|
@@ -121,7 +108,9 @@ describe( 'validation', () => {
|
|
|
121
108
|
{ value: 'a', label: 'A' },
|
|
122
109
|
{ value: 'b', label: 'B' },
|
|
123
110
|
],
|
|
124
|
-
isValid:
|
|
111
|
+
isValid: {
|
|
112
|
+
custom: () => null, // Overrides the validation provided for integer types.
|
|
113
|
+
},
|
|
125
114
|
},
|
|
126
115
|
];
|
|
127
116
|
const form = { fields: [ 'order' ] };
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ReactElement,
|
|
6
|
+
ReactNode,
|
|
7
|
+
ComponentType,
|
|
8
|
+
ComponentProps,
|
|
9
|
+
} from 'react';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* Internal dependencies
|
|
@@ -94,15 +99,12 @@ export type FieldType =
|
|
|
94
99
|
| 'text'
|
|
95
100
|
| 'integer'
|
|
96
101
|
| 'datetime'
|
|
102
|
+
| 'date'
|
|
97
103
|
| 'media'
|
|
98
104
|
| 'boolean'
|
|
99
105
|
| 'email'
|
|
100
106
|
| 'array';
|
|
101
107
|
|
|
102
|
-
export type ValidationContext = {
|
|
103
|
-
elements?: Option[];
|
|
104
|
-
};
|
|
105
|
-
|
|
106
108
|
/**
|
|
107
109
|
* An abstract interface for Field based on the field type.
|
|
108
110
|
*/
|
|
@@ -115,7 +117,7 @@ export type FieldTypeDefinition< Item > = {
|
|
|
115
117
|
/**
|
|
116
118
|
* Callback used to validate the field.
|
|
117
119
|
*/
|
|
118
|
-
isValid:
|
|
120
|
+
isValid: Rules< Item >;
|
|
119
121
|
|
|
120
122
|
/**
|
|
121
123
|
* Callback used to render an edit control for the field or control name.
|
|
@@ -144,6 +146,11 @@ export type FieldTypeDefinition< Item > = {
|
|
|
144
146
|
enableSorting: boolean;
|
|
145
147
|
};
|
|
146
148
|
|
|
149
|
+
export type Rules< Item > = {
|
|
150
|
+
required?: boolean;
|
|
151
|
+
custom?: ( item: Item, field: NormalizedField< Item > ) => null | string;
|
|
152
|
+
};
|
|
153
|
+
|
|
147
154
|
/**
|
|
148
155
|
* A dataview field for a specific property of a data type.
|
|
149
156
|
*/
|
|
@@ -197,7 +204,7 @@ export type Field< Item > = {
|
|
|
197
204
|
/**
|
|
198
205
|
* Callback used to validate the field.
|
|
199
206
|
*/
|
|
200
|
-
isValid?:
|
|
207
|
+
isValid?: Rules< Item >;
|
|
201
208
|
|
|
202
209
|
/**
|
|
203
210
|
* Callback used to decide if a field should be displayed.
|
|
@@ -249,7 +256,7 @@ export type NormalizedField< Item > = Omit< Field< Item >, 'Edit' > & {
|
|
|
249
256
|
render: ComponentType< DataViewRenderFieldProps< Item > >;
|
|
250
257
|
Edit: ComponentType< DataFormControlProps< Item > > | null;
|
|
251
258
|
sort: ( a: Item, b: Item, direction: SortDirection ) => number;
|
|
252
|
-
isValid:
|
|
259
|
+
isValid: Rules< Item >;
|
|
253
260
|
enableHiding: boolean;
|
|
254
261
|
enableSorting: boolean;
|
|
255
262
|
filterBy: NormalizedFilterByConfig | false;
|
|
@@ -279,6 +286,9 @@ export type DataFormControlProps< Item > = {
|
|
|
279
286
|
export type DataViewRenderFieldProps< Item > = {
|
|
280
287
|
item: Item;
|
|
281
288
|
field: NormalizedField< Item >;
|
|
289
|
+
config?: {
|
|
290
|
+
sizes: string;
|
|
291
|
+
};
|
|
282
292
|
};
|
|
283
293
|
|
|
284
294
|
/**
|
|
@@ -299,6 +309,11 @@ export interface Filter {
|
|
|
299
309
|
* The value to filter by.
|
|
300
310
|
*/
|
|
301
311
|
value: any;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Whether the filter can be edited by the user.
|
|
315
|
+
*/
|
|
316
|
+
isLocked?: boolean;
|
|
302
317
|
}
|
|
303
318
|
|
|
304
319
|
export interface NormalizedFilter {
|
|
@@ -336,6 +351,11 @@ export interface NormalizedFilter {
|
|
|
336
351
|
* Whether it is a primary filter.
|
|
337
352
|
*/
|
|
338
353
|
isPrimary: boolean;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Whether the filter can be edited by the user.
|
|
357
|
+
*/
|
|
358
|
+
isLocked: boolean;
|
|
339
359
|
}
|
|
340
360
|
|
|
341
361
|
interface ViewBase {
|
|
@@ -418,6 +438,11 @@ interface ViewBase {
|
|
|
418
438
|
* Whether to show the hierarchical levels.
|
|
419
439
|
*/
|
|
420
440
|
showLevels?: boolean;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* The field to group by.
|
|
444
|
+
*/
|
|
445
|
+
groupByField?: string;
|
|
421
446
|
}
|
|
422
447
|
|
|
423
448
|
export interface ColumnStyle {
|
|
@@ -610,6 +635,7 @@ export interface ViewBaseProps< Item > {
|
|
|
610
635
|
) => ReactElement;
|
|
611
636
|
isItemClickable: ( item: Item ) => boolean;
|
|
612
637
|
view: View;
|
|
638
|
+
empty: ReactNode;
|
|
613
639
|
}
|
|
614
640
|
|
|
615
641
|
export interface ViewTableProps< Item > extends ViewBaseProps< Item > {
|
package/src/validation.ts
CHANGED
|
@@ -21,7 +21,36 @@ export function isItemValid< Item >(
|
|
|
21
21
|
const _fields = normalizeFields(
|
|
22
22
|
fields.filter( ( { id } ) => !! form.fields?.includes( id ) )
|
|
23
23
|
);
|
|
24
|
+
|
|
25
|
+
const isEmptyNullOrUndefined = ( value: any ) =>
|
|
26
|
+
[ undefined, '', null ].includes( value );
|
|
27
|
+
|
|
24
28
|
return _fields.every( ( field ) => {
|
|
25
|
-
|
|
29
|
+
const value = field.getValue( { item } );
|
|
30
|
+
|
|
31
|
+
if ( field.isValid.required ) {
|
|
32
|
+
if (
|
|
33
|
+
( field.type === 'text' && isEmptyNullOrUndefined( value ) ) ||
|
|
34
|
+
( field.type === 'email' && isEmptyNullOrUndefined( value ) ) ||
|
|
35
|
+
( field.type === 'integer' &&
|
|
36
|
+
isEmptyNullOrUndefined( value ) ) ||
|
|
37
|
+
( field.type === undefined && isEmptyNullOrUndefined( value ) )
|
|
38
|
+
) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if ( field.type === 'boolean' && value !== true ) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (
|
|
48
|
+
typeof field.isValid.custom === 'function' &&
|
|
49
|
+
field.isValid.custom( item, field ) !== null
|
|
50
|
+
) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return true;
|
|
26
55
|
} );
|
|
27
56
|
}
|