Skip to content

Commit a16c118

Browse files
committed
feat: Add multi-organization login ui, messages and enhance organization reducer state
1 parent acec507 commit a16c118

File tree

4 files changed

+107
-3
lines changed

4 files changed

+107
-3
lines changed

app/client/src/ce/constants/messages.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,3 +2698,18 @@ export const PASSWORD_INSUFFICIENT_STRENGTH = () =>
26982698

26992699
export const PLUGIN_NOT_INSTALLED = () =>
27002700
"Upgrade your plan to unlock access to these integrations.";
2701+
2702+
// Multi-org login footer constants
2703+
export const MULTI_ORG_FOOTER_NOT_RIGHT_ORG_LEFT_TEXT = () =>
2704+
"Not the right organization?";
2705+
export const MULTI_ORG_FOOTER_NOT_RIGHT_ORG_RIGHT_TEXT = () =>
2706+
"Enter other URL";
2707+
2708+
export const MULTI_ORG_FOOTER_NOT_PART_OF_ORG_LEFT_TEXT = () =>
2709+
"Not part of the organization?";
2710+
export const MULTI_ORG_FOOTER_NOT_PART_OF_ORG_RIGHT_TEXT = () => "Sign up";
2711+
2712+
export const MULTI_ORG_FOOTER_CREATE_ORG_LEFT_TEXT = () =>
2713+
"Looking to create one?";
2714+
export const MULTI_ORG_FOOTER_CREATE_ORG_RIGHT_TEXT = () =>
2715+
"Create an organization";

app/client/src/ce/reducers/organizationReducer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
import { createReducer } from "utils/ReducerUtils";
1313

