PromucFlow_constructor/app/client/src/pages/setup/SetupForm.tsx

247 lines
7.4 KiB
TypeScript
Raw Normal View History

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,
WELCOME_FORM_NAME,
WELCOME_FORM_NAME_FIELD_NAME,
WELCOME_FORM_PASSWORD_FIELD_NAME,
WELCOME_FORM_ROLE_FIELD_NAME,
WELCOME_FORM_ROLE_NAME_FIELD_NAME,
WELCOME_FORM_VERIFY_PASSWORD_FIELD_NAME,
WELCOME_FORM_CUSTOM_USECASE_FIELD_NAME,
} from "@appsmith/constants/forms";
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com> ## Description This PR upgrades Prettier to v2 + enforces TypeScript’s [`import type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax where applicable. It’s submitted as a separate PR so we can merge it easily. As a part of this PR, we reformat the codebase heavily: - add `import type` everywhere where it’s required, and - re-format the code to account for Prettier 2’s breaking changes: https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes This PR is submitted against `release` to make sure all new code by team members will adhere to new formatting standards, and we’ll have fewer conflicts when merging `bundle-optimizations` into `release`. (I’ll merge `release` back into `bundle-optimizations` once this PR is merged.) ### Why is this needed? This PR is needed because, for the Lodash optimization from https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3, we need to use `import type`. Otherwise, `babel-plugin-lodash` complains that `LoDashStatic` is not a lodash function. However, just using `import type` in the current codebase will give you this: <img width="962" alt="Screenshot 2023-03-08 at 17 45 59" src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png"> That’s because Prettier 1 can’t parse `import type` at all. To parse it, we need to upgrade to Prettier 2. ### Why enforce `import type`? Apart from just enabling `import type` support, this PR enforces specifying `import type` everywhere it’s needed. (Developers will get immediate TypeScript and ESLint errors when they forget to do so.) I’m doing this because I believe `import type` improves DX and makes refactorings easier. Let’s say you had a few imports like below. Can you tell which of these imports will increase the bundle size? (Tip: it’s not all of them!) ```ts // app/client/src/workers/Linting/utils.ts import { Position } from "codemirror"; import { LintError as JSHintError, LintOptions } from "jshint"; import { get, isEmpty, isNumber, keys, last, set } from "lodash"; ``` It’s pretty hard, right? What about now? ```ts // app/client/src/workers/Linting/utils.ts import type { Position } from "codemirror"; import type { LintError as JSHintError, LintOptions } from "jshint"; import { get, isEmpty, isNumber, keys, last, set } from "lodash"; ``` Now, it’s clear that only `lodash` will be bundled. This helps developers to see which imports are problematic, but it _also_ helps with refactorings. Now, if you want to see where `codemirror` is bundled, you can just grep for `import \{.*\} from "codemirror"` – and you won’t get any type-only imports. This also helps (some) bundlers. Upon transpiling, TypeScript erases type-only imports completely. In some environment (not ours), this makes the bundle smaller, as the bundler doesn’t need to bundle type-only imports anymore. ## Type of change - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? This was tested to not break the build. ### 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 - [x] 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 - [x] 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: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test --------- Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
import type { FormErrors, InjectedFormProps } from "redux-form";
import { formValueSelector, getFormSyncErrors, reduxForm } from "redux-form";
import { isEmail, isStrongPassword } from "utils/formhelpers";
chore: upgrade to prettier v2 + enforce import types (#21013)Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com> ## Description This PR upgrades Prettier to v2 + enforces TypeScript’s [`import type`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax where applicable. It’s submitted as a separate PR so we can merge it easily. As a part of this PR, we reformat the codebase heavily: - add `import type` everywhere where it’s required, and - re-format the code to account for Prettier 2’s breaking changes: https://prettier.io/blog/2020/03/21/2.0.0.html#breaking-changes This PR is submitted against `release` to make sure all new code by team members will adhere to new formatting standards, and we’ll have fewer conflicts when merging `bundle-optimizations` into `release`. (I’ll merge `release` back into `bundle-optimizations` once this PR is merged.) ### Why is this needed? This PR is needed because, for the Lodash optimization from https://github.com/appsmithorg/appsmith/commit/7cbb12af886621256224be0c93e6a465dd710ad3, we need to use `import type`. Otherwise, `babel-plugin-lodash` complains that `LoDashStatic` is not a lodash function. However, just using `import type` in the current codebase will give you this: <img width="962" alt="Screenshot 2023-03-08 at 17 45 59" src="https://user-images.githubusercontent.com/2953267/223775744-407afa0c-e8b9-44a1-90f9-b879348da57f.png"> That’s because Prettier 1 can’t parse `import type` at all. To parse it, we need to upgrade to Prettier 2. ### Why enforce `import type`? Apart from just enabling `import type` support, this PR enforces specifying `import type` everywhere it’s needed. (Developers will get immediate TypeScript and ESLint errors when they forget to do so.) I’m doing this because I believe `import type` improves DX and makes refactorings easier. Let’s say you had a few imports like below. Can you tell which of these imports will increase the bundle size? (Tip: it’s not all of them!) ```ts // app/client/src/workers/Linting/utils.ts import { Position } from "codemirror"; import { LintError as JSHintError, LintOptions } from "jshint"; import { get, isEmpty, isNumber, keys, last, set } from "lodash"; ``` It’s pretty hard, right? What about now? ```ts // app/client/src/workers/Linting/utils.ts import type { Position } from "codemirror"; import type { LintError as JSHintError, LintOptions } from "jshint"; import { get, isEmpty, isNumber, keys, last, set } from "lodash"; ``` Now, it’s clear that only `lodash` will be bundled. This helps developers to see which imports are problematic, but it _also_ helps with refactorings. Now, if you want to see where `codemirror` is bundled, you can just grep for `import \{.*\} from "codemirror"` – and you won’t get any type-only imports. This also helps (some) bundlers. Upon transpiling, TypeScript erases type-only imports completely. In some environment (not ours), this makes the bundle smaller, as the bundler doesn’t need to bundle type-only imports anymore. ## Type of change - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? This was tested to not break the build. ### 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 - [x] 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 - [x] 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: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test --------- Co-authored-by: Satish Gandham <hello@satishgandham.com> Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
2023-03-16 11:41:47 +00:00
import type { AppState } from "@appsmith/reducers";
import { SUPER_USER_SUBMIT_PATH } from "@appsmith/constants/ApiConstants";
import { useState } from "react";
fix: hide telemetry form for airgap instance (#22546) ## Description - Since telemetry and newsletters are by default disabled in airgap we don't need it for airgapped instances. Fixes #22369 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? - Manual ### 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 - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
2023-04-20 09:27:41 +00:00
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
import { noop } from "utils/AppsmithUtils";
const PageWrapper = styled.div`
width: 100%;
display: flex;
justify-content: center;
height: 100vh;
overflow: auto;
position: relative;
z-index: 100;
`;
const SetupFormContainer = styled.div`
padding: 120px 42px 0px 0px;
`;
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;
email?: string;
password?: string;
verifyPassword?: string;
role?: string;
useCase?: string;
custom_useCase?: string;
role_name?: string;
};
const validate = (values: DetailsFormValues) => {
const errors: DetailsFormValues = {};
if (!values.name) {
errors.name = "Please enter a valid Full Name";
}
if (!values.email || !isEmail(values.email)) {
errors.email = "Please enter a valid Email address";
}
if (!values.password || !isStrongPassword(values.password)) {
errors.password = "Please enter a strong password";
}
if (!values.verifyPassword || values.password != values.verifyPassword) {
errors.verifyPassword = "Please reenter the password";
}
if (!values.role) {
errors.role = "Please select a role";
}
if (values.role == "other" && !values.role_name) {
errors.role_name = "Please enter a role";
}
if (!values.useCase) {
errors.useCase = "Please select a use case";
}
if (values.useCase === "other" && !values.custom_useCase)
errors.custom_useCase = "Please enter a use case";
return errors;
};
export type SetupFormProps = DetailsFormValues & {
formSyncErrors?: FormErrors<string, string>;
} & InjectedFormProps<
DetailsFormValues,
{
formSyncErrors?: FormErrors<string, string>;
}
>;
function SetupForm(props: SetupFormProps) {
fix: hide telemetry form for airgap instance (#22546) ## Description - Since telemetry and newsletters are by default disabled in airgap we don't need it for airgapped instances. Fixes #22369 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? - Manual ### 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 - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
2023-04-20 09:27:41 +00:00
const isAirgappedInstance = isAirgapped();
const signupURL = `/api/v1/${SUPER_USER_SUBMIT_PATH}`;
const [showDetailsForm, setShowDetailsForm] = useState(true);
const formRef = useRef<HTMLFormElement>(null);
const onSubmit = () => {
const form: HTMLFormElement = formRef.current as HTMLFormElement;
const verifyPassword: HTMLInputElement = document.querySelector(
`[name="verifyPassword"]`,
) as HTMLInputElement;
const roleInput = document.createElement("input");
verifyPassword.removeAttribute("name");
roleInput.type = "text";
roleInput.name = "role";
roleInput.style.display = "none";
if (props.role !== "other") {
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");
useCaseInput.type = "text";
useCaseInput.name = "useCase";
useCaseInput.style.display = "none";
if (props.useCase !== "other") {
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);
return true;
};
const onKeyDown = (event: React.KeyboardEvent<HTMLFormElement>) => {
if (event.key === "Enter") {
if (props.valid) {
if (showDetailsForm) {
// If we are on the details page we do not want to submit the form
// instead we move the user to the next page
event.preventDefault();
onNext();
}
} else {
// The fields to be marked as touched so that we can display the errors
const toTouch = [];
// We fetch the fields which are invalid
for (const key in props.formSyncErrors) {
props.formSyncErrors.hasOwnProperty(key) && toTouch.push(key);
}
props.touch(...toTouch);
// prevent submitting the form on enter if the values are invalid
event.preventDefault();
}
}
};
const onNext = () => {
setShowDetailsForm(false);
};
return (
<PageWrapper>
<SetupFormContainer>
<LogoContainer>
<AppsmithLogoImg alt="Appsmith logo" src={AppsmithLogo} />
</LogoContainer>
<form
action={signupURL}
data-testid="super-user-form"
id="super-user-form"
method="POST"
onKeyDown={onKeyDown}
onSubmit={onSubmit}
ref={formRef}
>
<SetupStep active={showDetailsForm}>
fix: hide telemetry form for airgap instance (#22546) ## Description - Since telemetry and newsletters are by default disabled in airgap we don't need it for airgapped instances. Fixes #22369 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? - Manual ### 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 - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
2023-04-20 09:27:41 +00:00
<DetailsForm
{...props}
onNext={!isAirgappedInstance ? onNext : () => noop}
/>
</SetupStep>
fix: hide telemetry form for airgap instance (#22546) ## Description - Since telemetry and newsletters are by default disabled in airgap we don't need it for airgapped instances. Fixes #22369 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - Chore (housekeeping or task changes that don't impact user perception) ## How Has This Been Tested? - Manual ### 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 - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
2023-04-20 09:27:41 +00:00
{!isAirgappedInstance && (
<SetupStep active={!showDetailsForm}>
<DataCollectionForm />
<NewsletterForm />
</SetupStep>
)}
</form>
<SpaceFiller />
</SetupFormContainer>
</PageWrapper>
);
}
const selector = formValueSelector(WELCOME_FORM_NAME);
export default connect((state: AppState) => {
return {
name: selector(state, WELCOME_FORM_NAME_FIELD_NAME),
email: selector(state, WELCOME_FORM_EMAIL_FIELD_NAME),
password: selector(state, WELCOME_FORM_PASSWORD_FIELD_NAME),
verify_password: selector(state, WELCOME_FORM_VERIFY_PASSWORD_FIELD_NAME),
role: selector(state, WELCOME_FORM_ROLE_FIELD_NAME),
role_name: selector(state, WELCOME_FORM_ROLE_NAME_FIELD_NAME),
useCase: selector(state, WELCOME_FORM_USECASE_FIELD_NAME),
custom_useCase: selector(state, WELCOME_FORM_CUSTOM_USECASE_FIELD_NAME),
formSyncErrors: getFormSyncErrors(WELCOME_FORM_NAME)(state),
};
}, null)(
reduxForm<DetailsFormValues, { formSyncErrors?: FormErrors<string, string> }>(
{
validate,
form: WELCOME_FORM_NAME,
touchOnBlur: true,
},
)(SetupForm),
);