Skip to content

fix: accept bare domains in website add dialog#793

Merged
Israeltheminer merged 4 commits into
mainfrom
fix/website-domain-validation
Mar 14, 2026
Merged

fix: accept bare domains in website add dialog#793
Israeltheminer merged 4 commits into
mainfrom
fix/website-domain-validation

Conversation

@Israeltheminer

@Israeltheminer Israeltheminer commented Mar 14, 2026

Copy link
Copy Markdown
Collaborator

Fixes #788

Summary

  • Change website domain input type from url to text to allow bare domain entry (e.g. example.com)
  • Replace .url() Zod validation with a custom refine that accepts both bare domains and full URLs
  • Add validDomain translation string with a helpful placeholder example
  • Add deleting website status and scan interval label translations

Test plan

  • Open the "Add Website" dialog and enter example.com (no protocol) → succeeds
  • Enter https://example.com → succeeds
  • Enter an invalid value like notadomain → shows "Enter a valid domain (e.g. example.com)" error
  • Enter an empty string → shows "Domain is required" error

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added interval filtering options for websites (60m to 30d)
    • Click website rows to open detailed view with pagination and search
    • Search functionality within website details
    • Permission-based action visibility
  • Bug Fixes

    • Domain validation now accepts URLs with or without https scheme
    • Improved error messaging for invalid domains
  • UI/UX Improvements

    • Color-coded status badges for website states
    • Human-readable scan interval labels
    • Crawled page counts displayed prominently

