Skip to content

Cleanup UI on primary pages - #88

Merged
FyreByrd merged 25 commits into
developfrom
refactor/clean-ui
Aug 12, 2026
Merged

Cleanup UI on primary pages#88
FyreByrd merged 25 commits into
developfrom
refactor/clean-ui

Conversation

@FyreByrd

@FyreByrd FyreByrd commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Todo:

  • view/update pages
  • SSE?
  • Right now the jobs index page is using PUBLIC_SCRIPTORIA_URL to construct a link to the product in Scriptoria:
    • Would it be better to have an extra field on clients for this purpose instead?
    • Would a similar link be useful in the projects list?

Changes:

  • Fix sort order bug in list views
  • Add sidebar
Screenshot 2026-08-11 at 2 56 41 PM
  • Reformat index page
Screenshot 2026-08-11 at 2 57 11 PM
  • Clean up about page
Screenshot 2026-08-11 at 2 57 43 PM
  • Reformat list views
Screenshot 2026-08-11 at 4 48 33 PM Screenshot 2026-08-12 at 10 06 50 AM

Summary by CodeRabbit

  • New Features

    • Added responsive card-based views for projects, jobs, builds, and releases.
    • Added search and application-type filtering with updated result counts and pagination.
    • Added responsive navigation with drawer controls, active-route styling, and item counts.
    • Added reusable dropdowns, tooltips, secure value displays, and search bars.
    • Added dashboard summary cards for project, job, build, and release activity.
    • Added application icons, relative-time information, sorting utilities, and improved status indicators.
  • Style

    • Improved themed link colors, hover states, icons, and responsive layouts.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@FyreByrd, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 06284c55-057a-4b7a-ad36-4c37413ea857

📥 Commits

Reviewing files that changed from the base of the PR and between f558044 and 49338d7.

📒 Files selected for processing (4)
  • src/routes/(ui)/build-admin/+page.svelte
  • src/routes/(ui)/job-admin/+page.svelte
  • src/routes/(ui)/project-admin/+page.svelte
  • src/routes/(ui)/release-admin/+page.svelte
📝 Walkthrough

Walkthrough

The pull request adds shared Svelte controls, centralized application and icon utilities, responsive navigation, dashboard aggregates, filtered administration queries, and card-based administration views. It also updates relative-time display, secure values, tooltips, and theme-aware link colors.

Changes

Shared foundations

