Issue views (List / Board / Calendar / Activity)

View on GitHub

Issue views (List / Board / Calendar / Activity)

A project's issues render as a sortable table, a status-grouped Kanban board, a calendar laid out by issue dates, or a chronological activity feed — the same issues.data array (plus, for Calendar and Activity, their own calendarIssues and activityLogs props) presented four different ways, switched with no page reload via a flat IssuePageLooks string type. This category documents how the switch works and what it takes to add a fifth view.

Guides, in the order you'd actually need them

  1. Add a new issue viewIssue views (List / Board / Calendar / Activity)Add a new issue viewWorked example: adding a fifth view, Timeline, alongside the existing List/Board/Calendar/Activity four. Six places need it — miss one and the new view eit… — worked example adding a fifth view, Timeline, across every place the existing four are wired: the type, the render switch, the nav button (plus its keyboard shortcut), and the Account settings default-view picker.

  2. Load a view's data lazilyIssue views (List / Board / Calendar / Activity)Load a view's data lazilyThe project page does not send every view's data on every visit. The table and board read issues (one page), Activity reads activityLogs, and the calendar'… — optional Inertia props, a date-ranged calendar query and why the dashboard only receives counts.

The architecture in one paragraph

IssuePageLooks (resources/js/types/Issues.ts) is 'List' | 'Board' | 'Calendar' | 'Activity' — a closed union with no registry array behind it (unlike settings tabs'Settings tabs/settings is not one page — every tab under it (Preferences, Profile, Notifications, Security & access, Export in the Account section; Labels, Issue Types,… SETTINGS_TABS), so every consumer hardcodes its own list of the four values. Pages/Projects/Show.tsx owns the actual selectedLook state for a project page visit, seeded once from localStorage.getItem('selectedLook') on mount and rendered via a flat ternary chain (selectedLook === 'List' ? <IssueTable /> : selectedLook === 'Board' ? <IssueBoard /> : selectedLook === 'Calendar' ? <CalendarView /> : <ActivityLogs logs={activityLogs.data} />) — List and Board receive the same issues.data, just presented differently, Calendar reads its own date-ranged, optional calendarIssues (see guide 2Issue views (List / Board / Calendar / Activity)Load a view's data lazilyThe project page does not send every view's data on every visit. The table and board read issues (one page), Activity reads activityLogs, and the calendar'…), and Activity instead reads activityLogs (a paginator of ActivityLogEntry, threaded down from ProjectController::show() via ActivityLogService::paginateForProject() — see ../activity-log/README.mdActivity logEvery project-changing action across the app writes a plain-text ActivityLog row — "Changed Jane's role to admin", "Deleted the \"Owner\" role" — and it's… for that read path). Non-obviously, switching the view from the project page's header only updates this page's React state — it never writes back to localStorage — only Account settings → Preferences' issue-view picker (AccountSettingsPreferencesTab) does that, which is why switching views mid-session doesn't "stick" across a reload the way changing your default view in Settings does. 1/2/3/4 are registered as global keyboard shortcutsKeyboard shortcutsEvery keyboard shortcut in Orbit — ? for help, mod+k, alt+p, a page-scoped p for "create project" — goes through one system: ShortcutContext. There's no pe… for the four views directly inside Layouts/MainLayout.tsx, categorized 'View', which also builds the tabs array PageHeader renders for the List/Board/Calendar/Activity toggle.