mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
* improvement(tables): improve table filtering UX - Replace popover filter with persistent inline panel below toolbar - Add AND/OR toggle between filter rules (shown in Where label slot) - Sync filter panel state from applied filter on open - Show filter button active state when filter is applied or panel is open - Use readable operator labels matching dropdown options - Add Clear filters button (shown only when filter is active) - Close filter panel when last rule is removed via X - Fix empty gap rows appearing in filtered results by skipping position gap rendering when filter is active - Add toggle mode to ResourceOptionsBar for inline panel pattern - Memoize FilterRuleRow for perf, fix filterTags key collision, remove dead filterActiveCount prop * fix(table-filter): use ref to stabilize handleRemove/handleApply callbacks Reading rules via ref instead of closure eliminates rules from useCallback dependency arrays, keeping callbacks stable across rule edits and preserving the memo() benefit on FilterRuleRow. * improvement(tables,kb): remove hacky patterns, fix KB filter popover width - Remove non-TSDoc comment from table-filter (rulesRef pattern is self-evident) - Simplify SearchSection: remove setState-during-render anti-pattern; controlled input binds directly to search.value/onChange (simpler and correct) - Reduce KB filter popover from w-[320px] to w-[200px]; tag filter uses vertical layout so narrow width works; Status-only case is now appropriately compact * feat(knowledge): add sort and filter to KB list page Sort dropdown: name, documents, tokens, created, last updated — pre-sorted externally before passing rows to Resource. Active sort highlights the Sort button; clear resets to default (created desc). Filter popover: filter by connector status (All / With connectors / Without connectors). Active filter shown as a removable tag in the toolbar. * feat(files): add sort and filter to files list page * feat(scheduled-tasks): add sort and filter to scheduled tasks page * fix(table-filter): use explicit close handler instead of toggle * improvement(files,knowledge): replace manual debounce with useDebounce hook and use type guards for file filtering * fix(resource): prevent popover from inheriting anchor min-width * feat(tables): add sort to tables list page * feat(knowledge): add content and owner filters to KB list * feat(scheduled-tasks): add status and health filters * feat(files): add size and uploaded-by filters to files list * feat(tables): add row count, owner, and column type filters * improvement(scheduled-tasks): use combobox filter panel matching logs UI style * improvement(knowledge): use combobox filter panel matching logs UI style * improvement(files): use combobox filter panel matching logs UI style Replaces button-list filters with Combobox-based multi-select sections for file type, size, and uploaded-by filters, aligning the panel with the logs page filter UI. * improvement(tables): use combobox filter panel matching logs UI style * feat(settings): add sort to recently deleted page Add a sort dropdown next to the search bar allowing users to sort by deletion date (default, newest first), name (A–Z), or type (A–Z). * feat(logs): add sort to logs page * improvement(knowledge): upgrade document list filter to combobox style * fix(resources): fix missing imports, memoization, and stale refs across resource pages * improvement(tables): remove column type filter * fix(resources): fix filter/sort correctness issues from audit * fix(chunks): add server-side sort to document chunks API Chunk sort was previously done client-side on a single page of server-paginated data, which only reordered the current page. Now sort params (sortBy, sortOrder) flow through the full stack: types → service → API route → query hook → useDocumentChunks → document.tsx. * perf(resources): memoize filterContent JSX across all resource pages Resource is wrapped in React.memo, so an unstable filterContent reference on every parent re-render defeats the memo. Wrap filterContent in useMemo with correct deps in all 6 pages (files, tables, scheduled-tasks, knowledge, base, document). * fix(resources): add missing sort options for all visible columns Every column visible in a resource table should be sortable. Three pages had visible columns with no sort support: - files.tsx: add 'owner' sort (member name lookup) - scheduled-tasks.tsx: add 'schedule' sort (localeCompare on description) - knowledge.tsx: add 'connectors' (count) and 'owner' (member name) sorts Also add 'members' to processedKBs deps in knowledge.tsx since owner sort now reads member names inside the memo. * whitelabeling updates, sidebar fixes, files bug * increased type safety * pr fixes
62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
/**
|
|
* Helper to detect if background is dark
|
|
*/
|
|
function isDarkBackground(hexColor: string): boolean {
|
|
const hex = hexColor.replace('#', '')
|
|
const r = Number.parseInt(hex.substr(0, 2), 16)
|
|
const g = Number.parseInt(hex.substr(2, 2), 16)
|
|
const b = Number.parseInt(hex.substr(4, 2), 16)
|
|
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
|
|
return luminance < 0.5
|
|
}
|
|
|
|
function getContrastTextColor(hexColor: string): string {
|
|
return isDarkBackground(hexColor) ? '#ffffff' : '#000000'
|
|
}
|
|
|
|
export function generateThemeCSS(): string {
|
|
const cssVars: string[] = []
|
|
|
|
if (process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR) {
|
|
cssVars.push(`--brand: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
cssVars.push(`--brand-accent: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
cssVars.push(`--auth-primary-btn-bg: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
cssVars.push(`--auth-primary-btn-border: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
cssVars.push(`--auth-primary-btn-hover-bg: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
cssVars.push(`--auth-primary-btn-hover-border: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR};`)
|
|
const primaryTextColor = getContrastTextColor(process.env.NEXT_PUBLIC_BRAND_PRIMARY_COLOR)
|
|
cssVars.push(`--auth-primary-btn-text: ${primaryTextColor};`)
|
|
cssVars.push(`--auth-primary-btn-hover-text: ${primaryTextColor};`)
|
|
}
|
|
|
|
if (process.env.NEXT_PUBLIC_BRAND_PRIMARY_HOVER_COLOR) {
|
|
cssVars.push(`--brand-hover: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_HOVER_COLOR};`)
|
|
cssVars.push(
|
|
`--auth-primary-btn-hover-bg: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_HOVER_COLOR};`
|
|
)
|
|
cssVars.push(
|
|
`--auth-primary-btn-hover-border: ${process.env.NEXT_PUBLIC_BRAND_PRIMARY_HOVER_COLOR};`
|
|
)
|
|
cssVars.push(
|
|
`--auth-primary-btn-hover-text: ${getContrastTextColor(process.env.NEXT_PUBLIC_BRAND_PRIMARY_HOVER_COLOR)};`
|
|
)
|
|
}
|
|
|
|
if (process.env.NEXT_PUBLIC_BRAND_ACCENT_COLOR) {
|
|
cssVars.push(`--brand-link: ${process.env.NEXT_PUBLIC_BRAND_ACCENT_COLOR};`)
|
|
}
|
|
|
|
if (process.env.NEXT_PUBLIC_BRAND_ACCENT_HOVER_COLOR) {
|
|
cssVars.push(`--brand-link-hover: ${process.env.NEXT_PUBLIC_BRAND_ACCENT_HOVER_COLOR};`)
|
|
}
|
|
|
|
if (process.env.NEXT_PUBLIC_BRAND_BACKGROUND_COLOR) {
|
|
const isDark = isDarkBackground(process.env.NEXT_PUBLIC_BRAND_BACKGROUND_COLOR)
|
|
if (isDark) {
|
|
cssVars.push(`--brand-is-dark: 1;`)
|
|
}
|
|
}
|
|
|
|
return cssVars.length > 0 ? `:root { ${cssVars.join(' ')} }` : ''
|
|
}
|