Layer / File(s) Summary
Shared contracts and UI primitives
src/app.css, src/lib/components/*, src/lib/icons/*, src/lib/utils/*, src/lib/valibot.ts, src/routes/(api)/project/+server.ts
Shared dropdown, application selector, search bar, secure display, tooltip, icon, sorting, time, theme, and application-type contracts were added or updated.
Shared application typing
src/lib/server/models/job.ts, src/lib/server/job-executors/system.ts
Job and application-version processing now use shared ApplicationType values.

Navigation and dashboard

Layer / File(s) Summary
Navigation and dashboard data
src/routes/(ui)/+layout.server.ts, src/routes/(ui)/+layout.svelte, src/routes/(ui)/+page.server.ts, src/routes/(ui)/+page.svelte
The layout now provides entity counts and responsive navigation. The dashboard now loads grouped counts and renders aggregate cards.

Administration query filtering

Layer / File(s) Summary
Administration query filtering
`src/routes/(ui)/(client-admin
job-admin

Administration card views

Layer / File(s) Summary
Administration card views
`src/routes/(ui)/(client-admin
job-admin

About version display

Layer / File(s) Summary
About version display
src/routes/(ui)/about/+page.server.ts, src/routes/(ui)/about/+page.svelte
Version rows now show application icons, relative update times, tooltip dates, and shared sorting. Credit links use HTTPS.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant AdminPage
  participant ServerAction
  participant Prisma

  Browser->>AdminPage: submit search or application filter
  AdminPage->>ServerAction: enhanced POST request
  ServerAction->>Prisma: query filtered records
  ServerAction->>Prisma: count filtered records
  Prisma-->>ServerAction: records and count
  ServerAction-->>AdminPage: update cards and pagination
  AdminPage-->>Browser: render responsive administration view
Loading

Suggested reviewers: chrisvire

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary UI cleanup, including navigation, dashboard, about page, and list-view changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/clean-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@FyreByrd
FyreByrd marked this pull request as ready for review August 12, 2026 15:07
@FyreByrd
FyreByrd requested a review from chrisvire August 12, 2026 15:10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (6)
src/routes/(ui)/+layout.server.ts (1)

5-13: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Run independent Prisma queries concurrently.

Each load waits for unrelated database queries before it starts the next query. When these loads run, total latency becomes the sum of all query durations. Start the queries with Promise.all.

  • src/routes/(ui)/+layout.server.ts#L5-L13: run the five count() calls concurrently, then construct count from the resolved values.
  • src/routes/(ui)/+page.server.ts#L5-L27: run the four groupBy() calls concurrently, then construct aggregate from the resolved values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`(ui)/+layout.server.ts around lines 5 - 13, Run the independent
Prisma queries concurrently: in src/routes/(ui)/+layout.server.ts lines 5-13,
update the load result construction to await all five client, project, job,
build, and release count() calls via Promise.all, then map the resolved values
into count; in src/routes/(ui)/+page.server.ts lines 5-27, likewise await all
four groupBy() calls via Promise.all and construct aggregate from their resolved
values.
src/lib/server/models/job.ts (1)

5-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep Job.AppType aligned with the canonical application list.

src/lib/valibot.ts:124-129 is the shared applicationTypes source, but this object repeats the four values. satisfies Record<string, ApplicationType> checks value membership only. It does not ensure that every canonical application has a named Job.AppType member.

Derive both definitions from one mapping or add an exhaustive key and value check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/server/models/job.ts` around lines 5 - 10, Update AppType in the job
model to stay synchronized with the canonical applicationTypes mapping from
valibot, ensuring every canonical application has a named member and no
duplicated values can drift. Prefer deriving both definitions from one shared
mapping, or add an exhaustive key-and-value consistency check while preserving
the existing AppType member names.
src/routes/(ui)/client-admin/+page.svelte (1)

29-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The declared count in the result cast is never used.

onUpdate types data.query.count but assigns only clients, and the totals on lines 52-58 and 97 still read data.count. This page has no search control, so the total cannot change and the current behaviour is correct. For consistency with the other four list pages, either track a reactive count or drop count from the cast.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`(ui)/client-admin/+page.svelte around lines 29 - 37, Update the
onUpdate handler’s FormResult cast to remove the unused query.count field, since
this page only assigns data.query.data to clients and continues reading the
stable page-level data.count for totals.
src/routes/(ui)/client-admin/+page.server.ts (1)

22-26: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Run the list query and the count in parallel.

findMany resolves before count starts, so the load waits for two sequential round trips.

♻️ Proposed change
 export const load = (async () => {
-  const clients = await prisma.client.findMany({ select, take: 20, orderBy: { id: 'desc' } });
+  const [clients, count] = await Promise.all([
+    prisma.client.findMany({ select, take: 20, orderBy: { id: 'desc' } }),
+    prisma.client.count()
+  ]);
   return {
     clients,
-    count: await prisma.client.count(),
+    count,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`(ui)/client-admin/+page.server.ts around lines 22 - 26, Update
the load function to start prisma.client.findMany and prisma.client.count
concurrently, await both results together, and return the existing clients and
count fields without changing their query options or response shape.
src/routes/(ui)/job-admin/+page.svelte (1)

92-92: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Both card views cast a database string to ApplicationType without a check. getAppIcon returns '' for an unregistered type, per src/lib/icons/index.ts lines 8-10. An empty src makes the browser re-request the current document and renders a broken image.

  • src/routes/(ui)/job-admin/+page.svelte#L92-L92: resolve the icon into a {@const} and render the <img> only when the value is non-empty.
  • src/routes/(ui)/project-admin/+page.svelte#L91-L95: apply the same guard around the project application icon.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`(ui)/job-admin/+page.svelte at line 92, In
src/routes/(ui)/job-admin/+page.svelte lines 92-92, resolve
getAppIcon(job.app_id as ApplicationType) into a {`@const`} and render the image
only when the resolved icon is non-empty. Apply the same guarded icon resolution
and conditional rendering in src/routes/(ui)/project-admin/+page.svelte lines
91-95 for the project application icon.
src/routes/(ui)/build-admin/+page.svelte (1)

89-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The status badge markup is duplicated verbatim. Both pages inline the same result || status derivation, the same four-way class chain, and the same Icons.Unknown check. Any later change to the status colours must be applied twice.

  • src/routes/(ui)/build-admin/+page.svelte#L89-L108: move this block into a shared StatusBadge.svelte component that accepts status and renders the badge and icon.
  • src/routes/(ui)/release-admin/+page.svelte#L89-L108: replace the inlined block with the shared component.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`(ui)/build-admin/+page.svelte around lines 89 - 108, Extract the
duplicated status badge markup into a shared StatusBadge.svelte component
accepting status and preserving the existing status-to-class mapping and
Icons.Unknown handling. Update src/routes/(ui)/build-admin/+page.svelte lines
89-108 to use the component, and replace the equivalent inline block in
src/routes/(ui)/release-admin/+page.svelte lines 89-108 with the same component.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/SecureDisplay.svelte`:
- Around line 25-27: Update the visibility toggle button in SecureDisplay to
include a state-specific aria-label and an aria-pressed attribute derived from
visible, while preserving the existing toggle handler and icon behavior.

In `@src/lib/utils/sorting.ts`:
- Around line 12-14: Update byString to explicitly handle null or undefined
inputs before localeCompare, using a consistent deterministic ordering for
missing values regardless of argument position. Preserve locale-aware comparison
for two present strings and ensure equal missing values compare as equal.

In `@src/routes/`(ui)/+layout.svelte:
- Around line 101-106: Replace the non-focusable <label> mobile navigation
control with a keyboard-operable <button> in the layout’s drawer toggle,
preserving its styling and hamburger icon. Bind the button’s aria-expanded
attribute to the mobile drawer state and retain the existing drawer target
behavior.

In `@src/routes/`(ui)/+page.svelte:
- Around line 46-50: Update the aggregate table’s <thead> row to give both
columns meaningful header text, identifying the type and count columns. Use
visible labels or screen-reader-only text while preserving the existing table
structure.
- Line 33: Update the cards container near the `id="cards"` element to use
`md:flex-row` instead of `lg:flex-row`, and replace the empty aggregate table
headers with `App ID` or `Result` and `Count`, adding `scope="col"` to each
header.

In `@src/routes/`(ui)/about/+page.svelte:
- Around line 66-67: Validate appVersion.appName against applicationTypes before
passing it to getAppIcon in the IconContainer; remove the unsafe type assertion
and use the established fallback icon behavior for unsupported values.
- Around line 19-20: Update the data-fetching query used by the page to order
appVersion records by updated descending before the results are consumed with
.at(0) at both call sites. Ensure the first record is consistently the newest
while preserving the existing getRelativeTime behavior.

In `@src/routes/`(ui)/build-admin/+page.svelte:
- Around line 22-39: Reset pagination before filtered list submissions: in
src/routes/(ui)/build-admin/+page.svelte lines 22-39, add a search() wrapper
that sets $form.page.page to 0 before submit(), and pass it to SearchBar and the
Enter handler; apply the same wrapper in src/routes/(ui)/job-admin/+page.svelte
lines 28-32 and src/routes/(ui)/project-admin/+page.svelte lines 27-31, also
resetting the page when appType changes; in
src/routes/(ui)/release-admin/+page.svelte lines 25-29, use the wrapper for the
search control.

In `@src/routes/`(ui)/client-admin/+page.server.ts:
- Around line 8-20: Remove access_token from the Prisma clientSelect projection
used by the list page so tokens are not included in load payloads, SSR HTML, or
action responses; keep token retrieval limited to the single-record view or
replace it with a server-generated masked prefix.

In `@src/routes/`(ui)/job-admin/+page.svelte:
- Around line 93-99: Update the job request link rendering in the page markup to
check whether env.PUBLIC_SCRIPTORIA_URL is set; render the existing anchor with
its URL and external-link icon only when present, otherwise render
job.request_id as plain text.

---

Nitpick comments:
In `@src/lib/server/models/job.ts`:
- Around line 5-10: Update AppType in the job model to stay synchronized with
the canonical applicationTypes mapping from valibot, ensuring every canonical
application has a named member and no duplicated values can drift. Prefer
deriving both definitions from one shared mapping, or add an exhaustive
key-and-value consistency check while preserving the existing AppType member
names.

In `@src/routes/`(ui)/+layout.server.ts:
- Around line 5-13: Run the independent Prisma queries concurrently: in
src/routes/(ui)/+layout.server.ts lines 5-13, update the load result
construction to await all five client, project, job, build, and release count()
calls via Promise.all, then map the resolved values into count; in
src/routes/(ui)/+page.server.ts lines 5-27, likewise await all four groupBy()
calls via Promise.all and construct aggregate from their resolved values.

In `@src/routes/`(ui)/build-admin/+page.svelte:
- Around line 89-108: Extract the duplicated status badge markup into a shared
StatusBadge.svelte component accepting status and preserving the existing
status-to-class mapping and Icons.Unknown handling. Update
src/routes/(ui)/build-admin/+page.svelte lines 89-108 to use the component, and
replace the equivalent inline block in
src/routes/(ui)/release-admin/+page.svelte lines 89-108 with the same component.

In `@src/routes/`(ui)/client-admin/+page.server.ts:
- Around line 22-26: Update the load function to start prisma.client.findMany
and prisma.client.count concurrently, await both results together, and return
the existing clients and count fields without changing their query options or
response shape.

In `@src/routes/`(ui)/client-admin/+page.svelte:
- Around line 29-37: Update the onUpdate handler’s FormResult cast to remove the
unused query.count field, since this page only assigns data.query.data to
clients and continues reading the stable page-level data.count for totals.

In `@src/routes/`(ui)/job-admin/+page.svelte:
- Line 92: In src/routes/(ui)/job-admin/+page.svelte lines 92-92, resolve
getAppIcon(job.app_id as ApplicationType) into a {`@const`} and render the image
only when the resolved icon is non-empty. Apply the same guarded icon resolution
and conditional rendering in src/routes/(ui)/project-admin/+page.svelte lines
91-95 for the project application icon.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3e443b5b-f223-43b2-823f-234c12d25d8c

📥 Commits

Reviewing files that changed from the base of the PR and between 737bc06 and a8a4477.

⛔ Files ignored due to path filters (4)
  • src/lib/icons/app-builders/dictionaryappbuilder.svg is excluded by !**/*.svg
  • src/lib/icons/app-builders/keyboardappbuilder.svg is excluded by !**/*.svg
  • src/lib/icons/app-builders/readingappbuilder.svg is excluded by !**/*.svg
  • src/lib/icons/app-builders/scriptureappbuilder.svg is excluded by !**/*.svg
📒 Files selected for processing (34)
  • src/app.css
  • src/lib/components/AppTypeSelector.svelte
  • src/lib/components/Dropdown.svelte
  • src/lib/components/IconContainer.svelte
  • src/lib/components/SearchBar.svelte
  • src/lib/components/SecureDisplay.svelte
  • src/lib/components/SortTable.svelte
  • src/lib/components/Tooltip.svelte
  • src/lib/icons/ArrowDownIcon.svelte
  • src/lib/icons/ArrowUpIcon.svelte
  • src/lib/icons/IconContainer.svelte
  • src/lib/icons/index.ts
  • src/lib/server/job-executors/system.ts
  • src/lib/server/models/job.ts
  • src/lib/server/utils.ts
  • src/lib/utils/sorting.ts
  • src/lib/utils/time.ts
  • src/lib/valibot.ts
  • src/routes/(api)/project/+server.ts
  • src/routes/(ui)/+layout.server.ts
  • src/routes/(ui)/+layout.svelte
  • src/routes/(ui)/+page.server.ts
  • src/routes/(ui)/+page.svelte
  • src/routes/(ui)/about/+page.svelte
  • src/routes/(ui)/build-admin/+page.server.ts
  • src/routes/(ui)/build-admin/+page.svelte
  • src/routes/(ui)/client-admin/+page.server.ts
  • src/routes/(ui)/client-admin/+page.svelte
  • src/routes/(ui)/job-admin/+page.server.ts
  • src/routes/(ui)/job-admin/+page.svelte
  • src/routes/(ui)/project-admin/+page.server.ts
  • src/routes/(ui)/project-admin/+page.svelte
  • src/routes/(ui)/release-admin/+page.server.ts
  • src/routes/(ui)/release-admin/+page.svelte
💤 Files with no reviewable changes (4)
  • src/lib/server/utils.ts
  • src/lib/icons/ArrowDownIcon.svelte
  • src/lib/components/IconContainer.svelte
  • src/lib/icons/ArrowUpIcon.svelte

Comment thread src/lib/components/SecureDisplay.svelte
Comment thread src/lib/utils/sorting.ts
Comment thread src/routes/(ui)/+layout.svelte
Comment thread src/routes/(ui)/+page.svelte Outdated
Comment thread src/routes/(ui)/+page.svelte Outdated
Comment thread src/routes/(ui)/about/+page.svelte
Comment thread src/routes/(ui)/about/+page.svelte
Comment thread src/routes/(ui)/build-admin/+page.svelte
Comment thread src/routes/(ui)/client-admin/+page.server.ts
Comment thread src/routes/(ui)/job-admin/+page.svelte

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/routes/`(ui)/about/+page.server.ts:
- Line 6: Update the appVersion.findMany query in the page data loader to
explicitly order nullable updated timestamps with NULL values last while
retaining descending order for dated records, ensuring the first result remains
the latest dated version.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2af633db-f5e9-4c51-86d3-278a063dd083

📥 Commits

Reviewing files that changed from the base of the PR and between a8a4477 and f558044.

📒 Files selected for processing (6)
  • src/routes/(ui)/+page.svelte
  • src/routes/(ui)/about/+page.server.ts
  • src/routes/(ui)/build-admin/+page.svelte
  • src/routes/(ui)/job-admin/+page.svelte
  • src/routes/(ui)/project-admin/+page.svelte
  • src/routes/(ui)/release-admin/+page.svelte
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/routes/(ui)/build-admin/+page.svelte
  • src/routes/(ui)/project-admin/+page.svelte
  • src/routes/(ui)/release-admin/+page.svelte
  • src/routes/(ui)/job-admin/+page.svelte

Comment thread src/routes/(ui)/about/+page.server.ts
@FyreByrd
FyreByrd merged commit db0d6b3 into develop Aug 12, 2026
4 checks passed
@FyreByrd
FyreByrd deleted the refactor/clean-ui branch August 12, 2026 20:00
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