Skip to content

fix(admin): fix Org Security loading state UI#1738

Open
Shreyag02 wants to merge 1 commit into
mainfrom
fix/bug-org-security-loading-state-ui
Open

fix(admin): fix Org Security loading state UI#1738
Shreyag02 wants to merge 1 commit into
mainfrom
fix/bug-org-security-loading-state-ui

Conversation

@Shreyag02

Copy link
Copy Markdown
Contributor

Summary

The Org → Security page had a buggy loading state — the "Allowed email domains" loader showed up as an unstyled empty box, and the whole section would vanish or behave oddly depending on the data. This PR fixes the loader and makes the loading, empty, and error states consistent and clear.

Changes

  • Switched the domains loader from react-loading-skeleton to Apsara's Skeleton (self-styled, no extra CSS needed).
  • Loading, list, empty, and error states now all render inside the same bordered box, so nothing pops in or collapses.
  • Added a friendly empty state ("No allowed email domains added yet") instead of rendering nothing.
  • Added a distinct error state with a Retry button, so a failed fetch is no longer mistaken for an org with no domains.

Technical Details

  • The root cause: the default react-loading-skeleton Skeleton relies on react-loading-skeleton/dist/skeleton.css, which is never imported anywhere in web/sdk/admin or web/apps/admin. The app's <SkeletonTheme> only provides color variables, not the base skeleton styles — so the skeleton rendered as an invisible/empty box. Apsara's Skeleton ships its own styles, so it works out of the box (same approach as session-skeleton.tsx and apis/details-dialog.tsx).
  • Previously the component had three branches (skeleton / rows / null). The null empty case made the bordered box disappear, causing the "abrupt close" jump. All four states (loading/list/empty/error) now share the same .domains-list container for a stable layout.
  • The error state gets error + onRetry from the listOrganizationDomains query in index.tsx; Retry calls the query's refetch(). The existing error toast is kept.

Test Plan

  • Manual testing completed
    • Loaded the Org → Security page and confirmed the domains loader shows a proper skeleton, then swaps into the list without any layout jump.
    • Verified an org with no domains shows the empty-state text instead of a blank/collapsing box.
    • Simulated an API failure (blocked the ListOrganizationDomains request in DevTools) and confirmed the error state + Retry button appear; Retry re-fetches and recovers.
  • Build and type checking passes (tsc --noEmit clean for the changed files)

SQL Safety (if your PR touches *_repository.go or goqu.*)

N/A

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added retry support for loading organization email domains after a fetch error.
    • Displayed a clear empty state when no allowed email domains have been added yet.
  • Bug Fixes

    • Improved error handling in the domains list so failures are shown inline instead of leaving the section blank.
  • Style

    • Simplified the loading placeholder layout for a cleaner, more consistent appearance.

Walkthrough

DomainsList now accepts error and onRetry props, rendering an inline error message with a Retry button, a simplified two-skeleton loading state, and an explicit empty-state message instead of returning null. OrganizationSecurity wires refetch from useQuery to pass error and retry handling to DomainsList.

Changes

Domains list retry UI

Layer / File(s) Summary
DomainsList error, empty state, and skeleton rendering
web/sdk/admin/views/organizations/details/security/domains-list.tsx
Adds error and onRetry props; renders retry UI on error, simplified skeleton loading, and an explicit "No allowed email domains added yet" empty state instead of null. Switches Skeleton import to @raystack/apsara and adjusts destructuring formatting.
OrganizationSecurity refetch wiring
web/sdk/admin/views/organizations/details/security/index.tsx
Destructures refetch from useQuery and passes error and an onRetry callback calling refetch() into DomainsList.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: rohilsurana, rsbh

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
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.

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.

@Shreyag02 Shreyag02 requested a review from rohanchkrabrty July 7, 2026 10:50

@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: 1

🧹 Nitpick comments (1)
web/sdk/admin/views/organizations/details/security/domains-list.tsx (1)

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

Retry button has no in-flight/disabled state.

Clicking Retry triggers onRetry() (parent's refetch()), but there's no indication that a refetch is in progress and nothing prevents multiple rapid clicks from firing duplicate requests while the previous one is still pending.

Consider threading an isFetching/isRetrying flag down to disable the button (and optionally show a loading label) while a refetch is outstanding.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1335a2e4-b2b2-4faf-8b48-5ba5442cb8d4

📥 Commits

Reviewing files that changed from the base of the PR and between 961da8a and 6cbca8b.

📒 Files selected for processing (2)
  • web/sdk/admin/views/organizations/details/security/domains-list.tsx
  • web/sdk/admin/views/organizations/details/security/index.tsx

Comment on lines +146 to +168
if (!isLoading && error) {
return (
<Flex
justify="between"
align="center"
className={styles["domains-list"]}
style={{ padding: "var(--rs-space-5) var(--rs-space-7)" }}
>
<Text size="small" variant="secondary">
Couldn&apos;t load email domains
</Text>
<Button
variant="outline"
color="neutral"
size="small"
onClick={() => onRetry()}
data-test-id="retry-domains-button"
>
Retry
</Button>
</Flex>
);
}

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file with line numbers
sed -n '1,240p' web/sdk/admin/views/organizations/details/security/domains-list.tsx | cat -n

# Find the query hook and related state usage in this file
rg -n "useQuery|isLoading|error|domains|onRetry|refetch|fetch" web/sdk/admin/views/organizations/details/security/domains-list.tsx

# Locate the query source / hook definition if it exists nearby
fd -a "domains-list.tsx|*.ts|*.tsx" web/sdk/admin/views/organizations/details/security | head -n 50

Repository: raystack/frontier

Length of output: 8294


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find where DomainsList is used
rg -n "DomainsList" web/sdk/admin -g '*.tsx' -g '*.ts'

# Inspect the parent component that fetches domains
fd -a "domains*.tsx|*security*.tsx|*domain*.tsx" web/sdk/admin/views/organizations/details/security web/sdk/admin/views/organizations/details | head -n 50

# Search for the listOrganizationDomains query usage and its loading/error/data mapping
rg -n "listOrganizationDomains|useQuery\\(|error\\s*:|isLoading\\s*:|domains\\s*=" web/sdk/admin -g '*.tsx' -g '*.ts'

Repository: raystack/frontier

Length of output: 984


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the parent component that supplies isLoading/domains/error/onRetry
sed -n '1,220p' web/sdk/admin/views/organizations/details/security/index.tsx | cat -n

# Search for the exact query state mapping in this directory
rg -n "useQuery|isLoading|isFetching|error|data|refetch|DomainsList" web/sdk/admin/views/organizations/details/security -g '*.tsx' -g '*.ts'

Repository: raystack/frontier

Length of output: 8666


Gate the error state on missing data. A refetch failure after domains have already loaded will replace the visible list with the retry screen. Show this branch only when there’s no existing data to keep on screen, e.g. !domains.length.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 28860476387

Coverage remained the same at 44.879%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 37621
Covered Lines: 16884
Line Coverage: 44.88%
Coverage Strength: 12.49 hits per line

💛 - Coveralls

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.

2 participants