Conversation
|
discussed with EricG, going to merge changes form #8474 to this PR :) |
|
@ericpgreen2 i havent added e2e! wanted to get your feedback on the look and feel. added the features in your draft :) |
begelundmuller
left a comment
There was a problem hiding this comment.
Backend changes look okay
Code Review SummaryReviewed the Project Status page enhancements. The PR is well-structured with clean architecture and good test coverage. ✅ Highlights
✅ Fixes Applied
Minor Suggestions (Non-blocking)
Approved ✓ |
ericpgreen2
left a comment
There was a problem hiding this comment.
Nice work on the individual components here — the info grid, resource filtering, and logs stream are all well-built. Before iterating on the code, though, I think we should step back and align on the information architecture for the project admin pages. A few observations:
The single-item left nav. The new Status layout introduces a LeftNav with one item ("Project Status"). This takes ~180px of horizontal space without adding navigational value, and signals future expansion without committing to it. If we're going to have a left nav, we should decide now what the full set of sub-pages will be.
The Status page is doing a lot. It currently serves four roles in one scrolling page: project configuration info (GitHub, OLAP, AI, Local Dev), resource health (the table), parse errors, and live logs. These serve different use cases — an admin checking connector config shouldn't need to scroll past a resource table to find logs buried at the bottom.
Status and Settings are both "project admin" but siloed. GitHub connection, connector info, environment variables, and public URLs are all facets of project configuration, but they're split across two top-level tabs with separate left navs.
One possible direction: merge Status and Settings into a single section with sub-pages that justify the left nav:
- Overview — deployment status, version, connectors, GitHub, local dev
- Resources — resource table with filtering (parse errors fold in here)
- Logs — gets its own page instead of being buried
- Environment Variables — moved from Settings
- Public URLs — moved from Settings
This is just one option. The key decision is: what sub-pages justify the left nav, and should Status and Settings be one section or two? I think we should sketch this out and agree on it before going further with the code.
Developed in collaboration with Claude Code
|
Discussed the above with Di and EricO, Have a good idea on how to move forward, with a few changes to our original plan. https://www.loom.com/share/a51e74d080c24ac4b32f231a7a2ce4c7
|
kill dead code, PR review
PR Review: #8718 — feat: project status page51 files changed | +2,330 / -463 | OverviewRebuilds the project status page into a multi-tab layout with:
What Looks Good
|
There was a problem hiding this comment.
The IA refactor is solid — the Status/Settings split, sub-page structure, and overview design are all big improvements. Here are the issues I found, in priority order.
Blocking
1. Reports and Alerts tabs are hidden from non-admin users. ProjectTabs.svelte replaced the reports and alerts feature flags (both default true) with projectPermissions.manageProject. Viewers who previously saw these tabs no longer can. The original hasPermission values should be restored.
2. Filter state is read from the URL but never written back. ProjectResources.svelte reads ?kind= and ?error= on mount, but toggleType, toggleStatus, and clearFilters only update local state. Refreshing the page or sharing the link loses the filter. The frontend guide is clear on this: "When state can be represented in the URL, it should be." Filters, search text, and status should all sync to URL params.
3. Empty table shows no empty-state message. When filters produce zero results (e.g. filtering by "Error" when there are none), the resources table shows headers but no body — no "no results" message. The root cause is in VirtualizedTable.svelte:107: dynamicContainerHeight = rows.length <= 10 ? rowHeight * rows.length : containerHeight. When rows.length === 0, the height evaluates to 0px, and the container clips the empty-state message inside it. The zero-row case needs a minimum height so the empty-state content is visible.
4. "Canvass" pluralization bug. ResourcesSection.svelte:29 and ErrorsSection.svelte:96 append "s" for pluralization:
{label}{count !== 1 ? "s" : ""}prettyResourceKind("rill.runtime.v1.Canvas") returns "Canvas", so this produces "Canvass". A lookup map for known kinds (or at minimum a special case for Canvas → Canvases) would fix this and prevent the same class of bug for future resource kinds.
5. Logs auto-scroll doesn't respect user scroll position. ProjectLogsPage.svelte scrolls to bottom on every new message regardless of where the user is reading. Standard pattern: track whether the user is at/near the bottom, and only auto-scroll if they are.
6. Errors section is interactive when there are no errors. ErrorsSection.svelte always applies role="button" and tabindex="0", even when totalErrors === 0. The click handler fires but does nothing. These interactive attributes should be conditional on totalErrors > 0.
7. Layout shift when navigating between pages. Navigating from Overview to Resources/Logs (and from Status to Settings) shifts the sidebar left. This likely involves the interplay between ContentContainer's overflow-y-auto (scrollbar appearing/disappearing) and the flex layout, but the exact cause needs investigation.
8. "Learn more" link in the clone popover is a 404. ProjectClone.svelte:45 links to https://docs.rilldata.com/developers/guides/clone-a-project, which returns a 404. Either fix the URL or remove the link until the page exists.
9. Route path /project-logs should be /logs. Other status sub-routes are /resources, /model-details, /analytics. The "project-" prefix is inconsistent and was already removed from the nav label and heading.
10. Resources table has extra vertical whitespace below rows. ProjectResourcesTable.svelte passes containerHeight={550} to VirtualizedTable. The body uses this fixed height when there are more than 10 rows, but when the rows don't fill it, there's empty space below the last row. Same root cause as #3 — the dynamicContainerHeight logic should use Math.min(rows.length * rowHeight, containerHeight) instead of the <= 10 threshold check.
11. NameCell truncates without a tooltip. Long resource names are truncated with no way to see the full name. RefreshCell already uses a Tooltip component for the same purpose — NameCell should too.
Should fix
12. Remove placeholder pages. The six "coming soon" route files (/query, /token-management, /console, /analytics, /dag-viewer, /model-details) are dead-end pages reachable by URL. The nav items with hasPermission: false are fine to keep, but the empty page files should be removed.
13. Overview sections silently swallow query errors. ResourcesSection, ErrorsSection, and DeploymentSection query data but never check isLoading or isError. When queries fail, ErrorsSection shows "No errors detected" — misleading since it couldn't actually check. At minimum, ErrorsSection should surface query failures.
Design feedback
On the "Describe" menu label. In CLI tools (kubectl, aws), "describe" means "show detailed info." In a web context, users are more likely to read "Describe" as an imperative — "describe this resource," i.e. add a description or annotation. "View spec" or "Inspect" would unambiguously communicate that clicking shows you information rather than asks you to provide it.
On the clone popover. The two-step flow (clone → env pull) is the right information to show, but the visual hierarchy doesn't communicate "two sequential steps" clearly. The second command is visually subordinate (smaller text, separated by a thin rule), which makes it easy to miss. Numbering the steps ("1. Clone the repo" / "2. Pull environment variables") or using a more explicit step indicator would make the two-step nature harder to overlook.
Developed in collaboration with Claude Code
royendo
left a comment
There was a problem hiding this comment.
Code Review
Decision: COMMENT (improvements needed, not blocking)
CI is green (12/12 checks passing). The architecture is solid and prior feedback from @ericpgreen2 has been substantially addressed. The remaining issues are improvements rather than blockers.
Should fix before merge:
-
Missing
{#each}key inErrorsSection.svelte(line 81) —{#each errorsByKind as { kind, label, count }}needs a(kind)key for correct reactivity, matching the pattern already used inResourcesSection.svelte. -
Loading/error state ordering in
ProjectResources.svelte— Currently checksdatafirst, thenisError. If data is truthy but stale while a refetch errors, the error state won't be shown. Should follow the defensive pattern:isLoading→isError→data. -
Redundant
Componentfilter inProjectResourcesTable.svelte(lines 205-207) — TheuseResourcesselector inselectors.tsalready filters outResourceKind.Component. The table component filters it again, which is redundant and should be removed.
Should fix soon (follow-up OK):
-
Add
pluralizeKindunit tests tooverview-utils.spec.ts— Exported function with special-case logic (pluralOverridesfor "Canvas" → "Canvases") has no dedicated tests. -
URL params not reactive in
ProjectResources.svelte(lines 146-148) —kindParam,statusParam, andqParamare read from$page.url.searchParamsonce on mount. They won't update on browser back/forward navigation. Should use$:reactive declarations. -
Use
$page.urlinstead ofwindow.location.hrefinsyncFiltersToUrl(line 175) for SvelteKit consistency. -
ContentContainertitle says "Project Status" in the status layout — per earlier reviewer feedback to drop "Project" from sub-headings, this should just be "Status". -
Add JSDoc to
extractDimensionFiltersinPublicURLsResourceTable.svelte— non-trivial recursive expression tree parsing logic deserves documentation.
Strengths:
- Good test coverage with
display-utils.spec.ts(241 lines) andoverview-utils.spec.ts(133 lines) - Clean refactoring of display utils from component references to pure functions with JSDoc
- Proper reuse of existing components (
VirtualizedTable,Search,SSEConnectionManager) - Good
VirtualizedTablefix for empty-state height - Go backend change correctly mirrors the existing OLAP connector pattern
- No security concerns identified
🤖 Generated with Claude Code
ericpgreen2
left a comment
There was a problem hiding this comment.
This is great — all the blocking items from the last round are resolved.
1. ProjectLogsPage.svelte:104 — the logs array is spread + sliced on every incoming message:
logs = [...logs, { ...log, _id: nextLogId++ }].slice(-MAX_LOGS);Fine for now, but if users report sluggishness on busy projects, a ring buffer or in-place mutation would reduce GC pressure.
2. When filters produce zero results, the resources table shows the generic "No data available." A filter-aware message like "No resources match the current filters" would be more helpful. VirtualizedTable already accepts an emptyText prop — ProjectResourcesTable just needs to pass one.

Updated 2/13: https://www.loom.com/share/9bec42943b3647049abf5cf2df513302
Add
rill project Deploymentand version infoAdd OLAP and AI Connector
Add Type Filter, Status Filter
Add Search Bar
Add Project Logs
closes: #6619
Checklist: