@object-ui/plugin-view 3.1.0 → 3.1.1
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/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +12 -0
- package/dist/index.js +1249 -1218
- package/dist/index.umd.cjs +3 -3
- package/package.json +7 -7
- package/src/FilterUI.tsx +33 -0
- package/src/ObjectView.tsx +9 -2
- package/src/__tests__/FilterUI.test.tsx +97 -0
package/src/ObjectView.tsx
CHANGED
|
@@ -546,7 +546,7 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
546
546
|
|
|
547
547
|
const filterableFieldDefs = fieldEntries.map(([key, f]: [string, any]) => {
|
|
548
548
|
const fieldType = f.type || 'text';
|
|
549
|
-
let filterType: 'text' | 'number' | 'select' | 'date' | 'boolean' = 'text';
|
|
549
|
+
let filterType: 'text' | 'number' | 'select' | 'multi-select' | 'date' | 'boolean' = 'text';
|
|
550
550
|
let options: Array<{ label: string; value: any }> | undefined;
|
|
551
551
|
|
|
552
552
|
if (fieldType === 'number' || fieldType === 'currency' || fieldType === 'percent') {
|
|
@@ -555,11 +555,18 @@ export const ObjectView: React.FC<ObjectViewProps> = ({
|
|
|
555
555
|
filterType = 'boolean';
|
|
556
556
|
} else if (fieldType === 'date' || fieldType === 'datetime') {
|
|
557
557
|
filterType = 'date';
|
|
558
|
-
} else if (fieldType === 'select' || f.options) {
|
|
558
|
+
} else if (fieldType === 'select' || fieldType === 'status' || f.options) {
|
|
559
559
|
filterType = 'select';
|
|
560
560
|
options = (f.options || []).map((o: any) =>
|
|
561
561
|
typeof o === 'string' ? { label: o, value: o } : { label: o.label, value: o.value },
|
|
562
562
|
);
|
|
563
|
+
} else if (fieldType === 'lookup' || fieldType === 'master_detail' || fieldType === 'user' || fieldType === 'owner') {
|
|
564
|
+
if (f.options && f.options.length > 0) {
|
|
565
|
+
filterType = 'multi-select';
|
|
566
|
+
options = (f.options || []).map((o: any) =>
|
|
567
|
+
typeof o === 'string' ? { label: o, value: o } : { label: o.label, value: o.value },
|
|
568
|
+
);
|
|
569
|
+
}
|
|
563
570
|
}
|
|
564
571
|
return {
|
|
565
572
|
field: key,
|
|
@@ -541,4 +541,101 @@ describe('FilterUI', () => {
|
|
|
541
541
|
window.removeEventListener('filter:changed', spy);
|
|
542
542
|
});
|
|
543
543
|
});
|
|
544
|
+
|
|
545
|
+
// -------------------------------------------------------------------------
|
|
546
|
+
// 9. Multi-select filter type
|
|
547
|
+
// -------------------------------------------------------------------------
|
|
548
|
+
describe('multi-select filter type', () => {
|
|
549
|
+
const multiSelectFilters: FilterUISchema['filters'] = [
|
|
550
|
+
{
|
|
551
|
+
field: 'tags',
|
|
552
|
+
label: 'Tags',
|
|
553
|
+
type: 'multi-select',
|
|
554
|
+
options: [
|
|
555
|
+
{ label: 'Frontend', value: 'frontend' },
|
|
556
|
+
{ label: 'Backend', value: 'backend' },
|
|
557
|
+
{ label: 'DevOps', value: 'devops' },
|
|
558
|
+
],
|
|
559
|
+
},
|
|
560
|
+
];
|
|
561
|
+
|
|
562
|
+
it('renders checkboxes for multi-select type', () => {
|
|
563
|
+
render(
|
|
564
|
+
<FilterUI
|
|
565
|
+
schema={makeSchema({ filters: multiSelectFilters })}
|
|
566
|
+
/>,
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
expect(screen.getByText('Tags')).toBeInTheDocument();
|
|
570
|
+
const checkboxes = screen.getAllByTestId('checkbox');
|
|
571
|
+
expect(checkboxes.length).toBe(3);
|
|
572
|
+
expect(screen.getByText('Frontend')).toBeInTheDocument();
|
|
573
|
+
expect(screen.getByText('Backend')).toBeInTheDocument();
|
|
574
|
+
expect(screen.getByText('DevOps')).toBeInTheDocument();
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it('calls onChange with array when multi-select checkbox is toggled', () => {
|
|
578
|
+
const onChange = vi.fn();
|
|
579
|
+
render(
|
|
580
|
+
<FilterUI
|
|
581
|
+
schema={makeSchema({ filters: multiSelectFilters })}
|
|
582
|
+
onChange={onChange}
|
|
583
|
+
/>,
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
const checkboxes = screen.getAllByTestId('checkbox');
|
|
587
|
+
fireEvent.click(checkboxes[0]); // Frontend
|
|
588
|
+
expect(onChange).toHaveBeenCalledWith({ tags: ['frontend'] });
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('adds to selection when another checkbox is checked', () => {
|
|
592
|
+
const onChange = vi.fn();
|
|
593
|
+
render(
|
|
594
|
+
<FilterUI
|
|
595
|
+
schema={makeSchema({
|
|
596
|
+
filters: multiSelectFilters,
|
|
597
|
+
values: { tags: ['frontend'] },
|
|
598
|
+
})}
|
|
599
|
+
onChange={onChange}
|
|
600
|
+
/>,
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
const checkboxes = screen.getAllByTestId('checkbox');
|
|
604
|
+
fireEvent.click(checkboxes[1]); // Backend
|
|
605
|
+
expect(onChange).toHaveBeenCalledWith({ tags: ['frontend', 'backend'] });
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
it('removes from selection when checkbox is unchecked', () => {
|
|
609
|
+
const onChange = vi.fn();
|
|
610
|
+
render(
|
|
611
|
+
<FilterUI
|
|
612
|
+
schema={makeSchema({
|
|
613
|
+
filters: multiSelectFilters,
|
|
614
|
+
values: { tags: ['frontend', 'backend'] },
|
|
615
|
+
})}
|
|
616
|
+
onChange={onChange}
|
|
617
|
+
/>,
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
// Uncheck Frontend (first checkbox)
|
|
621
|
+
const checkboxes = screen.getAllByTestId('checkbox');
|
|
622
|
+
fireEvent.click(checkboxes[0]); // Frontend
|
|
623
|
+
expect(onChange).toHaveBeenCalledWith({ tags: ['backend'] });
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
it('shows selected count in active badge for popover layout', () => {
|
|
627
|
+
render(
|
|
628
|
+
<FilterUI
|
|
629
|
+
schema={makeSchema({
|
|
630
|
+
layout: 'popover',
|
|
631
|
+
filters: multiSelectFilters,
|
|
632
|
+
values: { tags: ['frontend', 'backend'] },
|
|
633
|
+
})}
|
|
634
|
+
/>,
|
|
635
|
+
);
|
|
636
|
+
|
|
637
|
+
// Active count should be 1 (tags field has a value)
|
|
638
|
+
expect(screen.getByText('1')).toBeInTheDocument();
|
|
639
|
+
});
|
|
640
|
+
});
|
|
544
641
|
});
|