diff --git a/app/client/cypress/locators/welcomePage.json b/app/client/cypress/locators/welcomePage.json
index bfb3cea92e..c46795fa08 100644
--- a/app/client/cypress/locators/welcomePage.json
+++ b/app/client/cypress/locators/welcomePage.json
@@ -1,18 +1,18 @@
{
- "getStarted": ".t--welcome-form-get-started",
- "fullName": ".t--welcome-form-full-name input",
- "email": ".t--welcome-form-email input",
- "password": ".t--welcome-form-password input",
- "verifyPassword": ".t--welcome-form-verify-password input",
+ "firstName":".t--welcome-form-first-name input",
+ "lastName":".t--welcome-form-last-name input",
+ "email":".t--welcome-form-email input",
+ "password":".t--welcome-form-password input",
+ "verifyPassword":".t--welcome-form-verify-password input",
"roleDropdown": ".t--welcome-form-role-dropdown .setup-dropdown",
"roleDropdownOption": ".rc-select-item-option",
"roleInput": ".t--welcome-form-role-input input",
"useCaseDropdown": ".t--welcome-form-role-usecase",
"useCaseDropdownOption": ".rc-select-item-option-content",
- "nextButton": ".t--welcome-form-next-button",
- "dataCollection": ".ads-v2-switch__label:last",
- "newsLetter": ".ads-v2-switch__label:first",
+ "submitButton": ".t--welcome-form-submit-button",
+ "dataCollection": ".t--welcome-form-datacollection",
+ "newsLetter": ".t--welcome-form-newsletter",
"createButton": ".t--welcome-form-create-button",
"createSuperUser": "#super-user-form",
"superUserForm": "[data-testid='super-user-form']"
-}
+}
\ No newline at end of file
diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js
index b300978d0c..055a0736e6 100644
--- a/app/client/cypress/support/commands.js
+++ b/app/client/cypress/support/commands.js
@@ -267,7 +267,7 @@ Cypress.Commands.add("Signup", (uname, pword) => {
cy.get(signupPage.dropdownOption).click();
cy.get(signupPage.useCaseDropdown).click();
cy.get(signupPage.dropdownOption).click();
- cy.get(signupPage.roleUsecaseSubmit).click();
+ cy.get(signupPage.roleUsecaseSubmit).click({ force: true });
cy.wait("@getMe");
cy.wait(3000);
@@ -1275,73 +1275,36 @@ Cypress.Commands.add("createJSObject", (JSCode) => {
Cypress.Commands.add("createSuperUser", () => {
cy.wait(1000);
- cy.get(welcomePage.getStarted).should("be.visible");
- cy.get(welcomePage.getStarted).should("not.be.disabled");
- cy.get(welcomePage.getStarted).click();
- cy.get(welcomePage.fullName).should("be.visible");
+ cy.get(welcomePage.firstName).should("be.visible");
+ cy.get(welcomePage.lastName).should("be.visible");
cy.get(welcomePage.email).should("be.visible");
cy.get(welcomePage.password).should("be.visible");
cy.get(welcomePage.verifyPassword).should("be.visible");
- cy.get(welcomePage.roleDropdown).should("be.visible");
- cy.get(welcomePage.useCaseDropdown).should("be.visible");
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.submitButton).should("be.disabled");
- cy.get(welcomePage.fullName).type(Cypress.env("USERNAME"));
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.firstName).type(Cypress.env("USERNAME"));
+ cy.get(welcomePage.submitButton).should("be.disabled");
cy.get(welcomePage.email).type(Cypress.env("USERNAME"));
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.submitButton).should("be.disabled");
cy.get(welcomePage.password).type(Cypress.env("PASSWORD"));
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.submitButton).should("be.disabled");
cy.get(welcomePage.verifyPassword).type(Cypress.env("PASSWORD"));
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.submitButton).should("not.be.disabled");
+ cy.get(welcomePage.submitButton).click();
+
cy.get(welcomePage.roleDropdown).click();
cy.get(welcomePage.roleDropdownOption).eq(1).click();
- cy.get(welcomePage.nextButton).should("be.disabled");
+ cy.get(welcomePage.submitButton).should("be.disabled");
cy.get(welcomePage.useCaseDropdown).click();
cy.get(welcomePage.useCaseDropdownOption).eq(1).click();
- cy.get(welcomePage.nextButton).should("not.be.disabled");
- cy.get(welcomePage.nextButton).click();
- if (Cypress.env("AIRGAPPED")) {
- cy.get(welcomePage.newsLetter).should("not.exist");
- cy.get(welcomePage.dataCollection).should("not.exist");
- cy.get(welcomePage.createButton).should("not.exist");
- } else {
- cy.get(welcomePage.superUserForm).should("be.visible");
- cy.get(welcomePage.newsLetter).should("be.visible");
- cy.get(welcomePage.dataCollection).should("be.visible");
- cy.get(welcomePage.createButton).should("be.visible");
- cy.get(welcomePage.createButton).trigger("mouseover").click();
- cy.wait("@createSuperUser").then((interception) => {
- expect(interception.request.body).contains(
- "allowCollectingAnonymousData=true",
- );
- expect(interception.request.body).contains("signupForNewsletter=true");
- });
- }
- //cy.get(welcomePage.newsLetter).trigger("mouseover").click();
- //cy.get(welcomePage.newsLetter).find("input").uncheck();//not working
- //cy.get(welcomePage.dataCollection).trigger("mouseover").click();
- //cy.wait(1000); //for toggles to settle
-
- //Seeing issue with above also, trying multiple click as below
- //cy.get(welcomePage.createButton).click({ multiple: true });
- //cy.get(welcomePage.createButton).trigger("click");
-
- //Submit also not working
- //cy.get(welcomePage.createSuperUser).submit();
- //cy.wait(5000); //waiting a bit before attempting logout
-
- // cy.get("body").then(($ele) => {
- // if ($ele.find(locator._spanButton("Next").length) > 0) {
- // agHelper.GetNClick(locator._spanButton("Next"));
- // } else agHelper.GetNClick(locator._spanButton("Make your first App"));
- // });
-
- //trying jquery way - also not working
- // cy.get(welcomePage.createButton).then(($createBtn) => {
- // const $jQueryButton = Cypress.$($createBtn); // wrap the button element in jQuery
- // $jQueryButton.trigger("click"); // click on the button using jQuery
- // });
+ cy.get(welcomePage.submitButton).should("not.be.disabled");
+ cy.get(welcomePage.submitButton).click();
+ cy.wait("@createSuperUser").then((interception) => {
+ expect(interception.request.body).contains(
+ "allowCollectingAnonymousData=true",
+ );
+ expect(interception.request.body).contains("signupForNewsletter=true");
+ });
cy.LogOut();
cy.wait(2000);
diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts
index 22a07c4b75..ccd6a1ca39 100644
--- a/app/client/src/ce/constants/messages.ts
+++ b/app/client/src/ce/constants/messages.ts
@@ -999,6 +999,9 @@ export const ONBOARDING_CHECKLIST_DEPLOY_APPLICATIONS = {
export const ONBOARDING_CHECKLIST_FOOTER = () =>
"Not sure where to start? Take the welcome tour";
+export const ONBOARDING_TELEMETRY_POPUP = () =>
+ "We only collect usage data to make Appsmith better for everyone. Visit admin settings to toggle this off.";
+
//Introduction modal
export const HOW_APPSMITH_WORKS = () =>
"Here’s a quick overview of how Appsmith works. ";
@@ -1062,9 +1065,8 @@ export const USE_SNIPPET = () => "Snippet";
export const SNIPPET_TOOLTIP = () => "Search code snippets";
//Welcome page
-export const WELCOME_HEADER = () => "Welcome!";
-export const WELCOME_BODY = () =>
- "Let us setup your account so you can make awesome applications!";
+export const WELCOME_HEADER = () => "Almost there";
+export const WELCOME_BODY = () => "Let's setup your account first";
export const WELCOME_ACTION = () => "Get started";
// API Editor
@@ -1081,10 +1083,11 @@ export const ACTION_EXECUTION_MESSAGE = (actionType: string) =>
export const ACTION_EXECUTION_CANCEL = () => "Cancel request";
export const WELCOME_FORM_HEADER = () => "Let us get to know you better!";
-export const WELCOME_FORM_FULL_NAME = () => "Full Name";
-export const WELCOME_FORM_EMAIL_ID = () => "Email Id";
-export const WELCOME_FORM_CREATE_PASSWORD = () => "Create Password";
-export const WELCOME_FORM_VERIFY_PASSWORD = () => "Verify Password";
+export const WELCOME_FORM_FIRST_NAME = () => "First name";
+export const WELCOME_FORM_LAST_NAME = () => "Last name";
+export const WELCOME_FORM_EMAIL_ID = () => "Email";
+export const WELCOME_FORM_CREATE_PASSWORD = () => "Enter password";
+export const WELCOME_FORM_VERIFY_PASSWORD = () => "Verify password";
export const WELCOME_FORM_ROLE_DROPDOWN = () =>
"Tell us about your primary skillset";
export const WELCOME_FORM_ROLE_DROPDOWN_PLACEHOLDER = () =>
diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/AnonymousDataPopup.tsx b/app/client/src/pages/Editor/FirstTimeUserOnboarding/AnonymousDataPopup.tsx
new file mode 100644
index 0000000000..6ed56b2f68
--- /dev/null
+++ b/app/client/src/pages/Editor/FirstTimeUserOnboarding/AnonymousDataPopup.tsx
@@ -0,0 +1,38 @@
+import React from "react";
+import { Callout } from "design-system";
+import {
+ ADMIN_SETTINGS,
+ LEARN_MORE,
+ ONBOARDING_TELEMETRY_POPUP,
+ createMessage,
+} from "@appsmith/constants/messages";
+import { ADMIN_SETTINGS_CATEGORY_DEFAULT_PATH } from "constants/routes";
+import { TELEMETRY_DOCS_PAGE_URL } from "./constants";
+
+export default function AnonymousDataPopup(props: {
+ onCloseCallout: () => void;
+}) {
+ return (
+
+ {
+ props.onCloseCallout();
+ }}
+ >
+ {createMessage(ONBOARDING_TELEMETRY_POPUP)}
+
+
+ );
+}
diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Tasks.tsx b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Tasks.tsx
index c20483114f..f615e03735 100644
--- a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Tasks.tsx
+++ b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Tasks.tsx
@@ -21,7 +21,7 @@ import {
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import { INTEGRATION_TABS } from "constants/routes";
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
-import React from "react";
+import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
@@ -33,14 +33,25 @@ import {
getDatasources,
getPageActions,
} from "selectors/entitiesSelector";
-import { getFirstTimeUserOnboardingModal } from "selectors/onboardingSelectors";
import styled from "styled-components";
import AnalyticsUtil from "utils/AnalyticsUtil";
import history from "utils/history";
-import IntroductionModal from "./IntroductionModal";
import { integrationEditorURL } from "RouteBuilder";
-import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
+import { getAssetUrl, isAirgapped } from "@appsmith/utils/airgapHelpers";
+import AnonymousDataPopup from "./AnonymousDataPopup";
+import {
+ getFirstTimeUserOnboardingComplete,
+ getFirstTimeUserOnboardingModal,
+ getIsFirstTimeUserOnboardingEnabled,
+} from "selectors/onboardingSelectors";
+import { getCurrentUser } from "selectors/usersSelectors";
+import {
+ getFirstTimeUserOnboardingTelemetryCalloutIsAlreadyShown,
+ setFirstTimeUserOnboardingTelemetryCalloutVisibility,
+} from "utils/storage";
+import { ANONYMOUS_DATA_POPOP_TIMEOUT } from "./constants";
import { DatasourceCreateEntryPoints } from "constants/Datasource";
+import IntroductionModal from "./IntroductionModal";
const Wrapper = styled.div`
width: 100%;
@@ -92,6 +103,12 @@ const getOnboardingQueryImg = () => `${ASSETS_CDN_URL}/onboarding-query.svg`;
const getOnboardingWidgetImg = () => `${ASSETS_CDN_URL}/onboarding-widget.svg`;
export default function OnboardingTasks() {
+ const [isAnonymousDataPopupOpen, setisAnonymousDataPopupOpen] =
+ useState(false);
+
+ const isFirstTimeUserOnboardingEnabled = useSelector(
+ getIsFirstTimeUserOnboardingEnabled,
+ );
const applicationId = useSelector(getCurrentApplicationId);
const pageId = useSelector(getCurrentPageId);
let content;
@@ -99,7 +116,44 @@ export default function OnboardingTasks() {
const actions = useSelector(getPageActions(pageId));
const widgets = useSelector(getCanvasWidgets);
const dispatch = useDispatch();
+ const user = useSelector(getCurrentUser);
+ const isAdmin = user?.isSuperUser || false;
+ const isOnboardingCompleted = useSelector(getFirstTimeUserOnboardingComplete);
const showModal = useSelector(getFirstTimeUserOnboardingModal);
+
+ const hideAnonymousDataPopup = () => {
+ setisAnonymousDataPopupOpen(false);
+ setFirstTimeUserOnboardingTelemetryCalloutVisibility(true);
+ };
+
+ const showShowAnonymousDataPopup = async () => {
+ const shouldPopupShow =
+ !isAirgapped() &&
+ isFirstTimeUserOnboardingEnabled &&
+ isAdmin &&
+ !isOnboardingCompleted;
+ if (shouldPopupShow) {
+ const isAnonymousDataPopupAlreadyOpen =
+ await getFirstTimeUserOnboardingTelemetryCalloutIsAlreadyShown();
+ //true if the modal was already shown else show the modal and set to already shown, also hide the modal after 10 secs
+ if (isAnonymousDataPopupAlreadyOpen) {
+ setisAnonymousDataPopupOpen(false);
+ } else {
+ setisAnonymousDataPopupOpen(true);
+ setTimeout(() => {
+ hideAnonymousDataPopup();
+ }, ANONYMOUS_DATA_POPOP_TIMEOUT);
+ await setFirstTimeUserOnboardingTelemetryCalloutVisibility(true);
+ }
+ } else {
+ setisAnonymousDataPopupOpen(shouldPopupShow);
+ }
+ };
+
+ useEffect(() => {
+ showShowAnonymousDataPopup();
+ }, []);
+
if (!datasources.length && !actions.length) {
content = (
@@ -272,7 +326,10 @@ export default function OnboardingTasks() {
return (
{content}
- {showModal && (
+ {isAnonymousDataPopupOpen && (
+
+ )}
+ {!isAdmin && showModal && (
{
dispatch({
diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts b/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts
new file mode 100644
index 0000000000..22c1f646a7
--- /dev/null
+++ b/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts
@@ -0,0 +1,6 @@
+//Hide Anonymous Data Popup after 15 seconds
+export const ANONYMOUS_DATA_POPOP_TIMEOUT = 15000;
+
+//Telemetry Docs Page
+export const TELEMETRY_DOCS_PAGE_URL =
+ "https://docs.appsmith.com/product/telemetry";
diff --git a/app/client/src/pages/setup/DataCollectionForm.tsx b/app/client/src/pages/setup/DataCollectionForm.tsx
deleted file mode 100644
index a9aab0efc9..0000000000
--- a/app/client/src/pages/setup/DataCollectionForm.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import React, { memo, useState } from "react";
-import styled from "styled-components";
-import { Switch, Link } from "design-system";
-import { ControlWrapper } from "components/propertyControls/StyledControls";
-import {
- AllowToggle,
- AllowToggleWrapper,
- FormBodyWrapper,
- FormHeaderIndex,
- FormHeaderLabel,
- FormHeaderSubtext,
-} from "./common";
-import { TELEMETRY_URL } from "constants/ThirdPartyConstants";
-import {
- createMessage,
- WELCOME_FORM_DATA_COLLECTION_BODY,
- WELCOME_FORM_DATA_COLLECTION_HEADER,
- WELCOME_FORM_DATA_COLLECTION_LABEL_ENABLE,
- WELCOME_FORM_DATA_COLLECTION_LINK,
-} from "@appsmith/constants/messages";
-
-const DataCollectionFormWrapper = styled.div`
- width: 100%;
- position: relative;
- padding-left: ${(props) => props.theme.spaces[17] * 2}px;
-`;
-
-const StyledLink = styled(Link)`
- display: inline-block;
- margin-top: 8px;
-`;
-
-export default memo(function DataCollectionForm() {
- const [allowCollection, setAllowCollection] = useState(true);
- return (
-
-
- 2.
-
- {createMessage(WELCOME_FORM_DATA_COLLECTION_HEADER)}
-
-
- {createMessage(WELCOME_FORM_DATA_COLLECTION_BODY)}
-
-
- {createMessage(WELCOME_FORM_DATA_COLLECTION_LINK)}
-
-
-
-
-
-
-
- setAllowCollection(value)}
- value={allowCollection.toString()}
- >
- {createMessage(WELCOME_FORM_DATA_COLLECTION_LABEL_ENABLE)}
-
-
-
-
-
-
- );
-});
diff --git a/app/client/src/pages/setup/DetailsForm.tsx b/app/client/src/pages/setup/DetailsForm.tsx
index 84b8676f93..51a09a3706 100644
--- a/app/client/src/pages/setup/DetailsForm.tsx
+++ b/app/client/src/pages/setup/DetailsForm.tsx
@@ -1,44 +1,51 @@
-import React from "react";
+import React, { useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import { Field } from "redux-form";
-import {
- DropdownWrapper,
- FormBodyWrapper,
- FormHeaderIndex,
- FormHeaderLabel,
- withDropdown,
-} from "./common";
+import { DropdownWrapper, FormBodyWrapper, withDropdown } from "./common";
import {
createMessage,
WELCOME_FORM_EMAIL_ID,
- WELCOME_FORM_FULL_NAME,
+ WELCOME_FORM_FIRST_NAME,
+ WELCOME_FORM_LAST_NAME,
WELCOME_FORM_CREATE_PASSWORD,
WELCOME_FORM_VERIFY_PASSWORD,
WELCOME_FORM_ROLE_DROPDOWN,
WELCOME_FORM_ROLE,
WELCOME_FORM_USE_CASE,
WELCOME_FORM_CUSTOM_USE_CASE,
- WELCOME_FORM_HEADER,
WELCOME_FORM_ROLE_DROPDOWN_PLACEHOLDER,
WELCOME_FORM_USE_CASE_PLACEHOLDER,
+ CONTINUE,
+ ONBOARDING_STATUS_GET_STARTED,
} from "@appsmith/constants/messages";
import FormTextField from "components/utils/ReduxFormTextField";
import type { SetupFormProps } from "./SetupForm";
import { ButtonWrapper } from "pages/Applications/ForkModalStyles";
import { FormGroup } from "design-system-old";
-import { Button } from "design-system";
+import { Button, Checkbox } from "design-system";
import { roleOptions, useCaseOptions } from "./constants";
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
+import { setFirstTimeUserOnboardingTelemetryCalloutVisibility } from "utils/storage";
const DetailsFormWrapper = styled.div`
width: 100%;
position: relative;
- padding-left: ${(props) => props.theme.spaces[17] * 2}px;
- padding-right: ${(props) => props.theme.spaces[4]}px;
`;
-const StyledFormBodyWrapper = styled(FormBodyWrapper)`
- width: 260px;
+const StyledFormBodyWrapper = styled(FormBodyWrapper)``;
+
+const StyledTabIndicatorWrapper = styled.div`
+ display: flex;
+`;
+
+const StyledTabIndicator = styled.div<{ isFirstPage?: boolean }>`
+ width: 48px;
+ height: 3px;
+ margin: 0 6px 0 0;
+ background-color: ${(props) =>
+ props.isFirstPage
+ ? `var(--ads-v2-color-bg-emphasis);`
+ : `var(--ads-v2-color-bg-brand);`};
`;
const StyledFormGroup = styled(FormGroup)`
@@ -52,107 +59,143 @@ export default function DetailsForm(
) {
const ref = React.createRef();
- const isAirgappedInstance = isAirgapped();
+ const [formState, setFormState] = useState(0);
+
+ const isFirstPage = useMemo(() => formState === 0, [formState]);
+
+ useEffect(() => {
+ const setTelemetryVisibleFalse = async () => {
+ await setFirstTimeUserOnboardingTelemetryCalloutVisibility(false);
+ };
+ setTelemetryVisibleFalse();
+ }, []);
return (
-
- 1.
- {createMessage(WELCOME_FORM_HEADER)}
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {props.role == "other" && (
-
-
+
+
+
+
+
+
+
+
+
+
+
+
- )}
-
-
-
- {props.useCase == "other" && (
-
-
+
+
+
+
+
+
+
+ {!isFirstPage && (
+
+
+
+
+ {props.role == "other" && (
+
+
+
+ )}
+
+
+
+ {props.useCase == "other" && (
+
+
+
+ )}
+
+ {!isAirgapped() && (
+
+ I want security and product updates.
+
+ )}
+
)}
diff --git a/app/client/src/pages/setup/GetStarted.tsx b/app/client/src/pages/setup/GetStarted.tsx
index 8746fbc056..18acea0d1b 100644
--- a/app/client/src/pages/setup/GetStarted.tsx
+++ b/app/client/src/pages/setup/GetStarted.tsx
@@ -22,6 +22,7 @@ import { Field, formValueSelector, reduxForm } from "redux-form";
import styled from "styled-components";
import { DropdownWrapper, withDropdown } from "./common";
import { roleOptions, useCaseOptions } from "./constants";
+import SetupForm from "./SetupForm";
const ActionContainer = styled.div`
margin-top: ${(props) => props.theme.spaces[15]}px;
@@ -41,16 +42,10 @@ type NonSuperUserFormData = {
role_name?: string;
};
-export function SuperUserForm(props: UserFormProps) {
+export function SuperUserForm() {
return (
- props.onGetStarted && props.onGetStarted()}
- size="md"
- >
- {createMessage(WELCOME_ACTION)}
-
+
);
}
@@ -124,15 +119,9 @@ function NonSuperUser(
- !props.invalid && // temp fix - design system needs to be fixed for disabling click
- props.onGetStarted &&
- props.onGetStarted(
- props.role !== "other" ? props.role : props.role_name,
- props.useCase,
- )
- }
- size="md"
+ kind="primary"
+ renderAs="button"
+ type="submit"
>
{createMessage(WELCOME_ACTION)}
diff --git a/app/client/src/pages/setup/NewsletterForm.tsx b/app/client/src/pages/setup/NewsletterForm.tsx
deleted file mode 100644
index 8058c2c1b3..0000000000
--- a/app/client/src/pages/setup/NewsletterForm.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { noop } from "lodash";
-import React from "react";
-import styled from "styled-components";
-import { Button, Switch } from "design-system";
-import {
- AllowToggle,
- AllowToggleWrapper,
- ButtonWrapper,
- FormBodyWrapper,
- FormHeaderIndex,
- FormHeaderLabel,
-} from "./common";
-import { memo } from "react";
-import {
- createMessage,
- WELCOME_FORM_NEWLETTER_HEADER,
- WELCOME_FORM_NEWLETTER_LABEL,
- WELCOME_FORM_SUBMIT_LABEL,
-} from "@appsmith/constants/messages";
-
-const NewsletterContainer = styled.div`
- width: 100%;
- position: relative;
- padding-left: ${(props) => props.theme.spaces[17] * 2}px;
- margin-top: ${(props) => props.theme.spaces[12] * 2}px;
-`;
-
-export default memo(function NewsletterForm() {
- return (
-
-
- 3.
-
- {createMessage(WELCOME_FORM_NEWLETTER_HEADER)}
-
-
-
-
-
- noop}
- value={"true"}
- >
- {createMessage(WELCOME_FORM_NEWLETTER_LABEL)}
-
-
-
-
-
-
-
-
- );
-});
diff --git a/app/client/src/pages/setup/SetupForm.tsx b/app/client/src/pages/setup/SetupForm.tsx
index 79594906ff..ad28087370 100644
--- a/app/client/src/pages/setup/SetupForm.tsx
+++ b/app/client/src/pages/setup/SetupForm.tsx
@@ -1,10 +1,7 @@
import React, { useRef } from "react";
import styled from "styled-components";
import { connect } from "react-redux";
-import DataCollectionForm from "./DataCollectionForm";
import DetailsForm from "./DetailsForm";
-import NewsletterForm from "./NewsletterForm";
-import AppsmithLogo from "assets/images/appsmith_logo.png";
import {
WELCOME_FORM_USECASE_FIELD_NAME,
WELCOME_FORM_EMAIL_FIELD_NAME,
@@ -23,48 +20,29 @@ import type { AppState } from "@appsmith/reducers";
import { SUPER_USER_SUBMIT_PATH } from "@appsmith/constants/ApiConstants";
import { useState } from "react";
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
-import { noop } from "utils/AppsmithUtils";
const PageWrapper = styled.div`
width: 100%;
display: flex;
- justify-content: center;
- height: 100vh;
+ justify-content: start;
overflow: auto;
position: relative;
z-index: 100;
`;
-const SetupFormContainer = styled.div`
- padding: 120px 42px 0px 0px;
-`;
+const SetupFormContainer = styled.div``;
const SetupStep = styled.div<{ active: boolean }>`
display: ${(props) => (props.active ? "block" : "none")};
`;
-const LogoContainer = styled.div`
- padding-left: ${(props) => props.theme.spaces[17] * 2}px;
- padding-top: ${(props) => props.theme.spaces[12] * 2}px;
- transform: translate(-11px, 0);
- background-color: ${(props) => props.theme.colors.homepageBackground};
- position: fixed;
- width: 566px;
- height: 112px;
- z-index: 1;
- top: 0;
-`;
-
-const AppsmithLogoImg = styled.img`
- max-width: 170px;
-`;
-
const SpaceFiller = styled.div`
height: 100px;
`;
export type DetailsFormValues = {
- name?: string;
+ firstName?: string;
+ lastName?: string;
email?: string;
password?: string;
verifyPassword?: string;
@@ -76,20 +54,20 @@ export type DetailsFormValues = {
const validate = (values: DetailsFormValues) => {
const errors: DetailsFormValues = {};
- if (!values.name) {
- errors.name = "Please enter a valid Full Name";
+ if (!values.firstName) {
+ errors.firstName = "This field is required.";
}
if (!values.email || !isEmail(values.email)) {
- errors.email = "Please enter a valid Email address";
+ errors.email = "Enter a valid email address.";
}
if (!values.password || !isStrongPassword(values.password)) {
- errors.password = "Please enter a strong password";
+ errors.password = "Please enter a strong password.";
}
if (!values.verifyPassword || values.password != values.verifyPassword) {
- errors.verifyPassword = "Please reenter the password";
+ errors.verifyPassword = "Passwords don't match.";
}
if (!values.role) {
@@ -120,15 +98,35 @@ export type SetupFormProps = DetailsFormValues & {
>;
function SetupForm(props: SetupFormProps) {
- const isAirgappedInstance = isAirgapped();
const signupURL = `/api/v1/${SUPER_USER_SUBMIT_PATH}`;
const [showDetailsForm, setShowDetailsForm] = useState(true);
const formRef = useRef(null);
+ const isAirgappedFlag = isAirgapped();
+
const onSubmit = () => {
const form: HTMLFormElement = formRef.current as HTMLFormElement;
const verifyPassword: HTMLInputElement = document.querySelector(
`[name="verifyPassword"]`,
) as HTMLInputElement;
+ verifyPassword.removeAttribute("name");
+
+ const firstName: HTMLInputElement = document.querySelector(
+ `[name="firstName"]`,
+ ) as HTMLInputElement;
+
+ const lastName: HTMLInputElement = document.querySelector(
+ `[name="lastName"]`,
+ ) as HTMLInputElement;
+
+ if (firstName && lastName) {
+ const fullName = document.createElement("input");
+ fullName.type = "text";
+ fullName.name = "name";
+ fullName.style.display = "none";
+ fullName.value = `${firstName.value} ${lastName.value}`;
+ form.appendChild(fullName);
+ }
+
const roleInput = document.createElement("input");
verifyPassword.removeAttribute("name");
roleInput.type = "text";
@@ -138,10 +136,6 @@ function SetupForm(props: SetupFormProps) {
roleInput.value = props.role as string;
} else {
roleInput.value = props.role_name as string;
- const roleNameInput: HTMLInputElement = document.querySelector(
- `[name="role_name"]`,
- ) as HTMLInputElement;
- if (roleNameInput) roleNameInput.remove();
}
form.appendChild(roleInput);
const useCaseInput = document.createElement("input");
@@ -152,12 +146,20 @@ function SetupForm(props: SetupFormProps) {
useCaseInput.value = props.useCase as string;
} else {
useCaseInput.value = props.custom_useCase as string;
- const customUseCaseInput: HTMLInputElement = document.querySelector(
- `[name="custom_useCase"]`,
- ) as HTMLInputElement;
- if (customUseCaseInput) customUseCaseInput.remove();
}
form.appendChild(useCaseInput);
+ const anonymousDataInput = document.createElement("input");
+ anonymousDataInput.type = "checkbox";
+ anonymousDataInput.value = isAirgappedFlag ? "false" : "true";
+ anonymousDataInput.checked = isAirgappedFlag ? false : true;
+ anonymousDataInput.name = "allowCollectingAnonymousData";
+ anonymousDataInput.style.display = "none";
+ form.appendChild(anonymousDataInput);
+ const signupForNewsletter: HTMLInputElement = document.querySelector(
+ `[name="signupForNewsletter"]`,
+ ) as HTMLInputElement;
+ if (signupForNewsletter)
+ signupForNewsletter.value = signupForNewsletter.checked.toString();
return true;
};
@@ -191,9 +193,6 @@ function SetupForm(props: SetupFormProps) {
return (
-
-
-
diff --git a/app/client/src/pages/setup/Welcome.tsx b/app/client/src/pages/setup/Welcome.tsx
index 0aceeb8466..56d857b86e 100644
--- a/app/client/src/pages/setup/Welcome.tsx
+++ b/app/client/src/pages/setup/Welcome.tsx
@@ -1,4 +1,4 @@
-import React, { memo, useState } from "react";
+import React, { memo } from "react";
import styled from "styled-components";
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
import { useEffect } from "react";
@@ -11,49 +11,64 @@ import {
import NonSuperUserForm, { SuperUserForm } from "./GetStarted";
import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
-const LandingPageWrapper = styled.div<{ hide: boolean }>`
- width: ${(props) => props.theme.pageContentWidth}px;
+const LandingPageWrapper = styled.div`
+ width: 100%;
height: 100vh;
display: flex;
justify-content: center;
- align-items: center;
+ align-items: flex-start;
margin: 0 auto;
- opacity: ${(props) => (props.hide ? 0 : 1)};
`;
const LandingPageContent = styled.div`
width: 100%;
+ height: 100%;
display: flex;
- align-items: center;
+ align-items: start;
+ justify-content: center;
position: relative;
z-index: 100;
`;
const StyledTextBanner = styled.div`
- min-width: ${(props) => props.theme.pageContentWidth * 0.55}px;
- padding-left: 64px;
+ width: 60%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ margin-top: 6%;
`;
-const StyledBannerHeader = styled.h1`
- font-family: "Paytone One", sans-serif;
+const StyledBannerHeader = styled.div`
font-size: 72px;
margin: 0px 0px;
- color: var(--ads-v2-color-fg-emphasis-plus);
+ font-weight: 600;
+ margin-right: 1rem;
+ width: 100%;
+ text-align: center;
`;
-const StyledBannerBody = styled.p`
- font-family: "Montserrat", sans-serif;
+const StyledBannerBody = styled.div`
font-size: 24px;
margin: ${(props) => props.theme.spaces[7]}px 0px;
- width: 400px;
+ font-weight: 500;
+ margin-right: 8rem;
+ width: 100%;
+ text-align: center;
color: var(--ads-v2-color-fg);
`;
const StyledImageBanner = styled.div`
- min-width: ${(props) => props.theme.pageContentWidth * 0.45}px;
+ width: 40%;
+ display: flex;
+ justify-content: center;
+ height: 100%;
+ flex-direction: column;
+ align-items: end;
`;
-const getWelcomeImage = () => `${ASSETS_CDN_URL}/welcome-banner.svg`;
+const getWelcomeImage = () => `${ASSETS_CDN_URL}/welcome-banner-v2.svg`;
+const getAppsmithLogo = () => `${ASSETS_CDN_URL}/appsmith-logo.svg`;
type LandingPageProps = {
onGetStarted?: (role?: string, useCase?: string) => void;
@@ -62,25 +77,6 @@ type LandingPageProps = {
const WELCOME_PAGE_ANIMATION_CONTAINER = "welcome-page-animation-container";
-const includeFonts = () => {
- const preconnectGoogleapis = document.createElement("link");
- preconnectGoogleapis.rel = "preconnect";
- preconnectGoogleapis.href = "https://fonts.googleapis.com";
- document.head.appendChild(preconnectGoogleapis);
-
- const preconnectGstatic = document.createElement("link") as any;
- preconnectGstatic.rel = "preconnect";
- preconnectGstatic.href = "https://fonts.gstatic.com";
- preconnectGstatic.crossorigin = "crossorigin";
- document.head.appendChild(preconnectGstatic);
-
- const fonts = document.createElement("link");
- fonts.rel = "stylesheet";
- fonts.href =
- "https://fonts.googleapis.com/css2?family=Montserrat&family=Paytone+One&display=swap";
- document.head.appendChild(fonts);
-};
-
function Banner() {
return (
<>
@@ -91,32 +87,30 @@ function Banner() {
}
export default memo(function LandingPage(props: LandingPageProps) {
- const [fontsInjected, setFontsInjected] = useState(false);
useEffect(() => {
- includeFonts();
playWelcomeAnimation(`#${WELCOME_PAGE_ANIMATION_CONTAINER}`);
- //wait for the fonts to be loaded
- setTimeout(() => {
- setFontsInjected(true);
- }, 100);
}, []);
return (
{props.forSuperUser ? (
-
+
) : (
)}
-
+
+
)})
+
+
+
)})
+
diff --git a/app/client/src/pages/setup/common.tsx b/app/client/src/pages/setup/common.tsx
index a1d1e311f8..dd5ad75309 100644
--- a/app/client/src/pages/setup/common.tsx
+++ b/app/client/src/pages/setup/common.tsx
@@ -60,9 +60,6 @@ export const StyledLink = styled.a`
const DROPDOWN_CLASSNAME = "setup-dropdown";
export const DropdownWrapper = styled(StyledFormGroup)`
- && {
- margin-bottom: 33px;
- }
&& .cs-text {
width: 100%;
}
diff --git a/app/client/src/utils/storage.ts b/app/client/src/utils/storage.ts
index 436193d859..8cdc6f44f4 100644
--- a/app/client/src/utils/storage.ts
+++ b/app/client/src/utils/storage.ts
@@ -20,6 +20,8 @@ export const STORAGE_KEYS: {
"FIRST_TIME_USER_ONBOARDING_INTRO_MODAL_VISIBILITY",
HIDE_CONCURRENT_EDITOR_WARNING_TOAST: "HIDE_CONCURRENT_EDITOR_WARNING_TOAST",
APP_THEMING_BETA_SHOWN: "APP_THEMING_BETA_SHOWN",
+ FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY:
+ "FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY",
};
const store = localforage.createInstance({
@@ -384,3 +386,34 @@ export const setTemplateNotificationSeen = async (flag: boolean) => {
return false;
}
};
+export const getFirstTimeUserOnboardingTelemetryCalloutIsAlreadyShown =
+ async () => {
+ try {
+ const flag = await store.getItem(
+ STORAGE_KEYS.FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY,
+ );
+ return flag;
+ } catch (error) {
+ log.error(
+ "An error occurred while fetching FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY",
+ );
+ log.error(error);
+ }
+ };
+
+export const setFirstTimeUserOnboardingTelemetryCalloutVisibility = async (
+ flag: boolean,
+) => {
+ try {
+ await store.setItem(
+ STORAGE_KEYS.FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY,
+ flag,
+ );
+ return true;
+ } catch (error) {
+ log.error(
+ "An error occurred while fetching FIRST_TIME_USER_ONBOARDING_TELEMETRY_CALLOUT_VISIBILITY",
+ );
+ log.error(error);
+ }
+};