From 30c38f311f3ff895f7c9bd83938fa1cec756c5a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 12:28:08 +0000 Subject: [PATCH 1/3] Initial plan From bbc39dc0f3e078e4538def18e6e7d8e43694e415 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 12:33:40 +0000 Subject: [PATCH 2/3] fix: propagate showSearch/showFilters/showSort in renderListView and conditionally render toolbar controls - Add showSearch/showFilters/showSort/striped/bordered/color to renderListView schema in ObjectView.tsx (plugin-view) - Conditionally render Search, Filter, Sort toolbar buttons in ListView.tsx based on schema flags - Add 7 new tests for toolbar toggle visibility in ListView - Add 2 new tests for renderListView schema propagation in ObjectView Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/plugin-list/src/ListView.tsx | 6 ++ .../src/__tests__/ListView.test.tsx | 95 +++++++++++++++++++ packages/plugin-view/src/ObjectView.tsx | 8 ++ .../src/__tests__/ObjectView.test.tsx | 59 ++++++++++++ 4 files changed, 168 insertions(+) diff --git a/packages/plugin-list/src/ListView.tsx b/packages/plugin-list/src/ListView.tsx index 5324ed511..568134515 100644 --- a/packages/plugin-list/src/ListView.tsx +++ b/packages/plugin-list/src/ListView.tsx @@ -871,6 +871,7 @@ export const ListView: React.FC = ({ {/* Filter */} + {schema.showFilters !== false && ( {/* Sort */} + {schema.showSort !== false && ( )} + )} diff --git a/packages/plugin-list/src/__tests__/ListView.test.tsx b/packages/plugin-list/src/__tests__/ListView.test.tsx index 23b5839f8..722bb37e1 100644 --- a/packages/plugin-list/src/__tests__/ListView.test.tsx +++ b/packages/plugin-list/src/__tests__/ListView.test.tsx @@ -598,4 +598,99 @@ describe('ListView', () => { expect(screen.queryByTestId('user-filters')).not.toBeInTheDocument(); }); }); + + // ============================ + // Toolbar Toggle Visibility + // ============================ + describe('Toolbar Toggle Visibility', () => { + it('should hide Search button when showSearch is false', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showSearch: false, + }; + + renderWithProvider(); + expect(screen.queryByRole('button', { name: /search/i })).not.toBeInTheDocument(); + }); + + it('should show Search button when showSearch is true', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showSearch: true, + }; + + renderWithProvider(); + expect(screen.getByRole('button', { name: /search/i })).toBeInTheDocument(); + }); + + it('should show Search button when showSearch is undefined (default)', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + }; + + renderWithProvider(); + expect(screen.getByRole('button', { name: /search/i })).toBeInTheDocument(); + }); + + it('should hide Filter button when showFilters is false', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showFilters: false, + }; + + renderWithProvider(); + expect(screen.queryByRole('button', { name: /filter/i })).not.toBeInTheDocument(); + }); + + it('should show Filter button when showFilters is true', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showFilters: true, + }; + + renderWithProvider(); + expect(screen.getByRole('button', { name: /filter/i })).toBeInTheDocument(); + }); + + it('should hide Sort button when showSort is false', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showSort: false, + }; + + renderWithProvider(); + expect(screen.queryByRole('button', { name: /^sort$/i })).not.toBeInTheDocument(); + }); + + it('should show Sort button when showSort is true', () => { + const schema: ListViewSchema = { + type: 'list-view', + objectName: 'contacts', + viewType: 'grid', + fields: ['name', 'email'], + showSort: true, + }; + + renderWithProvider(); + expect(screen.getByRole('button', { name: /^sort$/i })).toBeInTheDocument(); + }); + }); }); diff --git a/packages/plugin-view/src/ObjectView.tsx b/packages/plugin-view/src/ObjectView.tsx index ecc10ce1c..3fa439f72 100644 --- a/packages/plugin-view/src/ObjectView.tsx +++ b/packages/plugin-view/src/ObjectView.tsx @@ -813,6 +813,14 @@ export const ObjectView: React.FC = ({ densityMode: activeView?.densityMode, groupBy: activeView?.groupBy, options: currentNamedViewConfig?.options || activeView, + // Propagate toolbar toggle flags + showSearch: activeView?.showSearch ?? schema.showSearch, + showFilters: activeView?.showFilters ?? schema.showFilters, + showSort: activeView?.showSort ?? schema.showSort, + // Propagate display properties + striped: activeView?.striped ?? (schema as any).striped, + bordered: activeView?.bordered ?? (schema as any).bordered, + color: activeView?.color ?? (schema as any).color, }, dataSource, onEdit: handleEdit, diff --git a/packages/plugin-view/src/__tests__/ObjectView.test.tsx b/packages/plugin-view/src/__tests__/ObjectView.test.tsx index 9c59e4909..321e0ad75 100644 --- a/packages/plugin-view/src/__tests__/ObjectView.test.tsx +++ b/packages/plugin-view/src/__tests__/ObjectView.test.tsx @@ -549,5 +549,64 @@ describe('ObjectView', () => { // Component renders without crash — showSort is respected expect(screen.getByTestId('object-grid')).toBeInTheDocument(); }); + + it('should include showSearch/showFilters/showSort in renderListView schema', async () => { + const schema: ObjectViewSchema = { + type: 'object-view', + objectName: 'contacts', + showSearch: false, + showFilters: false, + showSort: false, + }; + + const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => ( +
Custom ListView
+ )); + + render( + , + ); + + expect(renderListViewSpy).toHaveBeenCalled(); + const callSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema; + expect(callSchema?.showSearch).toBe(false); + expect(callSchema?.showFilters).toBe(false); + expect(callSchema?.showSort).toBe(false); + }); + + it('should propagate showSearch/showFilters/showSort from activeView in renderListView', async () => { + const schema: ObjectViewSchema = { + type: 'object-view', + objectName: 'contacts', + }; + + const renderListViewSpy = vi.fn(({ schema: listSchema }: any) => ( +
Custom ListView
+ )); + + const views = [ + { id: 'v1', label: 'View 1', type: 'grid' as const, showSearch: false, showFilters: false, showSort: false }, + ]; + + render( + , + ); + + expect(renderListViewSpy).toHaveBeenCalled(); + const callSchema = renderListViewSpy.mock.calls[0]?.[0]?.schema; + expect(callSchema?.showSearch).toBe(false); + expect(callSchema?.showFilters).toBe(false); + expect(callSchema?.showSort).toBe(false); + }); }); }); From 989926f847ff87a57c17d980f6a455f50839a3a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 12:43:00 +0000 Subject: [PATCH 3/3] docs: update ROADMAP.md with toolbar toggle fix status (PR #771) Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- ROADMAP.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 9008113ca..1d2938038 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -216,12 +216,16 @@ ObjectUI is a universal Server-Driven UI (SDUI) engine built on React + Tailwind 1. ~~**`generateViewSchema` (plugin-view):** Hardcodes `showSearch: false` for non-grid views~~ → Now propagates from `activeView` 2. ~~**Console `renderListView`:** Omits toolbar/display flags from `fullSchema`~~ → Now passes all config properties 3. ~~**`NamedListView` type:** Missing toolbar/display properties~~ → Added as first-class properties -4. **No per-view-type integration tests:** Pending — tests verify config reaches `fullSchema`, but per-renderer integration tests still needed +4. ~~**Plugin `renderListView` schema missing toolbar flags:** `renderContent` → `renderListView` schema did not include `showSearch`/`showFilters`/`showSort`~~ → Now propagated (PR #771) +5. ~~**ListView toolbar unconditionally rendered:** Search/Filter/Sort buttons always visible regardless of schema flags~~ → Now conditionally rendered based on `schema.showSearch`/`showFilters`/`showSort` (PR #771) +6. **No per-view-type integration tests:** Pending — tests verify config reaches `fullSchema`, but per-renderer integration tests still needed **Phase 1 — Grid/Table View (baseline, already complete):** - [x] `gridSchema` includes `striped`/`bordered` from `activeView` - [x] `showSort`/`showSearch`/`showFilters` passed via `ObjectViewSchema` - [x] `useMemo` dependency arrays cover all grid config +- [x] ListView toolbar buttons conditionally rendered based on `schema.showSearch`/`showFilters`/`showSort` (PR #771) +- [x] `renderListView` schema includes toolbar toggle flags (`showSearch`/`showFilters`/`showSort`) and display props (`striped`/`bordered`/`color`) (PR #771) **Phase 2 — Kanban Live Preview:** - [x] Propagate `showSort`/`showSearch`/`showFilters` through `generateViewSchema` kanban branch