feat: one click code splitting - Branding, SSO (#25231)
## Description Adds Support to show different versions of the following pages based on the plan the user is subscribed to. -Branding -SSO #### PR fixes following issue(s) Fixes #https://github.com/appsmithorg/appsmith-ee/issues/1800 #### Media https://www.notion.so/appsmith/POC-Code-Splitting-1-Click-Upgrade-Downgrade-Frontend-4fe83a8de6c54224bad2bc43e8e4d34b #### Type of change - New feature (non-breaking change which adds functionality) ## Testing - [x] Manual - [ ] Jest - [x] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
parent
f2636358af
commit
dbe3884417
|
|
@ -53,6 +53,7 @@ describe("Admin settings page", function () {
|
|||
stubPricingPage();
|
||||
cy.get(".t--settings-category-branding").click();
|
||||
cy.url().should("contain", "/settings/branding");
|
||||
cy.get(adminsSettings.brandingSubmitButton).should("be.disabled");
|
||||
cy.xpath(adminsSettings.upgrade).click();
|
||||
cy.get("@pricingPage").should("be.called");
|
||||
cy.wait(2000);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export default {
|
|||
auditLogs: ".t--settings-category-audit-logs",
|
||||
provisioning: ".t--settings-category-provisioning",
|
||||
upgrageLeftPane: "[data-testid='t--enterprise-settings-category-item-be']",
|
||||
brandingSubmitButton: ".t--settings-branding-submit-button",
|
||||
businessTag: "[data-testid='t--business-tag']",
|
||||
enterpriseTag: "[data-testid='t--enterprise-tag']",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1386,9 +1386,9 @@ export const DISCONNECT_AUTH_METHOD = () => "Disconnect";
|
|||
export const DISCONNECT_CONFIRMATION = () => "Are you sure?";
|
||||
|
||||
// Branding
|
||||
export const ADMIN_BRANDING_SETTINGS_TITLE = () =>
|
||||
export const ADMIN_BRANDING_SETTINGS_TITLE_UPGRADE = () =>
|
||||
"Custom Branding for your workspaces";
|
||||
export const ADMIN_BRANDING_SETTINGS_SUBTITLE = () =>
|
||||
export const ADMIN_BRANDING_SETTINGS_SUBTITLE_UPGRADE = () =>
|
||||
"Make your workspaces and apps look more yours in a few clicks as in the example below. Upload your logo and favicon, set your primary color, and preview the new look. To save a look you like, upgrade to our Business Edition.";
|
||||
export const ADMIN_BRANDING_COLOR_TOOLTIP = () =>
|
||||
`When you choose a primary color, we auto-magically fill in the secondary and accent colors. You can change them to get the look you want.`;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ export const FEATURE_FLAG = {
|
|||
ab_gsheet_schema_enabled: "ab_gsheet_schema_enabled",
|
||||
ab_wds_enabled: "ab_wds_enabled",
|
||||
release_widgetdiscovery_enabled: "release_widgetdiscovery_enabled",
|
||||
license_sso_enabled: "license_sso_enabled",
|
||||
license_branding_enabled: "license_branding_enabled",
|
||||
ab_table_widget_activation_enabled: "ab_table_widget_activation_enabled",
|
||||
} as const;
|
||||
|
||||
|
|
@ -35,6 +37,8 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
|
|||
ab_gsheet_schema_enabled: false,
|
||||
ab_wds_enabled: false,
|
||||
release_widgetdiscovery_enabled: false,
|
||||
license_sso_enabled: false,
|
||||
license_branding_enabled: false,
|
||||
ab_table_widget_activation_enabled: false,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ export type AuthMethodType = {
|
|||
isConnected?: boolean;
|
||||
calloutBanner?: banner;
|
||||
icon?: string;
|
||||
isFeatureEnabled: boolean;
|
||||
};
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
|
|
@ -109,7 +110,7 @@ export function ActionButton({ method }: { method: AuthMethodType }) {
|
|||
});
|
||||
|
||||
const onClickHandler = (method: AuthMethodType) => {
|
||||
if (!method.needsUpgrade || method.isConnected) {
|
||||
if (method?.isFeatureEnabled || method.isConnected) {
|
||||
AnalyticsUtil.logEvent(
|
||||
method.isConnected
|
||||
? "ADMIN_SETTINGS_EDIT_AUTH_METHOD"
|
||||
|
|
@ -133,7 +134,9 @@ export function ActionButton({ method }: { method: AuthMethodType }) {
|
|||
<ButtonWrapper>
|
||||
<Button
|
||||
className={`t--settings-sub-category-${
|
||||
method.needsUpgrade ? `upgrade-${method.category}` : method.category
|
||||
!method?.isFeatureEnabled
|
||||
? `upgrade-${method.category}`
|
||||
: method.category
|
||||
}`}
|
||||
data-testid="btn-auth-account"
|
||||
kind={"secondary"}
|
||||
|
|
@ -141,7 +144,11 @@ export function ActionButton({ method }: { method: AuthMethodType }) {
|
|||
size="md"
|
||||
>
|
||||
{createMessage(
|
||||
method.isConnected ? EDIT : !!method.needsUpgrade ? UPGRADE : ENABLE,
|
||||
method.isConnected
|
||||
? EDIT
|
||||
: !method?.isFeatureEnabled
|
||||
? UPGRADE
|
||||
: ENABLE,
|
||||
)}
|
||||
</Button>
|
||||
</ButtonWrapper>
|
||||
|
|
@ -183,7 +190,7 @@ export function AuthPage({ authMethods }: { authMethods: AuthMethodType[] }) {
|
|||
renderAs="p"
|
||||
>
|
||||
{method.label}
|
||||
{method.needsUpgrade && <BusinessTag />}
|
||||
{!method.isFeatureEnabled && <BusinessTag />}
|
||||
{method.isConnected && (
|
||||
<Tooltip
|
||||
content={createMessage(
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ import {
|
|||
SAML_AUTH_DESC,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import { isSSOEnabled } from "@appsmith/utils/planHelpers";
|
||||
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
|
||||
import store from "store";
|
||||
|
||||
const featureFlags = selectFeatureFlags(store.getState());
|
||||
|
||||
const FormAuth: AdminConfigType = {
|
||||
type: SettingCategories.FORM_AUTH,
|
||||
|
|
@ -195,6 +200,7 @@ export const FormAuthCallout: AuthMethodType = {
|
|||
subText: createMessage(FORM_LOGIN_DESC),
|
||||
image: Lock,
|
||||
icon: "lock-password-line",
|
||||
isFeatureEnabled: true,
|
||||
};
|
||||
|
||||
export const GoogleAuthCallout: AuthMethodType = {
|
||||
|
|
@ -203,6 +209,7 @@ export const GoogleAuthCallout: AuthMethodType = {
|
|||
label: "Google",
|
||||
subText: createMessage(GOOGLE_AUTH_DESC),
|
||||
image: Google,
|
||||
isFeatureEnabled: true,
|
||||
};
|
||||
|
||||
export const GithubAuthCallout: AuthMethodType = {
|
||||
|
|
@ -211,6 +218,7 @@ export const GithubAuthCallout: AuthMethodType = {
|
|||
label: "GitHub",
|
||||
subText: createMessage(GITHUB_AUTH_DESC),
|
||||
image: Github,
|
||||
isFeatureEnabled: true,
|
||||
};
|
||||
|
||||
export const SamlAuthCallout: AuthMethodType = {
|
||||
|
|
@ -219,7 +227,7 @@ export const SamlAuthCallout: AuthMethodType = {
|
|||
label: "SAML 2.0",
|
||||
subText: createMessage(SAML_AUTH_DESC),
|
||||
image: SamlSso,
|
||||
needsUpgrade: true,
|
||||
isFeatureEnabled: isSSOEnabled(featureFlags),
|
||||
};
|
||||
|
||||
export const OidcAuthCallout: AuthMethodType = {
|
||||
|
|
@ -228,7 +236,7 @@ export const OidcAuthCallout: AuthMethodType = {
|
|||
label: "OIDC",
|
||||
subText: createMessage(OIDC_AUTH_DESC),
|
||||
image: OIDC,
|
||||
needsUpgrade: true,
|
||||
isFeatureEnabled: isSSOEnabled(featureFlags),
|
||||
};
|
||||
|
||||
const AuthMethods = [
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import React from "react";
|
|||
import { Button } from "design-system";
|
||||
import { ContentBox } from "pages/Settings/components";
|
||||
import {
|
||||
ADMIN_BRANDING_SETTINGS_SUBTITLE,
|
||||
ADMIN_BRANDING_SETTINGS_TITLE,
|
||||
ADMIN_BRANDING_SETTINGS_SUBTITLE_UPGRADE,
|
||||
ADMIN_BRANDING_SETTINGS_TITLE_UPGRADE,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import useOnUpgrade from "utils/hooks/useOnUpgrade";
|
||||
|
|
@ -34,7 +34,7 @@ const UpgradeBanner = () => {
|
|||
kind="heading-l"
|
||||
renderAs="h1"
|
||||
>
|
||||
{createMessage(ADMIN_BRANDING_SETTINGS_TITLE)}
|
||||
{createMessage(ADMIN_BRANDING_SETTINGS_TITLE_UPGRADE)}
|
||||
</SettingsHeader>
|
||||
<StyledSettingsSubHeader
|
||||
className="w-7/12 mt-1"
|
||||
|
|
@ -42,11 +42,16 @@ const UpgradeBanner = () => {
|
|||
kind="body-m"
|
||||
renderAs="h2"
|
||||
>
|
||||
{createMessage(ADMIN_BRANDING_SETTINGS_SUBTITLE)}
|
||||
{createMessage(ADMIN_BRANDING_SETTINGS_SUBTITLE_UPGRADE)}
|
||||
</StyledSettingsSubHeader>
|
||||
</main>
|
||||
<aside>
|
||||
<Button onClick={onUpgrade} size="md" startIcon="star-line">
|
||||
<Button
|
||||
data-testid="t--branding-upgrade-button"
|
||||
onClick={onUpgrade}
|
||||
size="md"
|
||||
startIcon="star-line"
|
||||
>
|
||||
Upgrade
|
||||
</Button>
|
||||
</aside>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,12 @@ import {
|
|||
SettingCategories,
|
||||
SettingTypes,
|
||||
} from "@appsmith/pages/AdminSettings/config/types";
|
||||
import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors";
|
||||
import { isBrandingEnabled } from "@appsmith/utils/planHelpers";
|
||||
import BrandingPage from "pages/Settings/config/branding/BrandingPage";
|
||||
import store from "store";
|
||||
|
||||
const featureFlags = selectFeatureFlags(store.getState());
|
||||
|
||||
export const config: AdminConfigType = {
|
||||
type: SettingCategories.BRANDING,
|
||||
|
|
@ -14,4 +19,5 @@ export const config: AdminConfigType = {
|
|||
title: "Branding",
|
||||
icon: "pantone",
|
||||
component: BrandingPage,
|
||||
isFeatureEnabled: isBrandingEnabled(featureFlags),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export interface Category {
|
|||
categoryType: string;
|
||||
needsUpgrade?: boolean;
|
||||
isEnterprise?: boolean;
|
||||
isFeatureEnabled?: boolean;
|
||||
}
|
||||
|
||||
export const SettingCategories = {
|
||||
|
|
@ -136,4 +137,5 @@ export type AdminConfigType = {
|
|||
needsUpgrade?: boolean;
|
||||
categoryType: CategoryType;
|
||||
isEnterprise?: boolean;
|
||||
isFeatureEnabled?: boolean;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export function FooterComponent(props: FooterProps) {
|
|||
</div>
|
||||
</div>
|
||||
<div className="right">
|
||||
<Button onClick={onClick} size="md">
|
||||
<Button data-testid="t--button-upgrade" onClick={onClick} size="md">
|
||||
{createMessage(UPGRADE)}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
10
app/client/src/ce/utils/planHelpers.ts
Normal file
10
app/client/src/ce/utils/planHelpers.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { FeatureFlags } from "@appsmith/entities/FeatureFlag";
|
||||
|
||||
//if feature flag is true then return feature is enbaled
|
||||
export const isBrandingEnabled = (featureFlags: FeatureFlags) => {
|
||||
return featureFlags?.license_branding_enabled;
|
||||
};
|
||||
|
||||
export const isSSOEnabled = (featureFlags: FeatureFlags) => {
|
||||
return featureFlags?.license_sso_enabled;
|
||||
};
|
||||
1
app/client/src/ee/utils/planHelpers.ts
Normal file
1
app/client/src/ee/utils/planHelpers.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "ce/utils/planHelpers";
|
||||
|
|
@ -47,6 +47,7 @@ export class ConfigFactory {
|
|||
needsUpgrade: config.needsUpgrade,
|
||||
isEnterprise: config.isEnterprise,
|
||||
needsRefresh: config.needsRefresh,
|
||||
isFeatureEnabled: config.isFeatureEnabled,
|
||||
children: config?.children?.map((child) =>
|
||||
ConfigFactory.getCategory(child),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ import { useForm } from "react-hook-form";
|
|||
import Previews from "./previews";
|
||||
import SettingsForm from "./SettingsForm";
|
||||
import { getTenantConfig } from "@appsmith/selectors/tenantSelectors";
|
||||
import type { AdminConfigType } from "@appsmith/pages/AdminSettings/config/types";
|
||||
import { Wrapper } from "@appsmith/pages/AdminSettings/config/authentication/AuthPage";
|
||||
import UpgradeBanner from "@appsmith/pages/AdminSettings/config/branding/UpgradeBanner";
|
||||
|
||||
import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
|
||||
import type { AdminConfigType } from "@appsmith/pages/AdminSettings/config/types";
|
||||
import { getUpgradeBanner } from "utils/BusinessFeatures/brandingPageHelpers";
|
||||
|
||||
export type brandColorsKeys =
|
||||
| "primary"
|
||||
|
|
@ -29,7 +30,7 @@ type BrandingPageProps = {
|
|||
|
||||
function BrandingPage(props: BrandingPageProps) {
|
||||
const { category } = props;
|
||||
const { needsUpgrade = true } = category;
|
||||
const isBrandingEnabled = category?.isFeatureEnabled ?? false;
|
||||
const tentantConfig = useSelector(getTenantConfig);
|
||||
const defaultValues = {
|
||||
brandColors: tentantConfig.brandColors,
|
||||
|
|
@ -66,12 +67,12 @@ function BrandingPage(props: BrandingPageProps) {
|
|||
|
||||
return (
|
||||
<Wrapper>
|
||||
<UpgradeBanner />
|
||||
{getUpgradeBanner(isBrandingEnabled)}
|
||||
<div className="grid md:grid-cols-[1fr] lg:grid-cols-[max(300px,30%)_1fr] gap-8 mt-4 pr-7">
|
||||
<SettingsForm
|
||||
control={control}
|
||||
defaultValues={defaultValues}
|
||||
disabled={needsUpgrade}
|
||||
disabled={!isBrandingEnabled}
|
||||
formState={formState}
|
||||
handleSubmit={handleSubmit}
|
||||
reset={reset}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,12 @@ function SettingsForm(props: SettingsFormProps) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<Button isDisabled={disabled || !hasDirtyFields} size="md" type="submit">
|
||||
<Button
|
||||
className="t--settings-branding-submit-button"
|
||||
isDisabled={disabled || !hasDirtyFields}
|
||||
size="md"
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Wrapper>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { default as UpgradeBanner_CE } from "ce/pages/AdminSettings/config/branding/UpgradeBanner";
|
||||
import { default as UpgradeBanner_EE } from "ee/pages/AdminSettings/config/branding/UpgradeBanner";
|
||||
import React from "react";
|
||||
|
||||
export const getUpgradeBanner = (isEnabled: boolean) => {
|
||||
if (isEnabled) {
|
||||
return <UpgradeBanner_EE />;
|
||||
} else return <UpgradeBanner_CE />;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user