refactor: extract RecentDomainsSection into reusable component (#41020)

### Description

Refactored the recent domains section from being an inline constant in
`SignUp.tsx` into a dedicated, reusable React component. This improves
code organization, maintainability, and testability.

### Changes Made

- **Created new component**: `RecentDomainsSection.tsx`
  - Encapsulates all logic for rendering recent organization domains
- Handles conditional rendering internally (returns null when no
domains)
  - Includes proper TypeScript types and imports

- **Updated SignUp component**:
  - Removed inline `recentDomainsSection` constant definition
  - Added import for new `RecentDomainsSection` component
  - Replaced usage with JSX component

- **Improved avatar logic**:
- Changed from alphabetical cycling (`String.fromCharCode(65 + (index %
26))`) to using the actual organization name's first letter
(`orgName.charAt(0).toUpperCase()`)
  - This provides more meaningful and recognizable avatars for users

## Automation

/ok-to-test tags="@tag.Sanity, @tag.Authentication"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/15838492574>
> Commit: f4c799f7fd76851b404ddddd441728d9bd6445ca
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15838492574&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Sanity, @tag.Authentication`
> Spec:
> <hr>Tue, 24 Jun 2025 01:35:51 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a dedicated section to display recently accessed domains
during user sign-up, allowing quick access to previously used domains.

- **Refactor**
- Modularized the recent domains display by moving its logic and UI into
a separate component for improved maintainability and clarity.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Jacques Ikot 2025-06-24 18:04:57 +01:00 committed by GitHub
parent 959f5108c2
commit 2e6ede2419
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 61 deletions

View File

@ -0,0 +1,74 @@
import { Button, Text } from "@appsmith/ads";
import {
createMessage,
YOU_VE_ALREADY_SIGNED_INTO,
} from "ee/constants/messages";
import React from "react";
import { getRecentDomains, isValidAppsmithDomain } from "utils/multiOrgDomains";
const RecentDomainsSection: React.FC = () => {
const recentDomains = getRecentDomains();
if (recentDomains.length === 0) {
return null;
}
return (
<div className="mt-8">
<div className="mb-2">
<Text kind="body-m">{createMessage(YOU_VE_ALREADY_SIGNED_INTO)}</Text>
</div>
<div className="max-h-48 overflow-y-auto border border-gray-200 rounded-md py-4 px-3">
{recentDomains.map((domain, index) => {
const orgName = domain
.split(".")[0]
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
const avatarLetter = orgName.charAt(0).toUpperCase();
const isLastItem = index === recentDomains.length - 1;
return (
<div
className={`flex items-center justify-between p-1 ${
isLastItem ? "mb-0" : "mb-3"
}`}
key={domain}
>
<div className="flex items-center space-x-3">
<div className="w-8 h-8 bg-[color:var(--ads-color-background-secondary)] rounded-full flex items-center justify-center text-gray-600 font-light text-sm">
{avatarLetter}
</div>
<div className="flex flex-col">
<span className="text-md font-semibold text-gray-700 max-w-[180px] line-clamp-1">
{orgName}
</span>
<span className="text-xs font-light text-gray-500 max-w-[180px] line-clamp-1">
{domain}
</span>
</div>
</div>
<Button
className="px-4 py-2 text-sm"
kind="secondary"
onClick={() => {
if (isValidAppsmithDomain(domain)) {
window.location.href = `https://${domain}/user/login`;
}
}}
size="md"
>
Open
</Button>
</div>
);
})}
</div>
</div>
);
};
export default RecentDomainsSection;

View File

@ -28,7 +28,6 @@ import {
VISIT_OUR_DOCS,
SIGN_IN_TO_AN_EXISTING_ORGANISATION,
USING_APPSMITH,
YOU_VE_ALREADY_SIGNED_INTO,
} from "ee/constants/messages";
import FormTextField from "components/utils/ReduxFormTextField";
import ThirdPartyAuth from "pages/UserAuth/ThirdPartyAuth";
@ -66,7 +65,7 @@ import { isLoginHostname } from "utils/cloudBillingUtils";
import { appsmithTelemetry } from "instrumentation";
import { getIsAiAgentInstanceEnabled } from "ee/selectors/aiAgentSelectors";
import { getSafeErrorMessage } from "ee/constants/approvedErrorMessages";
import { getRecentDomains, isValidAppsmithDomain } from "utils/multiOrgDomains";
import RecentDomainsSection from "./RecentDomainsSection";
declare global {
interface Window {
@ -76,7 +75,6 @@ declare global {
}
}
const { cloudHosting, googleRecaptchaSiteKey } = getAppsmithConfigs();
const recentDomains = getRecentDomains();
const validate = (values: SignupFormValues) => {
const errors: SignupFormValues = {};
@ -96,63 +94,6 @@ const validate = (values: SignupFormValues) => {
return errors;
};
const recentDomainsSection = recentDomains.length > 0 && (
<div className="mt-8">
<div className="mb-2">
<Text kind="body-m">{createMessage(YOU_VE_ALREADY_SIGNED_INTO)}</Text>
</div>
<div className="max-h-48 overflow-y-auto border border-gray-200 rounded-md py-4 px-3">
{recentDomains.map((domain, index) => {
const orgName = domain
.split(".")[0]
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
const avatarLetter = String.fromCharCode(65 + (index % 26));
const isLastItem = index === recentDomains.length - 1;
return (
<div
className={`flex items-center justify-between p-1 ${
isLastItem ? "mb-0" : "mb-3"
}`}
key={domain}
>
<div className="flex items-center space-x-3">
<div className="w-8 h-8 bg-[color:var(--ads-color-background-secondary)] rounded-full flex items-center justify-center text-gray-600 font-light text-sm">
{avatarLetter}
</div>
<div className="flex flex-col">
<span className="text-md font-semibold text-gray-700 max-w-[180px] line-clamp-1">
{orgName}
</span>
<span className="text-xs font-light text-gray-500 max-w-[180px] line-clamp-1">
{domain}
</span>
</div>
</div>
<Button
className="px-4 py-2 text-sm"
kind="secondary"
onClick={() => {
if (isValidAppsmithDomain(domain)) {
window.location.href = `https://${domain}/user/login`;
}
}}
size="md"
>
Open
</Button>
</div>
);
})}
</div>
</div>
);
type SignUpFormProps = InjectedFormProps<
SignupFormValues,
{ emailValue: string }
@ -372,7 +313,9 @@ export function SignUp(props: SignUpFormProps) {
</SpacedSubmitForm>
)}
{isCloudBillingEnabled && isHostnameEqualtoLogin && cloudBillingSignIn}
{isCloudBillingEnabled && isHostnameEqualtoLogin && recentDomainsSection}
{isCloudBillingEnabled && isHostnameEqualtoLogin && (
<RecentDomainsSection />
)}
</Container>
);
}