1414
export interface OrganizationReduxState<T> {
15+
displayName?: string;
16+
slug?: string;
1517
userPermissions: string[];
1618
organizationConfiguration: Record<string, T>;
1719
new: boolean;

app/client/src/pages/UserAuth/Container.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors";
1313
import { isBrandingEnabled, isMultiOrgFFEnabled } from "ee/utils/planHelpers";
1414

1515
interface ContainerProps {
16-
title: string;
16+
title: string | React.ReactNode;
1717
subtitle?: React.ReactNode;
1818
children: React.ReactNode;
1919
footer?: React.ReactNode;

app/client/src/pages/UserAuth/Login.tsx

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ import {
2323
LOGIN_PAGE_INVALID_CREDS_ERROR,
2424
LOGIN_PAGE_INVALID_CREDS_FORGOT_PASSWORD_LINK,
2525
NEW_TO_APPSMITH,
26+
MULTI_ORG_FOOTER_NOT_RIGHT_ORG_LEFT_TEXT,
27+
MULTI_ORG_FOOTER_NOT_RIGHT_ORG_RIGHT_TEXT,
28+
MULTI_ORG_FOOTER_NOT_PART_OF_ORG_LEFT_TEXT,
29+
MULTI_ORG_FOOTER_NOT_PART_OF_ORG_RIGHT_TEXT,
30+
MULTI_ORG_FOOTER_CREATE_ORG_LEFT_TEXT,
31+
MULTI_ORG_FOOTER_CREATE_ORG_RIGHT_TEXT,
2632
createMessage,
2733
} from "ee/constants/messages";
2834
import { FormGroup } from "@appsmith/ads-old";
@@ -46,6 +52,7 @@ import {
4652
getThirdPartyAuths,
4753
getIsFormLoginEnabled,
4854
getOrganizationConfig,
55+
isWithinAnOrganization,
4956
} from "ee/selectors/organizationSelectors";
5057
import Helmet from "react-helmet";
5158
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
@@ -99,8 +106,12 @@ export function Login(props: LoginFormProps) {
99106
const isBrandingEnabled = useFeatureFlag(
100107
FEATURE_FLAG.license_branding_enabled,
101108
);
109+
const isMultiOrgEnabled = useFeatureFlag(
110+
FEATURE_FLAG.license_multi_org_enabled,
111+
);
102112
const organizationConfig = useSelector(getOrganizationConfig);
103-
const { instanceName } = organizationConfig;
113+
const withinOrg = useSelector(isWithinAnOrganization);
114+
const { displayName, instanceName, slug } = organizationConfig;
104115
const htmlPageTitle = getHTMLPageTitle(isBrandingEnabled, instanceName);
105116
const invalidCredsForgotPasswordLinkText = createMessage(
106117
LOGIN_PAGE_INVALID_CREDS_FORGOT_PASSWORD_LINK,
@@ -138,6 +149,33 @@ export function Login(props: LoginFormProps) {
138149
forgotPasswordURL += `?email=${props.emailValue}`;
139150
}
140151

152+
const getPrimaryLoginURL = () => {
153+
const hostnameParts = window.location.hostname.split(".");
154+
155+
hostnameParts[0] = "login";
156+
const orgChangeURL = `https://${hostnameParts.join(".")}`;
157+
158+
return orgChangeURL;
159+
};
160+
161+
const multiOrgFooterContent = [
162+
{
163+
leftText: createMessage(MULTI_ORG_FOOTER_NOT_RIGHT_ORG_LEFT_TEXT),
164+
rightText: createMessage(MULTI_ORG_FOOTER_NOT_RIGHT_ORG_RIGHT_TEXT),
165+
rightTextLink: getPrimaryLoginURL() + "/org",
166+
},
167+
{
168+
leftText: createMessage(MULTI_ORG_FOOTER_NOT_PART_OF_ORG_LEFT_TEXT),
169+
rightText: createMessage(MULTI_ORG_FOOTER_NOT_PART_OF_ORG_RIGHT_TEXT),
170+
rightTextLink: getPrimaryLoginURL(),
171+
},
172+
{
173+
leftText: createMessage(MULTI_ORG_FOOTER_CREATE_ORG_LEFT_TEXT),
174+
rightText: createMessage(MULTI_ORG_FOOTER_CREATE_ORG_RIGHT_TEXT),
175+
rightTextLink: getPrimaryLoginURL(),
176+
},
177+
];
178+
141179
const footerSection = isFormLoginEnabled && (
142180
<div className="px-2 flex align-center justify-center text-center text-[color:var(--ads-v2\-color-fg)] text-[14px]">
143181
{createMessage(NEW_TO_APPSMITH)}&nbsp;
@@ -152,8 +190,57 @@ export function Login(props: LoginFormProps) {
152190
</div>
153191
);
154192

193+
const multiOrgFooterSection = (
194+
<div className="px-2 flex flex-col gap-3 align-center justify-center text-center text-[color:var(--ads-v2\-color-fg)] text-[14px]">
195+
{multiOrgFooterContent.map((item) => (
196+
<div className="flex align-center justify-center" key={item.leftText}>
197+
{item.leftText}&nbsp;
198+
<Link
199+
className="t--sign-up t--signup-link"
200+
kind="primary"
201+
target="_self"
202+
to={item.rightTextLink}
203+
>
204+
{item.rightText}
205+
</Link>
206+
</div>
207+
))}
208+
</div>
209+
);
210+
211+
const renderTitle = () => {
212+
if (isMultiOrgEnabled && withinOrg && displayName) {
213+
return (
214+
<>
215+
Sign in to{" "}
216+
<span style={{ color: "var(--ads-v2-color-fg-brand)" }}>
217+
{displayName}
218+
</span>
219+
</>
220+
);
221+
}
222+
223+
return createMessage(LOGIN_PAGE_TITLE);
224+
};
225+
226+
const renderSubtitle = () => {
227+
if (isMultiOrgEnabled && withinOrg && slug) {
228+
const lowercaseInstanceName = slug.toLowerCase();
229+
230+
return `${lowercaseInstanceName}.appsmith.com`;
231+
}
232+
233+
return undefined;
234+
};
235+
155236
return (
156-
<Container footer={footerSection} title={createMessage(LOGIN_PAGE_TITLE)}>
237+
<Container
238+
footer={
239+
isMultiOrgEnabled && withinOrg ? multiOrgFooterSection : footerSection
240+
}
241+
subtitle={renderSubtitle()}
242+
title={renderTitle()}
243+
>
157244
<Helmet>
158245
<title>{htmlPageTitle}</title>
159246
</Helmet>

0 commit comments

Comments
 (0)