Web: Client: Data Import: add addEmail dialog

This commit is contained in:
Vladimir Khvan 2024-07-03 17:16:41 +05:00
parent db00964816
commit b01b9915ca
4 changed files with 203 additions and 64 deletions

View File

@ -10,6 +10,7 @@
"AccountsWithoutEmails": "We found <1>{{users}} users</1> without emails. You can fill their emails or continue without this action.",
"AccountsWithoutEmailsNextStep": "We found <1>{{users}} users</1> without emails. You can add necessary data to their accounts on the next step.",
"AddAllowedIP": "Add allowed IP address",
"AddEmail": "Add e-mail",
"AddEmails": "Add emails to incomplete accounts",
"AddEmailsDescription": "Check list of unimported users to import into {{organizationName}} {{productName}}.",
"AddEmailsWarning": "You don't have users with emails. Please proceed to the next step to add them.",

View File

@ -0,0 +1,119 @@
// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import styled from "styled-components";
import { useTranslation } from "react-i18next";
import {
ModalDialog,
ModalDialogType,
} from "@docspace/shared/components/modal-dialog";
import { Button, ButtonSize } from "@docspace/shared/components/button";
import { EmailInput } from "@docspace/shared/components/email-input";
import { InputType } from "@docspace/shared/components/text-input";
import { TValidate } from "@docspace/shared/components/email-input/EmailInput.types";
import { Text } from "@docspace/shared/components/text";
import ModalDialogContainer from "../ModalDialogContainer";
const DialogBodyWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 16px;
`;
interface EmailChangeDialogProps {
visible: boolean;
onClose: () => void;
tempEmail: string;
handleEmailChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
onValidateEmail: (res: TValidate) => {
isValid: boolean;
errors: string[];
};
hasError: boolean;
checkEmailValidity: () => void;
handleSave: () => void;
displayName: string;
}
const EmailChangeDialog = ({
visible,
onClose,
tempEmail,
handleEmailChange,
onValidateEmail,
hasError,
checkEmailValidity,
handleSave,
displayName,
}: EmailChangeDialogProps) => {
const { t } = useTranslation(["Settings", "SMTPSettings", "Common"]);
return (
<ModalDialogContainer
visible={visible}
onClose={onClose}
displayType={ModalDialogType.modal}
>
<ModalDialog.Header>{t("AddEmail")}</ModalDialog.Header>
<ModalDialog.Body>
<DialogBodyWrapper>
<Text>{displayName}</Text>
<EmailInput
placeholder={t("SMTPSettings:EnterEmail")}
className="import-email-input"
value={tempEmail}
onChange={handleEmailChange}
type={InputType.email}
onValidateInput={onValidateEmail}
hasError={hasError}
onBlur={checkEmailValidity}
isAutoFocussed
scale
/>
</DialogBodyWrapper>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
label={t("Common:SaveButton")}
size={ButtonSize.normal}
scale
primary
onClick={handleSave}
isDisabled={hasError}
/>
<Button
label={t("Common:CancelButton")}
size={ButtonSize.normal}
scale
onClick={onClose}
/>
</ModalDialog.Footer>
</ModalDialogContainer>
);
};
export default EmailChangeDialog;

View File

@ -37,12 +37,15 @@ import { Button } from "@docspace/shared/components/button";
import { TValidate } from "@docspace/shared/components/email-input/EmailInput.types";
import { InputType } from "@docspace/shared/components/text-input";
import { isMobile } from "@docspace/shared/utils";
import EditSvg from "PUBLIC_DIR/images/access.edit.react.svg";
import CrossSvg from "PUBLIC_DIR/images/cross.edit.react.svg";
import CheckSvg from "PUBLIC_DIR/images/check.edit.react.svg";
import { Base } from "@docspace/shared/themes";
import EmailChangeDialog from "SRC_DIR/components/dialogs/EmailChangeDialog";
import {
AddEmailRowContentProps,
InjectedAddEmailRowContentProps,
@ -181,26 +184,40 @@ const UsersRowContent = (props: AddEmailRowContentProps) => {
</Text>
</div>
{isEmailOpen ? (
<EmailInputWrapper ref={emailInputRef}>
<EmailInput
placeholder={t("Settings:NoEmail")}
className="import-email-input"
value={tempEmail}
onChange={handleEmailChange}
type={InputType.email}
onValidateInput={onValidateEmail}
isMobile() ? (
<EmailChangeDialog
visible={isEmailOpen}
onClose={clearEmail}
tempEmail={tempEmail}
handleEmailChange={handleEmailChange}
onValidateEmail={onValidateEmail}
hasError={hasError}
onBlur={checkEmailValidity}
isAutoFocussed
checkEmailValidity={checkEmailValidity}
handleSave={handleSaveClick}
displayName={displayName}
/>
) : (
<EmailInputWrapper ref={emailInputRef}>
<EmailInput
placeholder={t("SMTPSettings:EnterEmail")}
className="import-email-input"
value={tempEmail}
onChange={handleEmailChange}
type={InputType.email}
onValidateInput={onValidateEmail}
hasError={hasError}
onBlur={checkEmailValidity}
isAutoFocussed
/>
<DecisionButton
label=""
icon={<CheckSvg />}
onClick={handleSaveClick}
/>
<DecisionButton label="" icon={<CrossSvg />} onClick={clearEmail} />
</EmailInputWrapper>
<DecisionButton
label=""
icon={<CheckSvg />}
onClick={handleSaveClick}
/>
<DecisionButton label="" icon={<CrossSvg />} onClick={clearEmail} />
</EmailInputWrapper>
)
) : (
<span onClick={openEmail} className="user-email" ref={emailTextRef}>
<EditSvg />

View File

@ -31,6 +31,7 @@ import { SearchInput } from "@docspace/shared/components/search-input";
import { Text } from "@docspace/shared/components/text";
import { InputSize } from "@docspace/shared/components/text-input";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import AccountsTable from "./AccountsTable";
import AccountsPaging from "../../sub-components/AccountsPaging";
@ -43,7 +44,6 @@ import { parseQuota } from "../../utils";
import { AddEmailsStepProps, InjectedAddEmailsStepProps } from "../../types";
import { MigrationButtons } from "../../sub-components/MigrationButtons";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
const PAGE_SIZE = 25;
const REFRESH_TIMEOUT = 100;
@ -211,50 +211,52 @@ const AddEmailsStep = (props: AddEmailsStepProps) => {
);
};
export default inject<TStore>(({ importAccountsStore, currentQuotaStore, dialogsStore }) => {
const {
incrementStep,
decrementStep,
searchValue,
setSearchValue,
users,
setResultUsers,
areCheckedUsersEmpty,
checkedUsers,
withEmailUsers,
export default inject<TStore>(
({ importAccountsStore, currentQuotaStore, dialogsStore }) => {
const {
incrementStep,
decrementStep,
searchValue,
setSearchValue,
users,
setResultUsers,
areCheckedUsersEmpty,
checkedUsers,
withEmailUsers,
cancelMigration,
clearCheckedAccounts,
setStep,
setWorkspace,
setMigratingWorkspace,
setMigrationPhase,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
cancelMigration,
clearCheckedAccounts,
setStep,
setWorkspace,
setMigratingWorkspace,
setMigrationPhase,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
const { cancelUploadDialogVisible, setCancelUploadDialogVisible } =
dialogsStore;
return {
incrementStep,
decrementStep,
searchValue,
setSearchValue,
users,
setResultUsers,
areCheckedUsersEmpty,
checkedUsers,
withEmailUsers,
return {
incrementStep,
decrementStep,
searchValue,
setSearchValue,
users,
setResultUsers,
areCheckedUsersEmpty,
checkedUsers,
withEmailUsers,
cancelMigration,
clearCheckedAccounts,
setStep,
setWorkspace,
setMigratingWorkspace,
setMigrationPhase,
cancelMigration,
clearCheckedAccounts,
setStep,
setWorkspace,
setMigratingWorkspace,
setMigrationPhase,
quotaCharacteristics,
quotaCharacteristics,
cancelUploadDialogVisible,
setCancelUploadDialogVisible,
};
})(observer(AddEmailsStep));
cancelUploadDialogVisible,
setCancelUploadDialogVisible,
};
},
)(observer(AddEmailsStep));