Web: Client: Data Import: translate AddUsersStep to ts
This commit is contained in:
parent
bb285bcb80
commit
77b8f4f024
@ -31,7 +31,8 @@ import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
|
||||
import SelectFileStep from "../../components/SelectFileStep";
|
||||
import SelectUsersStep from "../../components/SelectUsersStep";
|
||||
import AddEmailsStep from "./AddEmailsStep";
|
||||
import AddEmailsStep from "../../components/AddEmailsStep";
|
||||
|
||||
import SelectUsersTypeStep from "./SelectUsersTypeStep";
|
||||
import ImportStep from "./ImportStep";
|
||||
import ImportProcessingStep from "./ImportProcessingStep";
|
||||
@ -68,13 +69,7 @@ export const getStepsData = (
|
||||
{
|
||||
title: t("Settings:AddEmails"),
|
||||
description: t("Settings:AddEmailsDescription"),
|
||||
component: (
|
||||
<AddEmailsStep
|
||||
t={t}
|
||||
incrementStep={incrementStep}
|
||||
decrementStep={decrementStep}
|
||||
/>
|
||||
),
|
||||
component: <AddEmailsStep t={t} />,
|
||||
},
|
||||
{
|
||||
title: t("Settings:SelectUserTypes"),
|
||||
|
@ -27,10 +27,10 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { Row } from "@docspace/shared/components/row";
|
||||
import UsersRowContent from "./UsersRowContent";
|
||||
import { AddEmailUsersRowProps } from "../../../../types";
|
||||
|
||||
const UsersRow = (props) => {
|
||||
const UsersRow = (props: AddEmailUsersRowProps) => {
|
||||
const {
|
||||
t,
|
||||
data,
|
||||
sectionWidth,
|
||||
isChecked,
|
||||
@ -39,32 +39,31 @@ const UsersRow = (props) => {
|
||||
setOpenedEmailKey,
|
||||
} = props;
|
||||
|
||||
const emailInputRef = useRef();
|
||||
const emailTextRef = useRef();
|
||||
const emailInputRef = useRef<HTMLDivElement>(null);
|
||||
const emailTextRef = useRef<HTMLSpanElement>(null);
|
||||
|
||||
const [isPrevEmailValid, setIsPrevEmailValid] = useState(
|
||||
data.email?.length > 0,
|
||||
);
|
||||
|
||||
const handleAccountToggle = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
!isPrevEmailValid ||
|
||||
emailInputRef.current?.contains(e.target) ||
|
||||
emailTextRef.current?.contains(e.target) ||
|
||||
const handleAccountToggle = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (
|
||||
isPrevEmailValid &&
|
||||
!emailInputRef.current?.contains(e.target) &&
|
||||
!emailTextRef.current?.contains(e.target)
|
||||
) {
|
||||
toggleAccount();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Row
|
||||
sectionWidth={sectionWidth}
|
||||
checked={isChecked}
|
||||
onClick={handleAccountToggle}
|
||||
onRowClick={handleAccountToggle}
|
||||
onSelect={toggleAccount}
|
||||
isDisabled={!isPrevEmailValid}
|
||||
>
|
||||
<UsersRowContent
|
||||
t={t}
|
||||
id={data.key}
|
||||
sectionWidth={sectionWidth}
|
||||
displayName={data.displayName}
|
||||
|
@ -34,6 +34,8 @@ import { RowContent } from "@docspace/shared/components/row-content";
|
||||
|
||||
import { EmailInput } from "@docspace/shared/components/email-input";
|
||||
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 EditSvg from "PUBLIC_DIR/images/access.edit.react.svg";
|
||||
import CrossSvg from "PUBLIC_DIR/images/cross.edit.react.svg";
|
||||
@ -41,6 +43,11 @@ import CheckSvg from "PUBLIC_DIR/images/check.edit.react.svg";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
import {
|
||||
AddEmailRowContentProps,
|
||||
InjectedAddEmailRowContentProps,
|
||||
} from "../../../../types";
|
||||
|
||||
const EmailInputWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@ -49,6 +56,7 @@ const EmailInputWrapper = styled.div`
|
||||
const DecisionButton = styled(Button)`
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
`;
|
||||
|
||||
DecisionButton.defaultProps = { theme: Base };
|
||||
@ -85,21 +93,22 @@ const StyledRowContent = styled(RowContent)`
|
||||
}
|
||||
`;
|
||||
|
||||
const UsersRowContent = ({
|
||||
sectionWidth,
|
||||
displayName,
|
||||
email,
|
||||
id,
|
||||
emailInputRef,
|
||||
emailTextRef,
|
||||
const UsersRowContent = (props: AddEmailRowContentProps) => {
|
||||
const {
|
||||
id,
|
||||
sectionWidth,
|
||||
displayName,
|
||||
email,
|
||||
emailInputRef,
|
||||
emailTextRef,
|
||||
isChecked,
|
||||
isEmailOpen,
|
||||
setOpenedEmailKey,
|
||||
toggleAccount,
|
||||
|
||||
toggleAccount,
|
||||
changeEmail,
|
||||
isChecked,
|
||||
isEmailOpen,
|
||||
setOpenedEmailKey,
|
||||
setIsPrevEmailValid,
|
||||
}) => {
|
||||
changeEmail,
|
||||
setIsPrevEmailValid,
|
||||
} = props as InjectedAddEmailRowContentProps;
|
||||
const { t, ready } = useTranslation(["SMTPSettings", "Settings", "Common"]);
|
||||
|
||||
const [prevEmail, setPrevEmail] = useState(email);
|
||||
@ -108,14 +117,16 @@ const UsersRowContent = ({
|
||||
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
const handleEmailChange = (e) => {
|
||||
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTempEmail(e.target.value);
|
||||
hasError && setHasError(false);
|
||||
if (hasError) {
|
||||
setHasError(false);
|
||||
}
|
||||
};
|
||||
|
||||
const clearEmail = () => {
|
||||
setTempEmail(prevEmail);
|
||||
setOpenedEmailKey(null);
|
||||
setOpenedEmailKey("");
|
||||
setHasError(false);
|
||||
};
|
||||
|
||||
@ -124,31 +135,40 @@ const UsersRowContent = ({
|
||||
const handleSaveEmail = () => {
|
||||
setPrevEmail(tempEmail);
|
||||
changeEmail(id, tempEmail);
|
||||
setOpenedEmailKey(null);
|
||||
setOpenedEmailKey("");
|
||||
setIsPrevEmailValid(true);
|
||||
!isChecked && toggleAccount();
|
||||
if (!isChecked) {
|
||||
toggleAccount();
|
||||
}
|
||||
};
|
||||
|
||||
const onValidateEmail = (res) => {
|
||||
const onValidateEmail = (res: TValidate) => {
|
||||
setIsEmailValid(res.isValid);
|
||||
return { isValid: res.isValid, errors: res.errors || [] };
|
||||
};
|
||||
|
||||
const handleSaveClick = () => {
|
||||
isEmailValid ? handleSaveEmail() : setHasError(true);
|
||||
if (isEmailValid) {
|
||||
handleSaveEmail();
|
||||
} else {
|
||||
setHasError(true);
|
||||
}
|
||||
};
|
||||
|
||||
const checkEmailValidity = () => {
|
||||
!isEmailValid && setHasError(true);
|
||||
if (!isEmailValid) {
|
||||
setHasError(true);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
isEmailOpen ||
|
||||
prevEmail === tempEmail ||
|
||||
setTempEmail(prevEmail) ||
|
||||
if (!isEmailOpen && prevEmail !== tempEmail) {
|
||||
setTempEmail(prevEmail);
|
||||
setHasError(false);
|
||||
}, [isEmailOpen]);
|
||||
}
|
||||
}, [isEmailOpen, prevEmail, tempEmail]);
|
||||
|
||||
if (!ready) return <></>;
|
||||
if (!ready) return;
|
||||
|
||||
return (
|
||||
<StyledRowContent sectionWidth={sectionWidth}>
|
||||
@ -167,15 +187,19 @@ const UsersRowContent = ({
|
||||
className="import-email-input"
|
||||
value={tempEmail}
|
||||
onChange={handleEmailChange}
|
||||
type="email"
|
||||
type={InputType.email}
|
||||
onValidateInput={onValidateEmail}
|
||||
hasError={hasError}
|
||||
onBlur={checkEmailValidity}
|
||||
isAutoFocussed
|
||||
/>
|
||||
|
||||
<DecisionButton icon={<CheckSvg />} onClick={handleSaveClick} />
|
||||
<DecisionButton icon={<CrossSvg />} onClick={clearEmail} />
|
||||
<DecisionButton
|
||||
label=""
|
||||
icon={<CheckSvg />}
|
||||
onClick={handleSaveClick}
|
||||
/>
|
||||
<DecisionButton label="" icon={<CrossSvg />} onClick={clearEmail} />
|
||||
</EmailInputWrapper>
|
||||
) : (
|
||||
<span onClick={openEmail} className="user-email" ref={emailTextRef}>
|
||||
@ -186,7 +210,7 @@ const UsersRowContent = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ importAccountsStore }) => {
|
||||
export default inject<TStore>(({ importAccountsStore }) => {
|
||||
const { changeEmail } = importAccountsStore;
|
||||
|
||||
return {
|
||||
|
@ -30,9 +30,11 @@ import { tablet } from "@docspace/shared/utils/device";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { RowContainer } from "@docspace/shared/components/row-container";
|
||||
import UsersRow from "./UsersRow";
|
||||
import { Row } from "@docspace/shared/components/row";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { TEnhancedMigrationUser } from "@docspace/shared/api/settings/types";
|
||||
import UsersRow from "./UsersRow";
|
||||
import { AddEmailRowProps, RowViewProps } from "../../../../types";
|
||||
|
||||
const StyledRow = styled(Row)`
|
||||
box-sizing: border-box;
|
||||
@ -48,41 +50,43 @@ const StyledRow = styled(Row)`
|
||||
|
||||
const checkedAccountType = "withoutEmail";
|
||||
|
||||
const RowView = (props) => {
|
||||
const RowView = (props: RowViewProps) => {
|
||||
const {
|
||||
t,
|
||||
sectionWidth,
|
||||
accountsData,
|
||||
|
||||
users,
|
||||
checkedUsers,
|
||||
toggleAccount,
|
||||
toggleAllAccounts,
|
||||
isAccountChecked,
|
||||
} = props;
|
||||
} = props as AddEmailRowProps;
|
||||
|
||||
const [openedEmailKey, setOpenedEmailKey] = useState(null);
|
||||
const [openedEmailKey, setOpenedEmailKey] = useState("");
|
||||
|
||||
const usersWithFilledEmails = users.withoutEmail.filter(
|
||||
(user) => user.email && user.email.length > 0,
|
||||
);
|
||||
|
||||
const toggleAll = (isChecked) =>
|
||||
const toggleAll = (isChecked: boolean) =>
|
||||
toggleAllAccounts(isChecked, usersWithFilledEmails, checkedAccountType);
|
||||
|
||||
const handleToggle = (user) => toggleAccount(user, checkedAccountType);
|
||||
const handleToggle = (user: TEnhancedMigrationUser) =>
|
||||
toggleAccount(user, checkedAccountType);
|
||||
|
||||
const isIndeterminate =
|
||||
checkedUsers.withoutEmail.length > 0 &&
|
||||
checkedUsers.withoutEmail.length !== usersWithFilledEmails.length;
|
||||
|
||||
const isChecked =
|
||||
usersWithFilledEmails.length > 0 &&
|
||||
checkedUsers.withoutEmail.length === usersWithFilledEmails.length;
|
||||
|
||||
return (
|
||||
<RowContainer useReactWindow={false}>
|
||||
<StyledRow
|
||||
sectionWidth={sectionWidth}
|
||||
checked={
|
||||
usersWithFilledEmails.length > 0 &&
|
||||
checkedUsers.withoutEmail.length === usersWithFilledEmails.length
|
||||
}
|
||||
checked={isChecked}
|
||||
onSelect={toggleAll}
|
||||
indeterminate={isIndeterminate}
|
||||
isDisabled={usersWithFilledEmails.length === 0}
|
||||
@ -107,7 +111,7 @@ const RowView = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ importAccountsStore }) => {
|
||||
export default inject<TStore>(({ importAccountsStore }) => {
|
||||
const {
|
||||
users,
|
||||
checkedUsers,
|
||||
|
@ -27,31 +27,29 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { TableHeader } from "@docspace/shared/components/table";
|
||||
import { TableHeader, TTableColumn } from "@docspace/shared/components/table";
|
||||
|
||||
import { UsersTableHeaderProps } from "../../../../types";
|
||||
|
||||
const TABLE_VERSION = "6";
|
||||
const TABLE_COLUMNS = `nextcloudThirdColumns_ver-${TABLE_VERSION}`;
|
||||
|
||||
const getColumns = (defaultColumns, userId) => {
|
||||
const getColumns = (defaultColumns: TTableColumn[], userId?: string) => {
|
||||
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
|
||||
const columns = [];
|
||||
|
||||
if (storageColumns) {
|
||||
const splitColumns = storageColumns.split(",");
|
||||
const splitColumns = storageColumns?.split(",");
|
||||
|
||||
for (let col of defaultColumns) {
|
||||
const column = splitColumns.find((key) => key === col.key);
|
||||
column ? (col.enable = true) : (col.enable = false);
|
||||
|
||||
columns.push(col);
|
||||
}
|
||||
return columns;
|
||||
} else {
|
||||
return defaultColumns;
|
||||
return defaultColumns.map((col) => ({
|
||||
...col,
|
||||
enable: splitColumns.includes(col.key),
|
||||
}));
|
||||
}
|
||||
|
||||
return defaultColumns;
|
||||
};
|
||||
|
||||
const UsersTableHeader = (props) => {
|
||||
const UsersTableHeader = (props: UsersTableHeaderProps) => {
|
||||
const {
|
||||
t,
|
||||
userId,
|
||||
@ -59,13 +57,39 @@ const UsersTableHeader = (props) => {
|
||||
tableRef,
|
||||
columnStorageName,
|
||||
columnInfoPanelStorageName,
|
||||
setHideColumns,
|
||||
isIndeterminate,
|
||||
isChecked,
|
||||
toggleAll,
|
||||
} = props;
|
||||
|
||||
const defaultColumns = [
|
||||
const [columns, setColumns] = useState<TTableColumn[]>([
|
||||
{
|
||||
key: "Name",
|
||||
title: t("Common:Name"),
|
||||
resizable: true,
|
||||
enable: true,
|
||||
default: true,
|
||||
active: true,
|
||||
minWidth: 180,
|
||||
},
|
||||
]);
|
||||
|
||||
function onColumnChange(key: string) {
|
||||
const columnIndex = columns.findIndex((c) => c.key === key);
|
||||
|
||||
if (columnIndex === -1) return;
|
||||
|
||||
setColumns((prevColumns: TTableColumn[]) =>
|
||||
prevColumns.map((item, index) =>
|
||||
index === columnIndex ? { ...item, enable: !item.enable } : item,
|
||||
),
|
||||
);
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
localStorage.setItem(`${TABLE_COLUMNS}=${userId}`, tableColumns.toString());
|
||||
}
|
||||
|
||||
const defaultColumns: TTableColumn[] = [
|
||||
{
|
||||
key: "Name",
|
||||
title: t("Common:Name"),
|
||||
@ -90,46 +114,27 @@ const UsersTableHeader = (props) => {
|
||||
},
|
||||
];
|
||||
|
||||
const [columns, setColumns] = useState(getColumns(defaultColumns, userId));
|
||||
|
||||
function onColumnChange(key, e) {
|
||||
const columnIndex = columns.findIndex((c) => c.key === key);
|
||||
|
||||
if (columnIndex === -1) return;
|
||||
|
||||
setColumns((prevColumns) =>
|
||||
prevColumns.map((item, index) =>
|
||||
index === columnIndex ? { ...item, enable: !item.enable } : item,
|
||||
),
|
||||
);
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
localStorage.setItem(`${TABLE_COLUMNS}=${userId}`, tableColumns);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(getColumns(defaultColumns));
|
||||
setColumns(getColumns(defaultColumns, userId));
|
||||
}, [isIndeterminate, isChecked]);
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
checkboxSize="48px"
|
||||
containerRef={tableRef}
|
||||
containerRef={tableRef as { current: HTMLDivElement }}
|
||||
columns={columns}
|
||||
columnStorageName={columnStorageName}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
sectionWidth={sectionWidth}
|
||||
checkboxMargin="12px"
|
||||
showSettings={false}
|
||||
useReactWindow
|
||||
setHideColumns={setHideColumns}
|
||||
infoPanelVisible={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ userStore }) => {
|
||||
export default inject<TStore>(({ userStore }) => {
|
||||
const userId = userStore.user?.id;
|
||||
return {
|
||||
userId: userStore.user.id,
|
||||
userId,
|
||||
};
|
||||
})(observer(UsersTableHeader));
|
||||
|
@ -29,8 +29,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { TableRow } from "@docspace/shared/components/table";
|
||||
import { TableCell } from "@docspace/shared/components/table";
|
||||
import { TableRow, TableCell } from "@docspace/shared/components/table";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
@ -43,6 +42,13 @@ import CheckSvg from "PUBLIC_DIR/images/check.edit.react.svg";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
import { InputType } from "@docspace/shared/components/text-input";
|
||||
import { TValidate } from "@docspace/shared/components/email-input/EmailInput.types";
|
||||
import {
|
||||
AddEmailTableRowProps,
|
||||
InjectedAddEmailTableRowProps,
|
||||
} from "../../../../types";
|
||||
|
||||
const EmailInputWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@ -81,16 +87,19 @@ const DecisionButton = styled(Button)`
|
||||
|
||||
DecisionButton.defaultProps = { theme: Base };
|
||||
|
||||
const UsersTableRow = ({
|
||||
displayName,
|
||||
isChecked,
|
||||
toggleAccount,
|
||||
email,
|
||||
id,
|
||||
changeEmail,
|
||||
isEmailOpen,
|
||||
setOpenedEmailKey,
|
||||
}) => {
|
||||
const UsersTableRow = (props: AddEmailTableRowProps) => {
|
||||
const {
|
||||
displayName,
|
||||
email,
|
||||
isChecked,
|
||||
toggleAccount,
|
||||
|
||||
id,
|
||||
changeEmail,
|
||||
isEmailOpen,
|
||||
setOpenedEmailKey,
|
||||
} = props as InjectedAddEmailTableRowProps;
|
||||
|
||||
const { t, ready } = useTranslation(["SMTPSettings", "Settings", "Common"]);
|
||||
|
||||
const [prevEmail, setPrevEmail] = useState(email);
|
||||
@ -100,17 +109,19 @@ const UsersTableRow = ({
|
||||
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
const emailInputRef = useRef();
|
||||
const emailTextRef = useRef();
|
||||
const emailInputRef = useRef<HTMLDivElement>(null);
|
||||
const emailTextRef = useRef<HTMLSpanElement>(null);
|
||||
|
||||
const handleEmailChange = (e) => {
|
||||
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTempEmail(e.target.value);
|
||||
hasError && setHasError(false);
|
||||
if (hasError) {
|
||||
setHasError(false);
|
||||
}
|
||||
};
|
||||
|
||||
const clearEmail = () => {
|
||||
setTempEmail(prevEmail);
|
||||
setOpenedEmailKey(null);
|
||||
setOpenedEmailKey("");
|
||||
setHasError(false);
|
||||
};
|
||||
|
||||
@ -119,44 +130,63 @@ const UsersTableRow = ({
|
||||
const handleSaveEmail = () => {
|
||||
setPrevEmail(tempEmail);
|
||||
changeEmail(id, tempEmail);
|
||||
setOpenedEmailKey(null);
|
||||
setOpenedEmailKey("");
|
||||
setIsPrevEmailValid(true);
|
||||
!isChecked && toggleAccount();
|
||||
if (!isChecked) {
|
||||
toggleAccount();
|
||||
}
|
||||
};
|
||||
|
||||
const handleAccountToggle = (e) => {
|
||||
const handleAccountToggle = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
!isPrevEmailValid ||
|
||||
emailInputRef.current?.contains(e.target) ||
|
||||
emailTextRef.current?.contains(e.target) ||
|
||||
|
||||
if (
|
||||
isPrevEmailValid &&
|
||||
!(emailInputRef.current && emailInputRef.current.contains(e.target)) &&
|
||||
!emailTextRef.current?.contains(e.target)
|
||||
) {
|
||||
toggleAccount();
|
||||
}
|
||||
};
|
||||
|
||||
const onValidateEmail = (res) => {
|
||||
const onValidateEmail = (res: TValidate) => {
|
||||
setIsEmailValid(res.isValid);
|
||||
return { isValid: res.isValid, errors: res.errors || [] };
|
||||
};
|
||||
|
||||
const handleSaveClick = () => {
|
||||
isEmailValid ? handleSaveEmail() : setHasError(true);
|
||||
if (isEmailValid) {
|
||||
handleSaveEmail();
|
||||
} else {
|
||||
setHasError(true);
|
||||
}
|
||||
};
|
||||
|
||||
const checkEmailValidity = () => {
|
||||
!isEmailValid && setHasError(true);
|
||||
if (!isEmailValid) {
|
||||
setHasError(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
e.key === "Enter" && isEmailValid ? handleSaveEmail() : setHasError(true);
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter") {
|
||||
if (isEmailValid) {
|
||||
handleSaveEmail();
|
||||
} else {
|
||||
setHasError(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
isEmailOpen ||
|
||||
prevEmail === tempEmail ||
|
||||
setTempEmail(prevEmail) ||
|
||||
if (!isEmailOpen && prevEmail !== tempEmail) {
|
||||
setTempEmail(prevEmail);
|
||||
setHasError(false);
|
||||
}, [isEmailOpen]);
|
||||
}
|
||||
}, [isEmailOpen, prevEmail, tempEmail]);
|
||||
|
||||
if (!ready) return <></>;
|
||||
if (!ready) return;
|
||||
|
||||
return (
|
||||
<StyledTableRow
|
||||
@ -178,11 +208,11 @@ const UsersTableRow = ({
|
||||
{isEmailOpen ? (
|
||||
<EmailInputWrapper ref={emailInputRef}>
|
||||
<EmailInput
|
||||
placeholder={t("EnterEmail")}
|
||||
placeholder={t("SMTPSettings:EnterEmail")}
|
||||
className="import-email-input"
|
||||
value={tempEmail}
|
||||
onChange={handleEmailChange}
|
||||
type="email"
|
||||
type={InputType.email}
|
||||
onValidateInput={onValidateEmail}
|
||||
onKeyDown={handleKeyDown}
|
||||
hasError={hasError}
|
||||
@ -190,8 +220,12 @@ const UsersTableRow = ({
|
||||
isAutoFocussed
|
||||
/>
|
||||
|
||||
<DecisionButton icon={<CheckSvg />} onClick={handleSaveClick} />
|
||||
<DecisionButton icon={<CrossSvg />} onClick={clearEmail} />
|
||||
<DecisionButton
|
||||
label=""
|
||||
icon={<CheckSvg />}
|
||||
onClick={handleSaveClick}
|
||||
/>
|
||||
<DecisionButton label="" icon={<CrossSvg />} onClick={clearEmail} />
|
||||
</EmailInputWrapper>
|
||||
) : (
|
||||
<span onClick={openEmail} className="user-email" ref={emailTextRef}>
|
||||
@ -206,7 +240,7 @@ const UsersTableRow = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ importAccountsStore }) => {
|
||||
export default inject<TStore>(({ importAccountsStore }) => {
|
||||
const { changeEmail } = importAccountsStore;
|
||||
|
||||
return {
|
||||
|
@ -27,10 +27,12 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { TableBody } from "@docspace/shared/components/table";
|
||||
import UsersTableHeader from "./UsersTableHeader";
|
||||
import UsersTableRow from "./UsersTableRow";
|
||||
import { TableBody } from "@docspace/shared/components/table";
|
||||
import { StyledTableContainer } from "../../../StyledStepper";
|
||||
import { StyledTableContainer } from "../../../../StyledDataImport";
|
||||
|
||||
import { TableViewProps, AddEmailTableProps } from "../../../../types";
|
||||
|
||||
const TABLE_VERSION = "6";
|
||||
const COLUMNS_SIZE = `nextcloudThirdColumnsSize_ver-${TABLE_VERSION}`;
|
||||
@ -38,27 +40,27 @@ const INFO_PANEL_COLUMNS_SIZE = `infoPanelNextcloudThirdColumnsSize_ver-${TABLE_
|
||||
|
||||
const checkedAccountType = "withoutEmail";
|
||||
|
||||
const TableView = (props) => {
|
||||
const TableView = (props: TableViewProps) => {
|
||||
const {
|
||||
t,
|
||||
userId,
|
||||
sectionWidth,
|
||||
accountsData,
|
||||
users,
|
||||
|
||||
userId,
|
||||
checkedUsers,
|
||||
toggleAccount,
|
||||
toggleAllAccounts,
|
||||
isAccountChecked,
|
||||
} = props;
|
||||
const [hideColumns, setHideColumns] = useState(false);
|
||||
const [openedEmailKey, setOpenedEmailKey] = useState(null);
|
||||
users,
|
||||
} = props as AddEmailTableProps;
|
||||
const [openedEmailKey, setOpenedEmailKey] = useState<string>("");
|
||||
const tableRef = useRef(null);
|
||||
|
||||
const usersWithFilledEmails = users.withoutEmail.filter(
|
||||
(user) => user.email && user.email.length > 0,
|
||||
);
|
||||
|
||||
const toggleAll = (e) =>
|
||||
const toggleAll = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
toggleAllAccounts(
|
||||
e.target.checked,
|
||||
usersWithFilledEmails,
|
||||
@ -68,6 +70,15 @@ const TableView = (props) => {
|
||||
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
|
||||
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
|
||||
|
||||
const isIndeterminate =
|
||||
checkedUsers.withoutEmail.length > 0 &&
|
||||
checkedUsers.withoutEmail.length !== usersWithFilledEmails.length;
|
||||
|
||||
const stub: () => Promise<void> = () =>
|
||||
new Promise((resolve) => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
|
||||
<UsersTableHeader
|
||||
@ -76,11 +87,7 @@ const TableView = (props) => {
|
||||
tableRef={tableRef}
|
||||
columnStorageName={columnStorageName}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
setHideColumns={setHideColumns}
|
||||
isIndeterminate={
|
||||
checkedUsers.withoutEmail.length > 0 &&
|
||||
checkedUsers.withoutEmail.length !== usersWithFilledEmails.length
|
||||
}
|
||||
isIndeterminate={isIndeterminate}
|
||||
isChecked={
|
||||
usersWithFilledEmails.length > 0 &&
|
||||
checkedUsers.withoutEmail.length === usersWithFilledEmails.length
|
||||
@ -96,7 +103,8 @@ const TableView = (props) => {
|
||||
filesLength={accountsData.length}
|
||||
hasMoreFiles={false}
|
||||
itemCount={accountsData.length}
|
||||
fetchMoreFiles={() => {}}
|
||||
fetchMoreFiles={stub}
|
||||
onScroll={stub}
|
||||
>
|
||||
{accountsData.map((data) => (
|
||||
<UsersTableRow
|
||||
@ -105,7 +113,6 @@ const TableView = (props) => {
|
||||
id={data.key}
|
||||
email={data.email || ""}
|
||||
displayName={data.displayName}
|
||||
hideColumns={hideColumns}
|
||||
isChecked={isAccountChecked(data.key, checkedAccountType)}
|
||||
toggleAccount={() => toggleAccount(data, checkedAccountType)}
|
||||
isEmailOpen={openedEmailKey === data.key}
|
||||
@ -117,8 +124,8 @@ const TableView = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ userStore, importAccountsStore }) => {
|
||||
const { id: userId } = userStore.user;
|
||||
export default inject<TStore>(({ userStore, importAccountsStore }) => {
|
||||
const userId = userStore.user?.id;
|
||||
const {
|
||||
users,
|
||||
checkedUsers,
|
||||
|
@ -30,8 +30,10 @@ import { Consumer } from "@docspace/shared/utils/context";
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
const AccountsTable = (props) => {
|
||||
const { t, viewAs, accountsData } = props;
|
||||
import { AccountsTableProps, InjectedAccountsTableProps } from "../../../types";
|
||||
|
||||
const AccountsTable = (props: AccountsTableProps) => {
|
||||
const { t, viewAs, accountsData } = props as InjectedAccountsTableProps;
|
||||
|
||||
return (
|
||||
<Consumer>
|
||||
@ -53,7 +55,7 @@ const AccountsTable = (props) => {
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
export default inject(({ setup }) => {
|
||||
export default inject<TStore>(({ setup }) => {
|
||||
const { viewAs } = setup;
|
||||
|
||||
return {
|
||||
|
@ -30,20 +30,26 @@ import { inject, observer } from "mobx-react";
|
||||
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
|
||||
import { SearchInput } from "@docspace/shared/components/search-input";
|
||||
|
||||
import AccountsTable from "./AccountsTable";
|
||||
import AccountsPaging from "../../../sub-components/AccountsPaging";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { InputSize } from "@docspace/shared/components/text-input";
|
||||
import AccountsTable from "./AccountsTable";
|
||||
import AccountsPaging from "../../sub-components/AccountsPaging";
|
||||
|
||||
import { Wrapper } from "../StyledStepper";
|
||||
import { Wrapper } from "../../StyledDataImport";
|
||||
|
||||
import UsersInfoBlock from "../../../sub-components/UsersInfoBlock";
|
||||
import { NoEmailUsersBlock } from "../../../sub-components/NoEmailUsersBlock";
|
||||
import UsersInfoBlock from "../../sub-components/UsersInfoBlock";
|
||||
import { NoEmailUsersBlock } from "../../sub-components/NoEmailUsersBlock";
|
||||
|
||||
import { parseQuota } from "../../../utils";
|
||||
import { parseQuota } from "../../utils";
|
||||
|
||||
const AddEmailsStep = (props) => {
|
||||
import { AddEmailsStepProps, InjectedAddEmailsStepProps } from "../../types";
|
||||
|
||||
const PAGE_SIZE = 25;
|
||||
|
||||
const AddEmailsStep = (props: AddEmailsStepProps) => {
|
||||
const {
|
||||
t,
|
||||
|
||||
incrementStep,
|
||||
decrementStep,
|
||||
users,
|
||||
@ -52,20 +58,24 @@ const AddEmailsStep = (props) => {
|
||||
setResultUsers,
|
||||
areCheckedUsersEmpty,
|
||||
checkedUsers,
|
||||
quotaCharacteristics,
|
||||
withEmailUsers,
|
||||
} = props;
|
||||
|
||||
quotaCharacteristics,
|
||||
} = props as InjectedAddEmailsStepProps;
|
||||
|
||||
const [dataPortion, setDataPortion] = useState(
|
||||
users.withoutEmail.slice(0, 25),
|
||||
users.withoutEmail.slice(0, PAGE_SIZE),
|
||||
);
|
||||
const [quota, setQuota] = useState({ used: 0, max: 0 });
|
||||
const [quota, setQuota] = useState<{
|
||||
used: number;
|
||||
max: number | null;
|
||||
}>({ used: 0, max: 0 });
|
||||
|
||||
const handleDataChange = (leftBoundary, rightBoundary) => {
|
||||
const handleDataChange = (leftBoundary: number, rightBoundary: number) => {
|
||||
setDataPortion(users.withoutEmail.slice(leftBoundary, rightBoundary));
|
||||
};
|
||||
|
||||
const onChangeInput = (value) => {
|
||||
const onChangeInput = (value: string) => {
|
||||
setSearchValue(value);
|
||||
};
|
||||
|
||||
@ -88,38 +98,43 @@ const AddEmailsStep = (props) => {
|
||||
checkedUsers.withEmail.length + checkedUsers.withoutEmail.length;
|
||||
|
||||
useEffect(() => {
|
||||
setSearchValue("");
|
||||
setQuota(parseQuota(quotaCharacteristics[1]));
|
||||
}, []);
|
||||
}, [quotaCharacteristics, setSearchValue]);
|
||||
|
||||
const totalUsedUsers =
|
||||
quota.used +
|
||||
checkedUsers.withEmail.filter((user) => !user.isDuplicate).length +
|
||||
checkedUsers.withoutEmail.length;
|
||||
|
||||
const Buttons = (
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={handleStepIncrement}
|
||||
onCancelClick={decrementStep}
|
||||
saveButtonLabel={t("Settings:NextStep")}
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
showReminder
|
||||
displaySettings
|
||||
saveButtonDisabled={
|
||||
areCheckedUsersEmpty || (quota.max ? totalUsedUsers > quota.max : false)
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
{users.withoutEmail.length > 0 && (
|
||||
<NoEmailUsersBlock
|
||||
users={users.withoutEmail.length}
|
||||
t={t}
|
||||
users={users.withoutEmail.length}
|
||||
isCurrentStep
|
||||
/>
|
||||
)}
|
||||
|
||||
{users.withoutEmail.length > 0 ? (
|
||||
<>
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={handleStepIncrement}
|
||||
onCancelClick={decrementStep}
|
||||
saveButtonLabel={t("Settings:NextStep")}
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
showReminder
|
||||
displaySettings
|
||||
saveButtonDisabled={
|
||||
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
|
||||
}
|
||||
/>
|
||||
{Buttons}
|
||||
|
||||
{quota.max && (
|
||||
<UsersInfoBlock
|
||||
@ -138,11 +153,12 @@ const AddEmailsStep = (props) => {
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
size={InputSize.base}
|
||||
/>
|
||||
|
||||
<AccountsTable t={t} accountsData={filteredAccounts} />
|
||||
|
||||
{users.withoutEmail.length > 25 && (
|
||||
{users.withoutEmail.length > PAGE_SIZE && (
|
||||
<AccountsPaging
|
||||
t={t}
|
||||
numberOfItems={users.withoutEmail.length}
|
||||
@ -156,24 +172,12 @@ const AddEmailsStep = (props) => {
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={handleStepIncrement}
|
||||
onCancelClick={decrementStep}
|
||||
saveButtonLabel={t("Settings:NextStep")}
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
showReminder
|
||||
displaySettings
|
||||
saveButtonDisabled={
|
||||
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
|
||||
}
|
||||
/>
|
||||
{Buttons}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ setup, importAccountsStore, currentQuotaStore }) => {
|
||||
const { viewAs } = setup;
|
||||
export default inject<TStore>(({ importAccountsStore, currentQuotaStore }) => {
|
||||
const {
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
@ -186,7 +190,6 @@ export default inject(({ setup, importAccountsStore, currentQuotaStore }) => {
|
||||
const { quotaCharacteristics } = currentQuotaStore;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
users,
|
||||
|
@ -120,8 +120,6 @@ const UsersTableHeader = (props: UsersTableHeaderProps) => {
|
||||
},
|
||||
];
|
||||
|
||||
const stub = () => {};
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(getColumns(defaultColumns, userId));
|
||||
}, [isIndeterminate, isChecked]);
|
||||
@ -136,14 +134,6 @@ const UsersTableHeader = (props: UsersTableHeaderProps) => {
|
||||
showSettings={false}
|
||||
useReactWindow
|
||||
infoPanelVisible={false}
|
||||
onClick={stub}
|
||||
sortBy=""
|
||||
sorted={false}
|
||||
resetColumnsSize={false}
|
||||
isLengthenHeader={false}
|
||||
sortingVisible={false}
|
||||
setHideColumns={stub}
|
||||
tagRef={null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ import { TEnhancedMigrationUser } from "@docspace/shared/api/settings/types";
|
||||
import UsersTableRow from "./UsersTableRow";
|
||||
import UsersTableHeader from "./UsersTableHeader";
|
||||
import { StyledTableContainer } from "../../../../StyledDataImport";
|
||||
import { InjectedTableViewProps, TableViewProps } from "../../../../types";
|
||||
import { SelectUserTableProps, TableViewProps } from "../../../../types";
|
||||
|
||||
const TABLE_VERSION = "6";
|
||||
const COLUMNS_SIZE = `nextcloudSecondColumnsSize_ver-${TABLE_VERSION}`;
|
||||
@ -58,7 +58,7 @@ const TableView = (props: TableViewProps) => {
|
||||
toggleAllAccounts,
|
||||
isAccountChecked,
|
||||
setSearchValue,
|
||||
} = props as InjectedTableViewProps;
|
||||
} = props as SelectUserTableProps;
|
||||
const tableRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const toggleAll = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -46,7 +46,7 @@ import {
|
||||
} from "../../types";
|
||||
|
||||
const REFRESH_TIMEOUT = 100;
|
||||
const PAGING_BREAKPOINT = 25;
|
||||
const PAGE_SIZE = 25;
|
||||
|
||||
const SelectUsersStep = (props: SelectUsersStepProps) => {
|
||||
const {
|
||||
@ -67,7 +67,9 @@ const SelectUsersStep = (props: SelectUsersStepProps) => {
|
||||
quotaCharacteristics,
|
||||
} = props as InjectedSelectUsersStepProps;
|
||||
|
||||
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
|
||||
const [dataPortion, setDataPortion] = useState(
|
||||
withEmailUsers.slice(0, PAGE_SIZE),
|
||||
);
|
||||
const [quota, setQuota] = useState<{
|
||||
used: number;
|
||||
max: number | null;
|
||||
@ -160,14 +162,13 @@ const SelectUsersStep = (props: SelectUsersStepProps) => {
|
||||
|
||||
<AccountsTable t={t} accountsData={filteredAccounts} />
|
||||
|
||||
{withEmailUsers.length > PAGING_BREAKPOINT &&
|
||||
filteredAccounts.length > 0 && (
|
||||
<AccountsPaging
|
||||
t={t}
|
||||
numberOfItems={withEmailUsers.length}
|
||||
setDataPortion={handleDataChange}
|
||||
/>
|
||||
)}
|
||||
{withEmailUsers.length > PAGE_SIZE && filteredAccounts.length > 0 && (
|
||||
<AccountsPaging
|
||||
t={t}
|
||||
numberOfItems={withEmailUsers.length}
|
||||
setDataPortion={handleDataChange}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Text fontWeight={600} lineHeight="20px" className="mb-17">
|
||||
|
@ -24,6 +24,7 @@
|
||||
// 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 React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
TEnhancedMigrationUser,
|
||||
@ -149,16 +150,23 @@ export interface TableViewProps {
|
||||
export interface InjectedTableViewProps extends TableViewProps {
|
||||
userId?: string;
|
||||
checkedUsers: TStore["importAccountsStore"]["checkedUsers"];
|
||||
withEmailUsers: TStore["importAccountsStore"]["withEmailUsers"];
|
||||
toggleAccount: TStore["importAccountsStore"]["toggleAccount"];
|
||||
toggleAllAccounts: TStore["importAccountsStore"]["toggleAllAccounts"];
|
||||
isAccountChecked: TStore["importAccountsStore"]["isAccountChecked"];
|
||||
}
|
||||
|
||||
export interface AddEmailTableProps extends InjectedTableViewProps {
|
||||
users: TStore["importAccountsStore"]["users"];
|
||||
}
|
||||
|
||||
export interface SelectUserTableProps extends InjectedTableViewProps {
|
||||
withEmailUsers: TStore["importAccountsStore"]["withEmailUsers"];
|
||||
setSearchValue: TStore["importAccountsStore"]["setSearchValue"];
|
||||
}
|
||||
|
||||
export interface UsersTableHeaderProps {
|
||||
t: TFunciton;
|
||||
sectionWidth: number;
|
||||
sectionWidth?: number;
|
||||
|
||||
userId?: string;
|
||||
tableRef: React.RefObject<HTMLDivElement>;
|
||||
@ -194,6 +202,14 @@ export interface InjectedRowViewProps extends RowViewProps {
|
||||
setSearchValue: TStore["importAccountsStore"]["setSearchValue"];
|
||||
}
|
||||
|
||||
export interface AddEmailRowProps extends RowViewProps {
|
||||
users: TStore["importAccountsStore"]["users"];
|
||||
checkedUsers: TStore["importAccountsStore"]["checkedUsers"];
|
||||
toggleAccount: TStore["importAccountsStore"]["toggleAccount"];
|
||||
toggleAllAccounts: TStore["importAccountsStore"]["toggleAllAccounts"];
|
||||
isAccountChecked: TStore["importAccountsStore"]["isAccountChecked"];
|
||||
}
|
||||
|
||||
export interface UsersRowProps {
|
||||
t: TFunciton;
|
||||
data: TEnhancedMigrationUser;
|
||||
@ -202,6 +218,11 @@ export interface UsersRowProps {
|
||||
toggleAccount: () => void;
|
||||
}
|
||||
|
||||
export interface AddEmailUsersRowProps extends UsersRowProps {
|
||||
isEmailOpen: boolean;
|
||||
setOpenedEmailKey: React.Dispatch<React.SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export interface UsersRowContentProps {
|
||||
t: TFunciton;
|
||||
data: TEnhancedMigrationUser;
|
||||
@ -210,3 +231,55 @@ export interface UsersRowContentProps {
|
||||
email: string;
|
||||
isDuplicate: boolean;
|
||||
}
|
||||
|
||||
export interface AddEmailsStepProps {
|
||||
t: TFunciton;
|
||||
}
|
||||
|
||||
export interface InjectedAddEmailsStepProps extends AddEmailsStepProps {
|
||||
incrementStep: TStore["importAccountsStore"]["incrementStep"];
|
||||
decrementStep: TStore["importAccountsStore"]["decrementStep"];
|
||||
users: TStore["importAccountsStore"]["users"];
|
||||
searchValue: TStore["importAccountsStore"]["searchValue"];
|
||||
setSearchValue: TStore["importAccountsStore"]["setSearchValue"];
|
||||
setResultUsers: TStore["importAccountsStore"]["setResultUsers"];
|
||||
areCheckedUsersEmpty: TStore["importAccountsStore"]["areCheckedUsersEmpty"];
|
||||
checkedUsers: TStore["importAccountsStore"]["checkedUsers"];
|
||||
withEmailUsers: TStore["importAccountsStore"]["withEmailUsers"];
|
||||
|
||||
quotaCharacteristics: TStore["currentQuotaStore"]["quotaCharacteristics"];
|
||||
}
|
||||
|
||||
export interface AddEmailTableRowProps {
|
||||
t: TFunciton;
|
||||
displayName: string;
|
||||
email: string;
|
||||
isChecked: boolean;
|
||||
toggleAccount: () => void;
|
||||
id: string;
|
||||
isEmailOpen: boolean;
|
||||
setOpenedEmailKey: React.Dispatch<React.SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export interface InjectedAddEmailTableRowProps extends AddEmailTableRowProps {
|
||||
changeEmail: TStore["importAccountsStore"]["changeEmail"];
|
||||
}
|
||||
|
||||
export interface AddEmailRowContentProps {
|
||||
id: string;
|
||||
sectionWidth: number | undefined;
|
||||
displayName: string;
|
||||
email: string;
|
||||
emailInputRef: React.RefObject<HTMLDivElement>;
|
||||
emailTextRef: React.RefObject<HTMLSpanElement>;
|
||||
isChecked: boolean;
|
||||
isEmailOpen: boolean;
|
||||
setOpenedEmailKey: React.Dispatch<React.SetStateAction<string>>;
|
||||
setIsPrevEmailValid: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
toggleAccount: () => void;
|
||||
}
|
||||
|
||||
export interface InjectedAddEmailRowContentProps
|
||||
extends AddEmailRowContentProps {
|
||||
changeEmail: TStore["importAccountsStore"]["changeEmail"];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user