When valueField/textField are not explicitly set in opts, the auto-select
logic (line 1140) and nullable empty-option creation (lines 1144-1145) used
data[0][undefined] which returned undefined, causing:
- Single-option selects to show blank (auto-select failed)
- nullable empty options to have undefined keys
Now extracts vf/tf local variables with ||'value'/||'text' fallback at the
top of build_options(), used consistently throughout.
- Remove unused event.target.bricks_widget assignment
- Add check to prevent clicks on interactive elements (A, BUTTON, INPUT, SELECT, TEXTAREA) from triggering row selection
- This ensures toolbar buttons and form inputs inside rows work correctly
Menu constructor hardcoded background to 'white' when no bgcolor option
was provided. This caused white background in sidebar menus regardless
of theme (dark/light). Changed default to 'transparent' so Menu inherits
parent container's themed background color.
- .menuitem: dark bg #334155 + light text #E2E8F0 (with !important to
override Menu widget's inline backgroundColor:white)
- .popup .vbox/.vcontainer/.vscroll: override inline white bg
- .popup h1-h6: light text color for headings
- .mini-window: dark card style for WindowsPanel dock items
- .toppopup: dark shadow variant
Sage shell defaults to dark theme but bricks.css had no dark rules,
causing light-gray text (#8a8a8a) on light backgrounds (#fafafa/#efefef)
in CRUD tables — unreadable against the dark shell.
Added comprehensive [data-theme=dark] overrides:
- body: #CBD5E1 text on #0F172A bg
- .card/.tabular/.tabular-row: dark slate backgrounds
- .inputbox/.popup/.modal/.toolbar: dark variants
- .accordion/.tabpanel/.message: dark variants
When CRUD JSON has data_filter in params:
- Toolbar shows a '搜索' button (name:'filter')
- Click opens PopupWindow with Form widget
- Form fields are dynamically generated from data_filter definition
- Extracts all {var, field, op} from AND/OR/NOT nested structure
- Supports dropdown (uitype:'code') via browserfields.alters config
- Customizable labels via filter_labels option
- Form submit collects values → stored in this.filter_values
- merge_search_params() sends data_filter (JSON string) + each var value
to backend API as URL parameters
- Backend .dspy uses sqlor.filter.DBFilter.gen(ns) for SQL WHERE clause
Deleted previous inline DataFilter widget approach; replaced with
popup Form pattern that matches existing CRUD edit/add form UX.
- New bricks.DataFilter widget (bricks/data_filter.js): parses data_filter
JSON definition, renders search input fields for each var parameter,
supports AND/OR/NOT nested structures, and UiCode dropdowns for fields
with browserfields.alters uitype=code configuration.
- Modified DataViewer (bricks/dataviewer.js): added build_datafilter_widget(),
filter_event_handle(), filter_clear_handle() methods; extended
merge_search_params() to send data_filter JSON + collected var values
to the backend API.
- Updated build.sh: added data_filter.js to the JS concatenation list.
Backend integration: DataViewer sends data_filter (JSON string) and
each var's user input value as URL params. Backend .dspy uses
sqlor.filter.DBFilter to convert to SQL WHERE clause.