chore: ai agent sing up flow (#39943)

## Description
Part of [EE PR](https://github.com/appsmithorg/appsmith-ee/pull/6704)


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

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

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!IMPORTANT]
> 🟣 🟣 🟣 Your tests are running.
> Tests running at:
<https://github.com/appsmithorg/appsmith/actions/runs/14106727889>
> Commit: 0fb8b6d7309a98d961c88923465f384bb2f518ea
> Workflow: `PR Automation test suite`
> Tags: `@tag.Sanity`
> Spec: ``
> <hr>Thu, 27 Mar 2025 12:36:47 UTC
<!-- end of auto-generated comment: Cypress test results  -->


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


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

- **New Features**
- Introduced informative messaging for AI Agent features in the
applications and sign-up experiences.
- Enabled dynamic interface behavior that conditionally displays content
based on the activation of AI Agent functionality.

- **Style**
- Enhanced text formatting in authentication views to improve
readability and support multi-line content.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Valera Melnikov 2025-03-27 15:48:12 +03:00 committed by GitHub
parent 79cdfef7a0
commit 7f3a66de2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 75 additions and 40 deletions

View File

@ -214,6 +214,10 @@ export const NEW_APPLICATION = () => `New application`;
export const APPLICATIONS = () => `Applications`; export const APPLICATIONS = () => `Applications`;
export const FIXED_APPLICATIONS = () => `Classic Applications`; export const FIXED_APPLICATIONS = () => `Classic Applications`;
export const AI_AGENTS_APPLICATIONS = () => `AI Agents`; export const AI_AGENTS_APPLICATIONS = () => `AI Agents`;
export const AI_APPLICATION_CARD_LIST_ZERO_STATE = () =>
`There are no AI Agents in this workspace.`;
export const AI_AGENT_AUTH_SUBTITLE = () =>
`Sign up with any Google account.\n Support for email will be available soon.`;
export const USER_PROFILE_PICTURE_UPLOAD_FAILED = () => export const USER_PROFILE_PICTURE_UPLOAD_FAILED = () =>
"Unable to upload display picture."; "Unable to upload display picture.";

View File

@ -17,6 +17,7 @@ export const FEATURE_FLAG = {
"release_show_publish_app_to_community_enabled", "release_show_publish_app_to_community_enabled",
license_gac_enabled: "license_gac_enabled", license_gac_enabled: "license_gac_enabled",
release_anvil_enabled: "release_anvil_enabled", release_anvil_enabled: "release_anvil_enabled",
license_ai_agent_enabled: "license_ai_agent_enabled",
license_git_branch_protection_enabled: license_git_branch_protection_enabled:
"license_git_branch_protection_enabled", "license_git_branch_protection_enabled",
license_git_continuous_delivery_enabled: license_git_continuous_delivery_enabled:
@ -75,6 +76,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_show_publish_app_to_community_enabled: false, release_show_publish_app_to_community_enabled: false,
license_gac_enabled: false, license_gac_enabled: false,
release_anvil_enabled: false, release_anvil_enabled: false,
license_ai_agent_enabled: false,
release_drag_drop_building_blocks_enabled: false, release_drag_drop_building_blocks_enabled: false,
license_git_branch_protection_enabled: false, license_git_branch_protection_enabled: false,
license_git_continuous_delivery_enabled: false, license_git_continuous_delivery_enabled: false,

View File

@ -9,6 +9,7 @@ import {
import type { UpdateApplicationPayload } from "ee/api/ApplicationApi"; import type { UpdateApplicationPayload } from "ee/api/ApplicationApi";
import { import {
AI_AGENTS_APPLICATIONS, AI_AGENTS_APPLICATIONS,
AI_APPLICATION_CARD_LIST_ZERO_STATE,
APPLICATIONS, APPLICATIONS,
CREATE_A_NEW_WORKSPACE, CREATE_A_NEW_WORKSPACE,
createMessage, createMessage,
@ -17,6 +18,7 @@ import {
NO_WORKSPACE_HEADING, NO_WORKSPACE_HEADING,
WORKSPACES_HEADING, WORKSPACES_HEADING,
} from "ee/constants/messages"; } from "ee/constants/messages";
import { getIsAiAgentFlowEnabled } from "ee/selectors/aiAgentSelectors";
import type { ApplicationPayload } from "entities/Application"; import type { ApplicationPayload } from "entities/Application";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { createWorkspaceSubmitHandler } from "ee/pages/workspace/helpers"; import { createWorkspaceSubmitHandler } from "ee/pages/workspace/helpers";
@ -552,6 +554,7 @@ export function ApplicationsSection(props: any) {
// This checks if the Anvil feature flag is enabled and shows different sections in the workspace // This checks if the Anvil feature flag is enabled and shows different sections in the workspace
// for Anvil and Classic applications // for Anvil and Classic applications
const isAnvilEnabled = useSelector(getIsAnvilLayoutEnabled); const isAnvilEnabled = useSelector(getIsAnvilLayoutEnabled);
const isAiAgentFlowEnabled = useSelector(getIsAiAgentFlowEnabled);
const currentUser = useSelector(getCurrentUser); const currentUser = useSelector(getCurrentUser);
const isMobile = useIsMobileDevice(); const isMobile = useIsMobileDevice();
const urlParams = new URLSearchParams(location.search); const urlParams = new URLSearchParams(location.search);
@ -896,42 +899,47 @@ export function ApplicationsSection(props: any) {
<ResourceListLoader isMobile={isMobile} resources={applications} /> <ResourceListLoader isMobile={isMobile} resources={applications} />
) : ( ) : (
<> <>
<ApplicationCardList {!isAiAgentFlowEnabled && (
applications={nonAnvilApplications} <ApplicationCardList
canInviteToWorkspace={canInviteToWorkspace} applications={nonAnvilApplications}
deleteApplication={deleteApplication} canInviteToWorkspace={canInviteToWorkspace}
enableImportExport={enableImportExport} deleteApplication={deleteApplication}
hasCreateNewApplicationPermission={ enableImportExport={enableImportExport}
hasCreateNewApplicationPermission hasCreateNewApplicationPermission={
} hasCreateNewApplicationPermission
hasManageWorkspacePermissions={hasManageWorkspacePermissions} }
isMobile={isMobile} hasManageWorkspacePermissions={hasManageWorkspacePermissions}
onClickAddNewButton={onClickAddNewAppButton} isMobile={isMobile}
title={createMessage(APPLICATIONS)} onClickAddNewButton={onClickAddNewAppButton}
updateApplicationDispatch={updateApplicationDispatch} title={createMessage(APPLICATIONS)}
workspaceId={activeWorkspace.id} updateApplicationDispatch={updateApplicationDispatch}
/> workspaceId={activeWorkspace.id}
{isAnvilEnabled && />
anvilApplications.length > 0 && ( // AI Agents list )}
<ApplicationCardList {((isAnvilEnabled && anvilApplications.length > 0) ||
applications={anvilApplications} isAiAgentFlowEnabled) && (
canInviteToWorkspace={canInviteToWorkspace} <ApplicationCardList
deleteApplication={deleteApplication} applications={anvilApplications}
enableImportExport={enableImportExport} canInviteToWorkspace={canInviteToWorkspace}
hasCreateNewApplicationPermission={ deleteApplication={deleteApplication}
hasCreateNewApplicationPermission emptyStateMessage={
} isAiAgentFlowEnabled
hasManageWorkspacePermissions={ ? createMessage(AI_APPLICATION_CARD_LIST_ZERO_STATE)
hasManageWorkspacePermissions : undefined
} }
isMobile={isMobile} enableImportExport={enableImportExport}
onClickAddNewButton={onClickAddNewAppButton} hasCreateNewApplicationPermission={
title={createMessage(AI_AGENTS_APPLICATIONS)} hasCreateNewApplicationPermission
titleTag={BetaTag} }
updateApplicationDispatch={updateApplicationDispatch} hasManageWorkspacePermissions={hasManageWorkspacePermissions}
workspaceId={activeWorkspace.id} isMobile={isMobile}
/> onClickAddNewButton={onClickAddNewAppButton}
)} title={createMessage(AI_AGENTS_APPLICATIONS)}
titleTag={BetaTag}
updateApplicationDispatch={updateApplicationDispatch}
workspaceId={activeWorkspace.id}
/>
)}
<PackageCardList <PackageCardList
isMobile={isMobile} isMobile={isMobile}
packages={packages} packages={packages}

View File

@ -1,3 +1,11 @@
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import type { AppState } from "ee/reducers";
import { selectFeatureFlagCheck } from "ee/selectors/featureFlagsSelectors";
export const getAgentChatQuery = () => { export const getAgentChatQuery = () => {
return undefined; return undefined;
}; };
export const getIsAiAgentFlowEnabled = (state: AppState) => {
return selectFeatureFlagCheck(state, FEATURE_FLAG.license_ai_agent_enabled);
};

View File

@ -68,7 +68,7 @@ function Container(props: ContainerProps) {
{title} {title}
</h1> </h1>
{subtitle && ( {subtitle && (
<p className="text-[14px] text-center text-[color:var(--ads-v2\-color-fg)]"> <p className="text-[14px] text-center text-[color:var(--ads-v2\-color-fg)] whitespace-pre-line">
{subtitle} {subtitle}
</p> </p>
)} )}

View File

@ -28,6 +28,8 @@ import {
VISIT_OUR_DOCS, VISIT_OUR_DOCS,
ALREADY_USING_APPSMITH, ALREADY_USING_APPSMITH,
SIGN_IN_TO_AN_EXISTING_ORGANISATION, SIGN_IN_TO_AN_EXISTING_ORGANISATION,
AI_AGENT_AUTH_SUBTITLE,
LOGIN_PAGE_TITLE,
} from "ee/constants/messages"; } from "ee/constants/messages";
import FormTextField from "components/utils/ReduxFormTextField"; import FormTextField from "components/utils/ReduxFormTextField";
import ThirdPartyAuth from "pages/UserAuth/ThirdPartyAuth"; import ThirdPartyAuth from "pages/UserAuth/ThirdPartyAuth";
@ -63,6 +65,7 @@ import * as Sentry from "@sentry/react";
import CsrfTokenInput from "pages/UserAuth/CsrfTokenInput"; import CsrfTokenInput from "pages/UserAuth/CsrfTokenInput";
import { useIsCloudBillingEnabled } from "hooks"; import { useIsCloudBillingEnabled } from "hooks";
import { isLoginHostname } from "utils/cloudBillingUtils"; import { isLoginHostname } from "utils/cloudBillingUtils";
import { getIsAiAgentFlowEnabled } from "ee/selectors/aiAgentSelectors";
declare global { declare global {
interface Window { interface Window {
@ -100,9 +103,10 @@ type SignUpFormProps = InjectedFormProps<
export function SignUp(props: SignUpFormProps) { export function SignUp(props: SignUpFormProps) {
const history = useHistory(); const history = useHistory();
const isFormLoginEnabled = useSelector(getIsFormLoginEnabled); const isFormLoginEnabled = useSelector(getIsFormLoginEnabled);
const isAiAgentFlowEnabled = useSelector(getIsAiAgentFlowEnabled);
useEffect(() => { useEffect(() => {
if (!isFormLoginEnabled) { if (!isFormLoginEnabled && !isAiAgentFlowEnabled) {
const search = new URL(window.location.href)?.searchParams?.toString(); const search = new URL(window.location.href)?.searchParams?.toString();
history.replace({ history.replace({
@ -226,7 +230,7 @@ export function SignUp(props: SignUpFormProps) {
</Link> </Link>
</div> </div>
)} )}
{cloudHosting && ( {cloudHosting && !isAiAgentFlowEnabled && (
<> <>
<OrWithLines>or</OrWithLines> <OrWithLines>or</OrWithLines>
<div className="px-2 text-center text-[color:var(--ads-v2\-color-fg)] text-[14px]"> <div className="px-2 text-center text-[color:var(--ads-v2\-color-fg)] text-[14px]">
@ -247,7 +251,15 @@ export function SignUp(props: SignUpFormProps) {
); );
return ( return (
<Container footer={footerSection} title={createMessage(SIGNUP_PAGE_TITLE)}> <Container
footer={footerSection}
subtitle={
isAiAgentFlowEnabled ? createMessage(AI_AGENT_AUTH_SUBTITLE) : ""
}
title={createMessage(
isAiAgentFlowEnabled ? SIGNUP_PAGE_TITLE : LOGIN_PAGE_TITLE,
)}
>
<Helmet> <Helmet>
<title>{htmlPageTitle}</title> <title>{htmlPageTitle}</title>
</Helmet> </Helmet>

View File

@ -15,6 +15,7 @@ import {
export const AvailableFeaturesToOverride: FeatureFlag[] = [ export const AvailableFeaturesToOverride: FeatureFlag[] = [
"release_anvil_enabled", "release_anvil_enabled",
"release_layout_conversion_enabled", "release_layout_conversion_enabled",
"license_ai_agent_enabled",
]; ];
export type OverriddenFeatureFlags = Partial<Record<FeatureFlag, boolean>>; export type OverriddenFeatureFlags = Partial<Record<FeatureFlag, boolean>>;