Web: Client: Data Import: translate SelectUsersStep to ts

This commit is contained in:
Vladimir Khvan 2024-06-11 16:28:35 +05:00
parent e32f5b36bc
commit 2328d10f95
8 changed files with 1036 additions and 0 deletions

View File

@ -0,0 +1,53 @@
// (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 { Row } from "@docspace/shared/components/row";
import UsersRowContent from "./UsersRowContent";
import { UsersRowProps } from "../../../../types";
const UsersRow = (props: UsersRowProps) => {
const { t, data, sectionWidth, isChecked, toggleAccount } = props;
return (
<Row
checked={isChecked}
onSelect={toggleAccount}
contextButtonSpacerWidth="0"
onRowClick={toggleAccount}
>
<UsersRowContent
t={t}
data={data}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
/>
</Row>
);
};
export default UsersRow;

View File

@ -0,0 +1,95 @@
// (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, { css } from "styled-components";
import { Text } from "@docspace/shared/components/text";
import { Box } from "@docspace/shared/components/box";
import { RowContent } from "@docspace/shared/components/row-content";
import { UsersRowContentProps } from "../../../../types";
const StyledRowContent = styled(RowContent)`
display: flex;
.rowMainContainer {
height: 100%;
width: 100%;
}
.username {
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-left: 5px;
`
: css`
margin-right: 5px;
`}
font-size: 14px;
font-weight: 600;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.user-email {
font-size: 12px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.user-existing {
font-size: 14px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.existingTextColor};
}
`;
const UsersRowContent = (props: UsersRowContentProps) => {
const { t, data, sectionWidth, displayName, email, isDuplicate } = props;
const contentData = [
<div key={data.key}>
<Box displayProp="flex">
<Text className="username">{displayName}</Text>
{isDuplicate && (
<Text className="user-existing">
({t("Settings:AccountAlreadyExists")})
</Text>
)}
</Box>
<Text className="user-email">{email}</Text>
</div>,
];
return (
<StyledRowContent sectionWidth={sectionWidth}>
{contentData}
</StyledRowContent>
);
};
export default UsersRowContent;

View File

@ -0,0 +1,195 @@
// (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 { inject, observer } from "mobx-react";
import { tablet } from "@docspace/shared/utils/device";
import styled, { css } from "styled-components";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link, LinkType } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { RowContainer } from "@docspace/shared/components/row-container";
import { Row } from "@docspace/shared/components/row";
import { Text } from "@docspace/shared/components/text";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
import { TEnhancedMigrationUser } from "@docspace/shared/api/settings/types";
import UsersRow from "./UsersRow";
import { InjectedRowViewProps, RowViewProps } from "../../../../types";
const StyledRowContainer = styled(RowContainer)`
margin: 0 0 20px;
.clear-icon {
margin-right: 8px;
}
.ec-desc {
max-width: 348px;
}
`;
const StyledRow = styled(Row)`
box-sizing: border-box;
height: 40px;
min-height: 40px;
.row-header-item {
display: flex;
align-items: center;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: 6px;
`
: css`
margin-left: 6px;
`}
}
.row-header-title {
color: ${(props) => props.theme.client.settings.migration.tableHeaderText};
font-weight: 600;
font-size: 12px;
}
@media ${tablet} {
.row_content {
height: auto;
}
}
`;
const checkedAccountType = "withEmail";
const RowView = (props: RowViewProps) => {
const {
t,
sectionWidth,
accountsData,
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props as InjectedRowViewProps;
const toggleAll = (e: React.ChangeEvent<HTMLInputElement>) =>
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
const handleToggle = (user: TEnhancedMigrationUser) =>
toggleAccount(user, checkedAccountType);
const onClearFilter = () => setSearchValue("");
const isIndeterminate =
checkedUsers.withEmail.length > 0 &&
checkedUsers.withEmail.length !== withEmailUsers.length;
const isChecked = checkedUsers.withEmail.length === withEmailUsers.length;
return (
<StyledRowContainer useReactWindow={false}>
{accountsData.length > 0 ? (
<>
<StyledRow>
<div className="row-header-item">
{checkedUsers.withEmail.length > 0 && (
<Checkbox
isIndeterminate={isIndeterminate}
isChecked={isChecked}
onChange={toggleAll}
/>
)}
<Text className="row-header-title">{t("Common:Name")}</Text>
</div>
</StyledRow>
{accountsData.map((data) => (
<UsersRow
t={t}
key={data.key}
data={data}
sectionWidth={sectionWidth}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => handleToggle(data)}
/>
))}
</>
) : (
<EmptyScreenContainer
imageSrc={EmptyScreenUserReactSvgUrl}
imageAlt="Empty Screen user image"
headerText={t("Common:NotFoundUsers")}
descriptionText={t("Common:NotFoundUsersDescription")}
buttons={
<Box displayProp="flex" alignItems="center">
<IconButton
className="clear-icon"
isFill
size={12}
onClick={onClearFilter}
iconName={ClearEmptyFilterSvgUrl}
/>
<Link
type={LinkType.action}
isHovered
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject<TStore>(({ importAccountsStore }) => {
const {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(RowView));

View File

@ -0,0 +1,151 @@
// (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 { useState, useEffect } from "react";
import { TableHeader, TTableColumn } from "@docspace/shared/components/table";
import { UsersTableHeaderProps } from "../../../../types";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `nextcloudSecondColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns: TTableColumn[], userId?: string) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
if (storageColumns) {
const splitColumns = storageColumns?.split(",");
return defaultColumns.map((col) => ({
...col,
enable: splitColumns.includes(col.key),
}));
}
return defaultColumns;
};
const UsersTableHeader = (props: UsersTableHeaderProps) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
isIndeterminate,
isChecked,
toggleAll,
} = props;
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"),
resizable: true,
enable: true,
default: true,
active: true,
minWidth: 180,
checkbox: {
value: isChecked,
isIndeterminate,
onChange: toggleAll,
},
onChange: onColumnChange,
},
{
key: "Email",
title: t("Common:Email"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
{
key: "Duplicate",
title: t("Settings:DuplicateNoun"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
const stub = () => {};
useEffect(() => {
setColumns(getColumns(defaultColumns, userId));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
containerRef={tableRef as { current: HTMLDivElement }}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
showSettings={false}
useReactWindow
infoPanelVisible={false}
onClick={stub}
sortBy=""
sorted={false}
resetColumnsSize={false}
isLengthenHeader={false}
sortingVisible={false}
setHideColumns={stub}
tagRef={null}
/>
);
};
export default UsersTableHeader;

View File

@ -0,0 +1,99 @@
// (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 { TableRow, TableCell } from "@docspace/shared/components/table";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import styled from "styled-components";
import { UsersTableRowProps } from "../../../../types";
const StyledTableRow = styled(TableRow)`
.table-container_cell {
padding-right: 30px;
text-overflow: ellipsis;
}
.username {
font-size: 13px;
font-weight: 600;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.user-email {
margin-right: 5px;
font-size: 13px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.not-existing {
font-size: 13px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.user-existing {
font-size: 13px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.existingTextColor};
}
`;
const NOT_EXIST = "—";
const UsersTableRow = (props: UsersTableRowProps) => {
const { t, displayName, email, isDuplicate, isChecked, toggleAccount } =
props;
return (
<StyledTableRow onClick={toggleAccount}>
<TableCell className="checkboxWrapper" forwardedRef={null} style={{}}>
<Checkbox isChecked={isChecked} onChange={toggleAccount} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell forwardedRef={null} style={{}} className="">
<Text className="user-email">{email}</Text>
</TableCell>
<TableCell forwardedRef={null} style={{}} className="">
{isDuplicate ? (
<Text className="user-existing">
{t("Settings:AccountAlreadyExists")}
</Text>
) : (
<Text className="not-existing">{NOT_EXIST}</Text>
)}
</TableCell>
</StyledTableRow>
);
};
export default UsersTableRow;

View File

@ -0,0 +1,185 @@
// (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 { useRef } from "react";
import { inject, observer } from "mobx-react";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link, LinkType } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableBody } from "@docspace/shared/components/table";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
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";
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `nextcloudSecondColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelNextcloudSecondColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "withEmail";
const TableView = (props: TableViewProps) => {
const {
t,
withEmailUsers,
userId,
sectionWidth,
accountsData,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props as InjectedTableViewProps;
const tableRef = useRef<HTMLDivElement>(null);
const toggleAll = (e: React.ChangeEvent<HTMLInputElement>) =>
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
const handleToggle = (
e: React.ChangeEvent<HTMLInputElement>,
user: TEnhancedMigrationUser,
) => {
e.stopPropagation();
toggleAccount(user, checkedAccountType);
};
const onClearFilter = () => {
setSearchValue("");
};
const isIndeterminate =
checkedUsers.withEmail.length > 0 &&
checkedUsers.withEmail.length !== withEmailUsers.length;
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
const stub: () => Promise<void> = () =>
new Promise((resolve) => {
resolve();
});
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{accountsData.length > 0 ? (
<>
<UsersTableHeader
t={t}
sectionWidth={sectionWidth!}
tableRef={tableRef}
userId={userId}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.withEmail.length === withEmailUsers.length}
toggleAll={toggleAll}
/>
<TableBody
itemHeight={49}
useReactWindow
infoPanelVisible={false}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
filesLength={accountsData.length}
hasMoreFiles={false}
itemCount={accountsData.length}
fetchMoreFiles={stub}
onScroll={stub}
>
{accountsData.map((data) => (
<UsersTableRow
t={t}
key={data.key}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={(e: React.ChangeEvent<HTMLInputElement>) =>
handleToggle(e, data)
}
/>
))}
</TableBody>
</>
) : (
<EmptyScreenContainer
imageSrc={EmptyScreenUserReactSvgUrl}
imageAlt="Empty Screen user image"
headerText={t("Common:NotFoundUsers")}
descriptionText={t("Common:NotFoundUsersDescription")}
buttons={
<Box displayProp="flex" alignItems="center">
<IconButton
className="clear-icon"
isFill
size={12}
onClick={onClearFilter}
iconName={ClearEmptyFilterSvgUrl}
/>
<Link
type={LinkType.action}
isHovered
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject<TStore>(({ userStore, importAccountsStore }) => {
const userId = userStore.user?.id;
const {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
userId,
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(TableView));

View File

@ -0,0 +1,64 @@
// (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 { inject, observer } from "mobx-react";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
import { AccountsTableProps, InjectedAccountsTableProps } from "../../../types";
const AccountsTable = (props: AccountsTableProps) => {
const { t, viewAs, accountsData } = props as InjectedAccountsTableProps;
return (
<Consumer>
{(context) =>
viewAs === "table" ? (
<TableView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
/>
) : (
<RowView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
/>
)
}
</Consumer>
);
};
export default inject<TStore>(({ setup }) => {
const { viewAs } = setup;
return {
viewAs,
};
})(observer(AccountsTable));

View File

@ -0,0 +1,194 @@
// (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 { useEffect, useState } from "react";
import { inject, observer } from "mobx-react";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { SearchInput } from "@docspace/shared/components/search-input";
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 UsersInfoBlock from "../../sub-components/UsersInfoBlock";
import { Wrapper } from "../../StyledDataImport";
import { parseQuota } from "../../utils";
import {
SelectUsersStepProps,
InjectedSelectUsersStepProps,
} from "../../types";
const SelectUsersStep = (props: SelectUsersStepProps) => {
const {
t,
incrementStep,
decrementStep,
withEmailUsers,
searchValue,
setSearchValue,
checkedUsers,
users,
quotaCharacteristics,
} = props as InjectedSelectUsersStepProps;
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
const [quota, setQuota] = useState<{
used: number;
max: number | null;
}>({
used: 0,
max: 0,
});
useEffect(() => {
setSearchValue("");
setQuota(parseQuota(quotaCharacteristics[1]));
}, [quotaCharacteristics, setSearchValue]);
const handleDataChange = (leftBoundary: number, rightBoundary: number) => {
setDataPortion(withEmailUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value: string) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.displayName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
const numberOfSelectedUsers =
checkedUsers.withEmail.length + checkedUsers.withoutEmail.length;
const totalUsedUsers =
quota.used +
checkedUsers.withEmail.filter((user) => !user.isDuplicate).length +
checkedUsers.withoutEmail.length;
return (
<Wrapper>
{withEmailUsers.length > 0 ? (
<>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={incrementStep}
onCancelClick={decrementStep}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
showReminder
displaySettings
/>
{quota.max && (
<UsersInfoBlock
t={t}
totalUsedUsers={totalUsedUsers}
selectedUsers={numberOfSelectedUsers}
totalUsers={withEmailUsers.length + users.withoutEmail.length}
totalLicenceLimit={quota.max}
/>
)}
<SearchInput
id="search-users-input"
placeholder={t("Common:Search")}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
size={InputSize.base}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{withEmailUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={withEmailUsers.length}
setDataPortion={handleDataChange}
/>
)}
</>
) : (
<Text fontWeight={600} lineHeight="20px" className="mb-17">
{t("Settings:AddEmailsWarning")}
</Text>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={incrementStep}
onCancelClick={decrementStep}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
showReminder
displaySettings
/>
)}
</Wrapper>
);
};
export default inject<TStore>(({ importAccountsStore, currentQuotaStore }) => {
const {
incrementStep,
decrementStep,
users,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
return {
incrementStep,
decrementStep,
users,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
quotaCharacteristics,
};
})(observer(SelectUsersStep));