The domain input required a full URL (e.g. https://example.com) but the
field label says "Domain name", causing confusion (#788).

- Change input type from `url` to `text` to allow bare domain entry
- Replace `.url()` validation with a custom `refine` that accepts both
  bare domains (`example.com`) and full URLs (`https://example.com`)
- Add `validDomain` translation string with a helpful example
- Add `deleting` website status string and scan interval translations

@greptile-apps greptile-apps 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR addresses domain validation inconsistency (issue #788) by modifying the website add form to accept domain names without requiring explicit scheme notation; the form now normalizes missing schemes by prepending https://. Additionally, the PR enhances the websites table with interval-based filtering, implements permission-based access controls via useAbility across multiple components, restructures table columns to display status badges and crawled page counts, and extends the view dialog with pagination, on-demand chunk loading, and search functionality. Related localization strings and route schema updates support the new filtering and validation behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

The diff introduces heterogeneous changes spanning validation logic, permission gating, state management with effects, UI column restructuring, and new dialog functionality. While individual components range from trivial (permission checks) to moderate (filtering, column definitions), the website-view-dialog.tsx file alone contains substantial logic density with multiple new components, state hooks, and search workflows. The variety of change types and the substantial modifications to the view dialog drive complexity despite some repetitive patterns (e.g., permission checks).

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes substantial additional changes beyond fixing domain validation: permission checks in row actions and action menu, pagination and search in view dialog, interval filtering, and status display updates. Consider separating permission-gating, view dialog enhancements, interval filtering, and UI/table updates into distinct PRs to maintain focused scope on the domain validation fix.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: updating domain validation to accept bare domains without protocols in the website add dialog.
Linked Issues check ✅ Passed The PR fully resolves issue #788 by accepting bare domains (example.com) and full URLs (https://example.com) via custom validation and input type change.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/website-domain-validation
📝 Coding Plan
  • Generate coding plan for human review comments

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
services/platform/app/features/websites/components/websites-table.tsx (1)

55-59: ⚠️ Potential issue | 🔴 Critical

Add interval parameter to query for server-side filtering.

The interval prop is received and displayed in the filter UI, but it's not passed to useListWebsitesPaginated, so the data isn't actually filtered by interval. Unlike status which is properly passed to the query and filtered server-side, interval has no filtering implementation. Add interval?: string to ListWebsitesPaginatedArgs (both in the Convex handler and hooks type), pass it to the query, and update the server-side filtering logic in list_websites_paginated.ts to filter by interval like it does for status.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/app/features/websites/components/websites-table.tsx` around
lines 55 - 59, The paginated query is missing the interval filter: add an
optional interval?: string field to the ListWebsitesPaginatedArgs type (both in
the Convex handler signature and the generated hooks/types), update all callers
including the use in the component where paginatedResult is created via
useListWebsitesPaginated to pass the interval prop, and modify
list_websites_paginated.ts server-side logic to apply the same interval-based
filtering as status (filter by interval when args.interval is present before
pagination). Ensure function/type names: useListWebsitesPaginated,
ListWebsitesPaginatedArgs, and the handler in list_websites_paginated.ts are
updated consistently so the client hook and server handler accept and use
interval.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@services/platform/app/features/websites/components/website-view-dialog.tsx`:
- Around line 437-442: The key for the mapped SearchResultItem currently uses
`${result.url}-${result.chunk_index}-${idx}`, which redundantly includes the
index; if result.url + result.chunk_index uniquely identify each result, remove
`idx` to avoid reorder-related re-render issues. Update the map generating
SearchResultItem (the searchResults.map block) to use a stable key based only on
result.url and result.chunk_index (or another unique id field on result if
available), ensuring the key remains a string and still unique across items.
- Around line 469-471: The Button in WebsiteViewDialog currently shows a
hardcoded '...' when isPending; replace that with an accessible, localized
loading indicator by using the imported Spinner component or a translated string
(e.g., t('loading')) instead of '...'. Update the conditional rendering around
isPending in the Button so it renders <Spinner /> (with an appropriate
aria-label) or t('pagesDialog.loading') to ensure localization and accessibility
while keeping the Button text for the non-pending branch
(t('pagesDialog.loadMore')).
- Around line 227-230: When handling failures in the fetchPages onError
callback, add user-visible error feedback instead of only flipping
setIsFirstLoad; update the onError for fetchPages to call the same
toast/error-display used by searchContent (include the error message/details)
and then setIsFirstLoad(false) so failures show an error toast rather than the
misleading empty "no pages" state; locate the fetchPages onError handler and
mirror the searchContent error behavior.
- Around line 79-84: The fetchChunks useConvexAction currently only sets chunks
on success and has no error path; add error handling by providing an onError
callback to the useConvexAction for api.websites.actions.fetchChunks that sets
an error state (e.g., setFetchError) and clears or preserves chunks
appropriately, and ensure the UI uses that state to show a user-facing error
message or toast when fetch fails instead of silently disappearing (adjust the
component around setChunks, fetchChunks and isPending to render the error). Also
consider logging the error for debugging and disabling any success-only
assumptions in the component that rely on setChunks.

In `@services/platform/app/features/websites/hooks/use-websites-table-config.tsx`:
- Around line 120-136: The intervalLabels map is being recreated on every render
inside the cell renderer; move it out of the per-cell render by extracting it to
a stable lookup (e.g., a top-level constant or a useMemo inside
useWebsitesTableConfig) and use that from the cell; update the cell
implementation (the cell function in use-websites-table-config.tsx) to look up
the label via the stable map or compute via tEntity('scanIntervals.' +
row.original.scanInterval) and return intervalLabels[row.original.scanInterval]
|| row.original.scanInterval so row.original.scanInterval and tEntity are
referenced but no per-render object allocation occurs.
- Around line 42-65: The statusLabels map is being recreated on every render
inside the column's cell renderer (the cell function for accessorKey 'status'),
hurting performance; extract the labels out of the cell (either define a
top-level const in this module or compute them once with useMemo where
use-websites-table-config builds the columns) and have the cell reference that
shared statusLabels map; keep using the existing statusVariant lookup and return
logic unchanged so only the label lookup is moved from inside the cell to a
single, memoized/shared definition.

---

Outside diff comments:
In `@services/platform/app/features/websites/components/websites-table.tsx`:
- Around line 55-59: The paginated query is missing the interval filter: add an
optional interval?: string field to the ListWebsitesPaginatedArgs type (both in
the Convex handler signature and the generated hooks/types), update all callers
including the use in the component where paginatedResult is created via
useListWebsitesPaginated to pass the interval prop, and modify
list_websites_paginated.ts server-side logic to apply the same interval-based
filtering as status (filter by interval when args.interval is present before
pagination). Ensure function/type names: useListWebsitesPaginated,
ListWebsitesPaginatedArgs, and the handler in list_websites_paginated.ts are
updated consistently so the client hook and server handler accept and use
interval.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1ee5cfd6-4ee7-44e6-a790-7aa5c06d3f91

📥 Commits

Reviewing files that changed from the base of the PR and between 5c0c819 and 06da5cf.

📒 Files selected for processing (8)
  • services/platform/app/features/websites/components/website-add-dialog.tsx
  • services/platform/app/features/websites/components/website-row-actions.tsx
  • services/platform/app/features/websites/components/website-view-dialog.tsx
  • services/platform/app/features/websites/components/websites-action-menu.tsx
  • services/platform/app/features/websites/components/websites-table.tsx
  • services/platform/app/features/websites/hooks/use-websites-table-config.tsx
  • services/platform/app/routes/dashboard/$id/_knowledge/websites.tsx
  • services/platform/messages/en.json

Comment on lines +227 to +230
onError: () => {
setIsFirstLoad(false);
},
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing error feedback for page fetch failures.

When fetchPages fails, the error handler only updates isFirstLoad state. Unlike searchContent which shows a toast on error (line 242), page fetch failures silently result in the "no pages" empty state, misleading users into thinking no pages exist rather than indicating a fetch error.

🛡️ Proposed fix
     onError: () => {
       setIsFirstLoad(false);
+      toast({ title: t('toast.fetchPagesError'), variant: 'destructive' });
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onError: () => {
setIsFirstLoad(false);
},
},
onError: () => {
setIsFirstLoad(false);
toast({ title: t('toast.fetchPagesError'), variant: 'destructive' });
},
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/platform/app/features/websites/components/website-view-dialog.tsx`
around lines 227 - 230, When handling failures in the fetchPages onError
callback, add user-visible error feedback instead of only flipping
setIsFirstLoad; update the onError for fetchPages to call the same
toast/error-display used by searchContent (include the error message/details)
and then setIsFirstLoad(false) so failures show an error toast rather than the
misleading empty "no pages" state; locate the fetchPages onError handler and
mirror the searchContent error behavior.

@Israeltheminer Israeltheminer merged commit 85ed118 into main Mar 14, 2026
17 checks passed
@Israeltheminer Israeltheminer deleted the fix/website-domain-validation branch March 14, 2026 18:17
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.

Bug: Website add form label says "Domain name" but validation requires full URL

1 participant