Skip to content

improvement(ui): fix nav loading flash, skeleton mismatches, and React anti-patterns across resource pages#3864

Merged
waleedlatif1 merged 6 commits intostagingfrom
feat/kb-loading
Mar 31, 2026
Merged

improvement(ui): fix nav loading flash, skeleton mismatches, and React anti-patterns across resource pages#3864
waleedlatif1 merged 6 commits intostagingfrom
feat/kb-loading

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Convert knowledge, files, tables, scheduled-tasks, and home `page.tsx` files from async server components to simple client re-exports — eliminates the full-page loading skeleton flash on every navigation between tabs
  • Add client-side permission redirects via `usePermissionConfig` to replace the removed server-side checks in knowledge, files, and tables
  • Fix knowledge loading skeleton column count (6→7); fix tables loading skeleton (remove phantom checkbox column that doesn't exist in the real table)
  • Fix connector documents not appearing live after creation — `isConnectorSyncingOrPending` now used instead of `status === 'syncing'`, so polling activates immediately on connector creation before the first sync runs
  • Remove dead chunk-switch `useEffect` in `ChunkEditor` (made redundant by `key={selectedChunk.id}` remount in parent)
  • Replace `useState` + `useEffect` debounce anti-pattern with `useDebounce` hook in `document.tsx`
  • Replace `useRef` + `useEffect` one-time URL init with lazy `useState` initializers in `document.tsx` and `logs.tsx`
  • Make `handleToggleEnabled` optimistic — cache updates immediately, mutation fires async, `onError` rolls back
  • Replace `mutate` + `new Promise` wrapper with `mutateAsync` + `try/catch` in rename handler
  • Fix `schedule-modal.tsx`: replace 15-setter `useEffect` init with lazy `useState` initializers + `key` prop remount at call site; wrap `parseCronToScheduleType` in `useMemo`
  • Fix logs search: remove mount-only `useEffect` (with `eslint-disable` comment) by passing `initialQuery` to `useSearchState`; parse query string once via shared `initialParsed` state
  • Add `useWorkspaceFileRecord` hook (selects from list cache — zero extra network request when list is already cached); refactor `FileViewer` to self-fetch
  • Fix `value: any` → `value: string` in `useTagSelection` and `collaborativeSetTagSelection`; fix `knowledge-tag-filters.tsx` to pass `''` instead of `null` when filters are cleared
  • Sidebar: fix workflow item active highlight to include multi-select state; fix workspace header context menu to keep item highlighted while menu is open; add `transition-opacity` consistency to task items

Type of Change

  • Bug fix
  • Improvement

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…t anti-patterns across resource pages

- Convert knowledge, files, tables, scheduled-tasks, and home page.tsx files from async server components to simple client re-exports, eliminating the loading.tsx flash on every navigation
- Add client-side permission redirects (usePermissionConfig) to knowledge, files, and tables components to replace server-side checks
- Fix knowledge loading.tsx skeleton column count (6→7) and tables loading.tsx (remove phantom checkbox column)
- Fix connector document live updates: use isConnectorSyncingOrPending instead of status === 'syncing' so polling activates immediately after connector creation
- Remove dead chunk-switch useEffect in ChunkEditor (redundant with key prop remount)
- Replace useState+useEffect debounce with useDebounce hook in document.tsx
- Replace useRef+useEffect URL init with lazy useState initializers in document.tsx and logs.tsx
- Make handleToggleEnabled optimistic in document.tsx (cache first, onError rollback)
- Replace mutate+new Promise wrapper with mutateAsync+try/catch in base.tsx
- Fix schedule-modal.tsx: replace 15-setter useEffect with useState lazy initializers + key prop remount; wrap parseCronToScheduleType in useMemo
- Fix logs search: eliminate mount-only useEffect with eslint-disable by passing initialQuery to useSearchState; parse query once via shared initialParsed state
- Add useWorkspaceFileRecord hook to workspace-files.ts; refactor FileViewer to self-fetch
- Fix value: any → value: string in useTagSelection and collaborativeSetTagSelection
- Fix knowledge-tag-filters.tsx: pass '' instead of null when filters are cleared (type safety)
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 31, 2026 6:24pm

Request Review

@cursor
Copy link
Copy Markdown

cursor bot commented Mar 31, 2026

PR Summary

Medium Risk
Moves several workspace tab routes from server-side session/membership checks to client-side rendering and redirects, which could affect access control behavior if other guards aren’t in place. Also refactors several data-fetching and optimistic-update paths (files viewer, knowledge chunks, connectors polling), which may introduce subtle UI/state regressions.

Overview
Eliminates async server page.tsx wrappers for workspace tabs (Home, Files, Knowledge, Tables, Scheduled Tasks, and file view routes) by re-exporting the client components directly, reducing full-page loading/skeleton flashes during tab navigation.

Shifts tab visibility enforcement to the client by adding usePermissionConfig()-driven redirects in Files, Knowledge, and Tables, and refactors file viewing so FileViewer self-fetches via new useWorkspaceFileRecord() (selecting from the existing files list query cache).

Fixes several UI/state issues: skeleton column mismatches (Knowledge, Tables), more robust connector polling by treating newly-created connectors as pending sync, optimistic chunk enable/disable with rollback on error, and removes mount-only useEffect anti-patterns by using debounced hooks/lazy useState initialization (including logs search initialization). Also stabilizes scheduled-task editing by initializing modal state from props and forcing remount via key, plus small sidebar selection/highlight and tag-selection typing/serialization fixes.

Written by Cursor Bugbot for commit 3d5b7f2. Configure here.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 31, 2026

Greptile Summary

This PR is a broad quality pass across the workspace resource pages, addressing a noticeable full-page skeleton flash on tab navigation, several React anti-patterns, and a handful of UI/state bugs.

Key changes:

  • Nav flash fix: knowledge, files, tables, scheduled-tasks, and home page.tsx files are converted from async server components to simple client re-exports. Tab-specific permission redirects (hideKnowledgeBaseTab, hideFilesTab, hideTablesTab) are relocated to the corresponding client components via usePermissionConfig + useEffect.
  • React anti-patterns removed: useState + useEffect debounce → useDebounce; mount-only useEffect URL init → lazy useState initializers; useRef + useEffect one-time inits → lazy useRef sentinel pattern; 15-setter useEffect in ScheduleModal → lazy useState initializers + key prop remount at call site; mutate + new Promise wrapper → mutateAsync + try/catch.
  • Bug fixes: isConnectorSyncingOrPending replaces status === 'syncing' so polling activates immediately on connector creation; knowledge loading skeleton column count corrected 6→7; phantom checkbox column removed from tables skeleton; optimistic toggle-enabled with onError rollback; dead chunk-switch useEffect removed.
  • Type safety: value: anyvalue: string in useTagSelection and collaborativeSetTagSelection; null'' in knowledge-tag-filters to match the string contract.
  • New useWorkspaceFileRecord hook: selects from the shared list cache on warm path (zero extra request); JSDoc documents the cold-path trade-off.
  • Sidebar polish: multi-select active highlight, workspace header context-menu highlight persistence, transition-opacity consistency.

Confidence Score: 5/5

Safe to merge — all prior review concerns are addressed and no new P0/P1 issues were found.

All three previously-raised concerns (fileId missing from query key, ScheduleModal key-based remount contract, FileViewer silent null) are resolved with JSDoc or explicit design acknowledgement. The only remaining finding is a P2 style suggestion in schedule-modal.tsx — no data loss, broken paths, or security issues identified.

schedule-modal.tsx — useMemo/useState initializer style concern (P2 only)

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/scheduled-tasks/components/create-schedule-modal/schedule-modal.tsx Replaces 15-setter useEffect with lazy useState initializers; uses useMemo to compute initialCronState — but the [schedule] dependency means it recomputes after mount when schedule changes while state values stay frozen
apps/sim/app/workspace/[workspaceId]/logs/logs.tsx Replaces mount-only useEffect URL init with lazy useState and inline ref initialization; clean and correct with proper SSR guards
apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx Replaces useState+useEffect debounce with useDebounce hook, lazy URL param init, and optimistic toggle-enabled — all correct patterns
apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx Fixes connector polling by using isConnectorSyncingOrPending instead of status === 'syncing'; replaces mutate+new Promise wrapper with mutateAsync+try/catch
apps/sim/app/workspace/[workspaceId]/files/[fileId]/view/file-viewer.tsx Refactored to self-fetch via useWorkspaceFileRecord hook; null render during loading is intentional per prior thread discussion
apps/sim/hooks/queries/workspace-files.ts New useWorkspaceFileRecord hook with clear JSDoc documenting warm/cold path trade-off; correctly shares list query key
apps/sim/app/workspace/[workspaceId]/logs/hooks/use-search-state.ts Adds initialQuery support via lazy useState initializer; removes eslint-disable mount-only useEffect; removes as-any cast from filter field
apps/sim/hooks/use-collaborative-workflow.ts Type safety fix: collaborativeSetTagSelection parameter changed from any to string

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["page.tsx server re-export"] --> B["Client Component"]
    B --> C{usePermissionConfig}
    C -- tab hidden --> D["router.replace to workspace"]
    C -- tab visible --> E["Render UI"]

    subgraph warmPath["Warm path"]
        F["useWorkspaceFileRecord"] --> G["React Query list cache hit"]
        G --> H["select by fileId"]
    end

    subgraph coldPath["Cold path"]
        F --> I["fetchWorkspaceFiles full list"]
        I --> H
    end

    subgraph modalRemount["ScheduleModal remount"]
        J["key prop on ScheduleModal"] --> K["Remount on task switch"]
        K --> L["useState lazy initializers run once"]
    end

    subgraph connectorFix["Connector polling fix"]
        M["isConnectorSyncingOrPending"] --> N["Polling activates on pending and syncing"]
        O["old: status syncing only"] --> P["Missed fresh connector pending state"]
    end
Loading

Reviews (3): Last reviewed commit: "fix(scheduled-tasks): correct useMemo de..." | Re-trigger Greptile

…s to useWorkspaceFileRecord, document key remount requirement in ScheduleModal
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@waleedlatif1 waleedlatif1 merged commit 4544fd4 into staging Mar 31, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/kb-loading branch March 31, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant