Web: Client: Data Import: remove old steps

This commit is contained in:
Vladimir Khvan 2024-07-03 17:19:08 +05:00
parent b01b9915ca
commit 1adfb662fa
61 changed files with 0 additions and 9993 deletions

View File

@ -1,195 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { HelpButton } from "@docspace/shared/components/help-button";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
margin: 16px 0 16px;
display: flex;
align-items: center;
.checkbox-text {
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
`;
const InfoText = styled(Text)`
margin-top: -8px;
margin-bottom: 8px;
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
`;
const ErrorText = styled(Text)`
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
margin-bottom: 8px;
`;
const ImportCompleteStep = ({
t,
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
}) => {
const [isChecked, setIsChecked] = useState(false);
const [importResult, setImportResult] = useState({
succeedUsers: 0,
failedUsers: 0,
errors: [],
});
const navigate = useNavigate();
const [isSaving, setIsSaving] = useState(false);
const onDownloadLog = async () => {
try {
await getMigrationLog()
.then((response) => new Blob([response]))
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "migration.log";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
console.log(error);
toastr.error(error);
}
};
const onChangeCheckbox = () => {
setIsChecked((prev) => !prev);
};
const onFinishClick = () => {
if (isChecked) {
sendWelcomeLetter({ isSendWelcomeEmail: true });
}
clearCheckedAccounts();
clearMigration();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
navigate("/portal-settings/data-import/migration");
}, 1000);
};
useEffect(() => {
try {
getMigrationStatus().then((res) =>
setImportResult({
succeedUsers: res.parseResult.successedUsers,
failedUsers: res.parseResult.failedUsers,
errors: res.parseResult.errors,
}),
);
} catch (error) {
toastr.error(error);
}
}, []);
return (
<>
<InfoText>
{t("Settings:ImportedUsers", {
selectedUsers: importResult.succeedUsers,
importedUsers: importResult.succeedUsers + importResult.failedUsers,
})}
</InfoText>
{importResult.failedUsers > 0 && (
<ErrorText>
{t("Settings:ErrorsWereFound", {
errors: importResult.failedUsers,
})}
</ErrorText>
)}
{importResult.errors?.length > 0 && (
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
)}
<Wrapper>
<Checkbox
label={t("Settings:SendInviteLetter")}
isChecked={isChecked}
onChange={onChangeCheckbox}
/>
<HelpButton
place="right"
offsetRight={0}
style={{ margin: "0px 5px" }}
tooltipContent={
<Text fontSize="12px">{t("Settings:InviteLetterTooltip")}</Text>
}
/>
</Wrapper>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onFinishClick}
onCancelClick={onDownloadLog}
saveButtonLabel={t("Common:Finish")}
cancelButtonLabel={t("Settings:DownloadLog")}
displaySettings
showReminder
isSaving={isSaving}
/>
</>
);
};
export default inject(({ importAccountsStore }) => {
const {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
} = importAccountsStore;
return {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
};
})(observer(ImportCompleteStep));

View File

@ -1,150 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { isTablet } from "@docspace/shared/utils/device";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import styled from "styled-components";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { Button } from "@docspace/shared/components/button";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
max-width: 350px;
.data-import-progress-bar {
margin-top: -8px;
margin-bottom: 16px;
}
`;
const ImportProcessingStep = ({
t,
onNextStep,
isFifthStep,
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
}) => {
const [percent, setPercent] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const uploadInterval = useRef(null);
const handleFileMigration = async () => {
setIsLoading(true);
setPercent(0);
setIsVisible(true);
try {
await proceedFileMigration("GoogleWorkspace");
uploadInterval.current = setInterval(async () => {
const res = await getMigrationStatus();
setPercent(res.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
if (res.isCompleted || res.progress === 100) {
clearInterval(uploadInterval.current);
setIsLoading(false);
setIsVisible(false);
setPercent(100);
setTimeout(() => {
onNextStep();
}, 1000);
}
}, 1000);
} catch (error) {
console.log(error);
toastr.error(error);
setIsLoading(false);
}
};
// const hideCancelDialog = () => setIsVisible(false);
// const onCancel = () => {
// setIsVisible(true);
// };
// const handleCancelMigration = () => {
// setIsLoading(false);
// cancelMigration();
// }
useEffect(() => {
handleFileMigration();
return () => clearInterval(uploadInterval.current);
}, []);
return (
<Wrapper>
<ProgressBar
percent={percent}
isInfiniteProgress={isVisible}
className="data-import-progress-bar"
/>
{/* <Button
size={isTablet() ? "medium" : "small"}
label={t("Common:CancelButton")}
onClick={onCancel}
/>
{isVisible && (
<CancelUploadDialog
visible={isVisible}
loading={false}
isFifthStep={isFifthStep}
cancelMigration={handleCancelMigration}
onClose={hideCancelDialog}
/>
)} */}
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
} = importAccountsStore;
return {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
};
})(observer(ImportProcessingStep));

View File

@ -1,160 +0,0 @@
// (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 styled from "styled-components";
import ImportSection from "../../../sub-components/ImportSection";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import PeopleIcon from "PUBLIC_DIR/images/catalog.accounts.react.svg";
import AccountsIcon from "PUBLIC_DIR/images/catalog.accounts.react.svg";
import DocumentsIcon from "PUBLIC_DIR/images/catalog.documents.react.svg";
import RoomsIcon from "PUBLIC_DIR/images/catalog.rooms.react.svg";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
.save-cancel-buttons {
margin-top: 4px;
}
`;
const ImportStep = ({
t,
onNextStep,
onPrevStep,
showReminder,
importOptions,
setImportOptions,
}) => {
const onChange = (e, name) => {
const checked = e.target.checked;
setImportOptions({ [name]: checked });
};
const serviceName = "Google Workspace";
const users =
t("Settings:Employees")[0].toUpperCase() + t("Settings:Employees").slice(1);
return (
<Wrapper>
<ImportSection
isChecked
sectionName={users}
description={t("Settings:UsersSectionDescription")}
exportSection={{ sectionName: users, workspace: serviceName }}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: PeopleIcon,
}}
isDisabled
/>
<ImportSection
isChecked={importOptions.importGroups}
onChange={(e) => onChange(e, "importGroups")}
sectionName={t("Common:Groups")}
description={t("Settings:GroupsDescription", { serviceName })}
exportSection={{
sectionName: t("Common:Groups"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: AccountsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importPersonalFiles}
onChange={(e) => onChange(e, "importPersonalFiles")}
sectionName={t("Settings:PersonalFiles")}
description={t("Settings:PersonalFilesDescription")}
exportSection={{
sectionName: "Google Drive's Files",
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFiles}
onChange={(e) => onChange(e, "importSharedFiles")}
sectionName={t("Settings:SharedFiles")}
description={t("Settings:SharedFilesDescription")}
exportSection={{
sectionName: t("Settings:SharedFiles"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFolders}
onChange={(e) => onChange(e, "importSharedFolders")}
sectionName={t("Settings:SharedFolders")}
description={t("Settings:SharedFoldersDescription")}
exportSection={{
sectionName: t("Settings:SharedFolders"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Rooms"),
workspace: PRODUCT_NAME,
SectionIcon: RoomsIcon,
}}
/>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
showReminder
/>
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const { importOptions, setImportOptions } = importAccountsStore;
return {
importOptions,
setImportOptions,
};
})(observer(ImportStep));

View File

@ -1,450 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import { isTablet } from "@docspace/shared/utils/device";
import styled from "styled-components";
import { Text } from "@docspace/shared/components/text";
import { Box } from "@docspace/shared/components/box";
import { Link } from "@docspace/shared/components/link";
import { Button } from "@docspace/shared/components/button";
import { FileInput } from "@docspace/shared/components/file-input";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
max-width: 350px;
.select-file-title {
font-weight: 600;
line-height: 20px;
margin-bottom: 4px;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.select-file-input {
height: 32px;
margin-bottom: 16px;
.icon-button_svg {
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.fileInputIconColor};
}
}
}
}
.select-file-progress-bar {
margin: 12px 0 16px;
width: 350px;
}
`;
const ErrorBlock = styled.div`
max-width: 700px;
.complete-progress-bar {
margin: 12px 0 16px;
max-width: 350px;
}
.error-text {
font-size: 12px;
margin-bottom: 10px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
}
.save-cancel-buttons {
margin-top: 16px;
}
`;
const FAILS_TRIES = 1;
const SelectFileStep = ({
t,
onNextStep,
showReminder,
setShowReminder,
cancelDialogVisible,
setCancelDialogVisible,
initMigrationName,
multipleFileUploading,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
}) => {
const [progress, setProgress] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const [isError, setIsError] = useState(false);
const [showErrorText, setShowErrorText] = useState(false);
const [isFileError, setIsFileError] = useState(false);
const [fileName, setFileName] = useState(null);
const [isBackupEmpty, setIsBackupEmpty] = useState(false);
const [searchParams] = useSearchParams();
const isAbort = useRef(false);
const uploadInterval = useRef(null);
const navigate = useNavigate();
const [failTries, setFailsTries] = useState(FAILS_TRIES);
const goBack = () => {
navigate("/portal-settings/data-import/migration");
};
const checkMigrationStatusAndUpdate = async () => {
try {
const res = await getMigrationStatus();
if (!res || res.parseResult.migratorName !== "GoogleWorkspace") {
clearInterval(uploadInterval.current);
return;
}
if (res.parseResult.operation === "parse" && !res.isCompleted) {
setProgress(res.progress);
setIsFileLoading(true);
} else {
setIsFileLoading(false);
}
setIsFileError(false);
setShowReminder(true);
if (res.parseResult.files?.length > 0) {
setFileName(res.parseResult.files.join(", "));
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
setIsFileError(false);
setShowReminder(false);
setFileName(null);
clearInterval(uploadInterval.current);
} else if (res.isCompleted || res.progress === 100) {
if (
res.parseResult.users.length +
res.parseResult.existUsers.length +
res.parseResult.withoutEmailUsers.length >
0
) {
setUsers(res.parseResult);
setShowReminder(true);
onNextStep && onNextStep();
}
clearInterval(uploadInterval.current);
}
} catch (error) {
toastr.error(error.message || t("Common:SomethingWentWrong"));
setIsFileError(true);
clearInterval(uploadInterval.current);
}
};
useEffect(() => {
setShowReminder(false);
checkMigrationStatusAndUpdate();
uploadInterval.current = setInterval(() => {
checkMigrationStatusAndUpdate();
}, 1000);
return () => clearInterval(uploadInterval.current);
}, []);
const onUploadToServer = () => {
setShowReminder(false);
checkMigrationStatusAndUpdate();
};
const onUploadFile = async (file) => {
setIsVisible(true);
try {
if (file.length) {
await multipleFileUploading(file, setProgress, isAbort);
} else {
await singleFileUploading(file, setProgress, isAbort);
}
if (isAbort.current) return;
await initMigrationName(searchParams.get("service"));
uploadInterval.current = setInterval(async () => {
try {
const res = await getMigrationStatus();
if (!res && failTries) {
setFailsTries((tries) => tries - 1);
return;
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
toastr.error(res.error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
clearInterval(uploadInterval.current);
setShowErrorText(true);
return;
}
if (res.isCompleted || res.parseResult.progress === 100) {
clearInterval(uploadInterval.current);
setIsFileLoading(false);
setIsVisible(false);
if (
res.parseResult.users.length +
res.parseResult.existUsers.length +
res.parseResult.withoutEmailUsers.length >
0
) {
setUsers(res.parseResult);
setShowReminder(true);
setIsBackupEmpty(false);
} else {
setIsBackupEmpty(true);
cancelMigration();
}
}
setProgress(res?.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
setShowErrorText(false);
} catch (error) {
toastr.error(error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
setIsError(true);
clearInterval(uploadInterval.current);
} finally {
isAbort.current = false;
}
}, 1000);
} catch (error) {
toastr.error(error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
}
};
const onSelectFile = (file) => {
setProgress(0);
setIsFileError(false);
setShowReminder(false);
setIsFileLoading(true);
setFailsTries(FAILS_TRIES);
try {
onUploadFile(file);
} catch (error) {
toastr.error(error);
setIsFileLoading(false);
}
};
const onDownloadArchives = async () => {
try {
await getMigrationStatus()
.then(
(res) =>
new Blob([res.parseResult.failedArchives], {
type: "text/csv;charset=utf-8",
}),
)
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "unsupported_files";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
toastr.error(error);
}
};
const onCancel = () => {
setCancelDialogVisible(true);
};
const handleCancelMigration = () => {
isAbort.current = true;
setProgress(0);
setIsFileLoading(false);
clearInterval(uploadInterval.current);
cancelMigration();
};
const hideCancelDialog = () => setCancelDialogVisible(false);
return (
<>
<Wrapper>
<Text className="select-file-title">
{t("Settings:ChooseBackupFiles")}
</Text>
<FileInput
scale
onInput={onSelectFile}
className="select-file-input"
placeholder={fileName || t("Settings:BackupFiles")}
isDisabled={isFileLoading}
accept={[".zip"]}
/>
</Wrapper>
{isFileLoading ? (
<Wrapper>
<ProgressBar
percent={progress}
isInfiniteProgress={isVisible}
className="select-file-progress-bar"
label={t("Settings:BackupFilesUploading")}
/>
<Button
size={isTablet() ? "medium" : "small"}
label={t("Common:CancelButton")}
onClick={onCancel}
/>
</Wrapper>
) : (
<ErrorBlock>
{isFileError && (
<Box>
<ProgressBar
percent={100}
className="complete-progress-bar"
label={t("Common:LoadingIsComplete")}
/>
<Text className="error-text">
{showErrorText
? t("Settings:UnsupportedFilesDescription")
: t("Settings:UnsupportedFilesWithUploadDesc")}
</Text>
<Link
type="action"
isHovered
fontWeight={600}
onClick={onDownloadArchives}
>
{t("Settings:CheckUnsupportedFiles")}
</Link>
</Box>
)}
{isBackupEmpty && (
<Box>
<ProgressBar
percent={100}
className="complete-progress-bar"
label={t("Common:LoadingIsComplete")}
/>
<Text className="error-text">
{t("Settings:NoUsersInBackup")}
</Text>
</Box>
)}
{isError ? (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onUploadToServer}
onCancelClick={goBack}
saveButtonLabel={t("Settings:UploadToServer")}
cancelButtonLabel={t("Common:Back")}
isSaving={showReminder}
displaySettings
saveButtonDisabled={showReminder}
showReminder
/>
) : (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={goBack}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
saveButtonDisabled={!showReminder}
showReminder
/>
)}
</ErrorBlock>
)}
{cancelDialogVisible && (
<CancelUploadDialog
visible={cancelDialogVisible}
// loading={isFileLoading}
onClose={hideCancelDialog}
cancelMigration={handleCancelMigration}
/>
)}
</>
);
};
export default inject(({ dialogsStore, importAccountsStore }) => {
const {
initMigrationName,
singleFileUploading,
multipleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
} = importAccountsStore;
const { cancelUploadDialogVisible, setCancelUploadDialogVisible } =
dialogsStore;
return {
initMigrationName,
singleFileUploading,
multipleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
cancelDialogVisible: cancelUploadDialogVisible,
setCancelDialogVisible: setCancelUploadDialogVisible,
};
})(observer(SelectFileStep));

View File

@ -1,57 +0,0 @@
// (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";
const UsersRow = (props) => {
const { t, data, sectionWidth, isChecked, toggleAccount } = props;
return (
<>
<Row
sectionWidth={sectionWidth}
data={data}
checkbox
checked={isChecked}
onClick={toggleAccount}
onSelect={toggleAccount}
contextButtonSpacerWidth="0"
>
<UsersRowContent
t={t}
data={data}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
/>
</Row>
</>
);
};
export default UsersRow;

View File

@ -1,99 +0,0 @@
// (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";
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 = ({
t,
data,
sectionWidth,
displayName,
email,
isDuplicate,
}) => {
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

@ -1,192 +0,0 @@
// (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 } 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 UsersRow from "./UsersRow";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
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) => {
const {
t,
sectionWidth,
accountsData,
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props;
const toggleAll = (e) => {
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
};
const handleToggle = (user) => 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 sectionWidth={sectionWidth}>
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(RowView));

View File

@ -1,140 +0,0 @@
// (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 { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `GoogleWorkspaceColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
isIndeterminate,
isChecked,
toggleAll,
} = props;
const defaultColumns = [
{
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: "Dublicate",
title: t("Settings:DuplicateNoun"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTableHeader));

View File

@ -1,100 +0,0 @@
// (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 } from "@docspace/shared/components/table";
import { 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";
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 = ({
t,
displayName,
email,
isDuplicate,
isChecked,
toggleAccount,
}) => {
return (
<StyledTableRow checked={isChecked} onClick={toggleAccount}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={toggleAccount} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
<TableCell>
{isDuplicate ? (
<Text className="user-existing">{t("Settings:AccountAlreadyExists")}</Text>
) : (
<Text className="not-existing">{NOT_EXIST}</Text>
)}
</TableCell>
</StyledTableRow>
);
};
export default UsersTableRow;

View File

@ -1,244 +0,0 @@
// (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 { Base } from "@docspace/shared/themes";
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 } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import UsersTableHeader from "./UsersTableHeader";
import UsersTableRow from "./UsersTableRow";
import { TableContainer } from "@docspace/shared/components/table";
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";
const StyledTableContainer = styled(TableContainer)`
margin: 0 0 20px;
.header-container-text {
font-size: 12px;
}
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
.checkboxWrapper {
padding: 0;
padding-inline-start: 8px;
}
.table-list-item {
cursor: pointer;
padding-left: 20px;
&:hover {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
.table-container_cell {
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
margin-left: -24px;
padding-left: 24px;
}
.checkboxWrapper {
padding-left: 32px;
}
.table-container_row-context-menu-wrapper {
margin-right: -20px;
padding-right: 20px;
}
}
}
.table-list-item:has(.selected-table-row) {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
}
.clear-icon {
margin-right: 8px;
margin-top: 2px;
}
.ec-desc {
max-width: 618px;
}
`;
StyledTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `googleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelGoogleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "withEmail";
const TableView = (props) => {
const {
t,
withEmailUsers,
userId,
sectionWidth,
accountsData,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props;
const tableRef = useRef(null);
const toggleAll = (e) => {
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
};
const handleToggle = (e, user) => {
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}`;
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={() => {}}
>
{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) => 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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
withEmailUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
withEmailUsers,
userId,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(TableView));

View File

@ -1,62 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
const AccountsTable = ({ t, viewAs, accountsData }) => {
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(({ setup }) => {
const { viewAs } = setup;
return {
viewAs,
};
})(withTranslation(["People"])(observer(AccountsTable)));

View File

@ -1,185 +0,0 @@
// (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 AccountsTable from "./AccountsTable";
import AccountsPaging from "../../../sub-components/AccountsPaging";
import UsersInfoBlock from "./../../../sub-components/UsersInfoBlock";
import { parseQuota } from "../../../utils";
const SelectUsersStep = ({
t,
onNextStep,
onPrevStep,
withEmailUsers,
searchValue,
setSearchValue,
setResultUsers,
areCheckedUsersEmpty,
cancelMigration,
checkedUsers,
quotaCharacteristics,
}) => {
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
const [quota, setQuota] = useState({ used: 0, max: 0 });
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
setSearchValue("");
setQuota(parseQuota(quotaCharacteristics[1]));
}, []);
const handleDataChange = (leftBoundary, rightBoundary) => {
setDataPortion(withEmailUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
const handleStepIncrement = () => {
setResultUsers();
onNextStep();
};
const goBack = () => {
cancelMigration();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
onPrevStep();
}, 1000);
};
const totalUsedUsers =
quota.used +
checkedUsers.withEmail.filter((user) => !user.isDuplicate).length;
return (
<>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={handleStepIncrement}
onCancelClick={goBack}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings={true}
saveButtonDisabled={
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
}
isSaving={isSaving}
/>
{quota.max && (
<UsersInfoBlock
t={t}
totalUsedUsers={totalUsedUsers}
selectedUsers={checkedUsers.withEmail.length}
totalUsers={withEmailUsers.length}
totalLicenceLimit={quota.max}
/>
)}
<SearchInput
id="search-withEmailUsers-input"
placeholder={t("Common:Search")}
style={{ marginTop: "16px" }}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{withEmailUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={withEmailUsers.length}
setDataPortion={handleDataChange}
/>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={handleStepIncrement}
onCancelClick={goBack}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings={true}
saveButtonDisabled={
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
}
isSaving={isSaving}
/>
)}
</>
);
};
export default inject(({ importAccountsStore, currentQuotaStore }) => {
const {
withEmailUsers,
searchValue,
setSearchValue,
areCheckedUsersEmpty,
setResultUsers,
cancelMigration,
checkedUsers,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
return {
withEmailUsers,
searchValue,
setSearchValue,
areCheckedUsersEmpty,
setResultUsers,
cancelMigration,
checkedUsers,
quotaCharacteristics,
};
})(observer(SelectUsersStep));

View File

@ -1,69 +0,0 @@
// (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 { Row } from "@docspace/shared/components/row";
import UsersTypeRowContent from "./UsersTypeRowContent";
const UsersTypeRow = ({
data,
sectionWidth,
typeOptions,
isChecked,
toggleAccount,
}) => {
const userTypeRef = useRef();
const handleAccountToggle = (e) => {
userTypeRef.current?.contains(e.target) || toggleAccount();
};
return (
<>
<Row
sectionWidth={sectionWidth}
key={data.key}
data={data}
checked={isChecked}
contextButtonSpacerWidth="0"
onRowClick={handleAccountToggle}
onSelect={handleAccountToggle}
>
<UsersTypeRowContent
id={data.key}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
type={data.userType}
typeOptions={typeOptions}
userTypeRef={userTypeRef}
/>
</Row>
</>
);
};
export default UsersTypeRow;

View File

@ -1,153 +0,0 @@
// (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 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 { ComboBox } from "@docspace/shared/components/combobox";
const StyledRowContent = styled(RowContent)`
display: flex;
.row-main-container-wrapper {
width: 100%;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-left: 0px;
`
: css`
margin-right: 0px;
`}
}
.rowMainContainer {
height: 100%;
width: 100%;
}
.username {
font-size: 14px;
font-weight: 600;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.user-email {
margin-right: 5px;
font-size: 12px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.user-type {
.combo-button {
border: none;
padding: 4px 8px;
justify-content: flex-end;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
}
}
`;
const UsersRowContent = ({
id,
sectionWidth,
displayName,
email,
typeOptions,
roleSelectorRef,
type,
changeUserType,
}) => {
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const contentData = [
<Box
key={id}
displayProp="flex"
justifyContent="space-between"
alignItems="center"
>
<Box>
<Text className="username">{displayName}</Text>
<Text className="user-email">{email}</Text>
</Box>
<div ref={roleSelectorRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</Box>,
];
return (
<StyledRowContent sectionWidth={sectionWidth}>
{contentData}
</StyledRowContent>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersRowContent));

View File

@ -1,241 +0,0 @@
// (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 UsersTypeRow from "./UsersTypeRow";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { RowContainer } from "@docspace/shared/components/row-container";
import { Row } from "@docspace/shared/components/row";
import { Text } from "@docspace/shared/components/text";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const StyledRowContainer = styled(RowContainer)`
margin: 0 0 20px;
.table-group-menu {
height: 61px;
position: sticky;
z-index: 201;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: -16px;
`
: css`
margin-left: -16px;
`}
width: 100%;
margin-top: 20px;
top: 61px;
margin-bottom: -29.5px;
.table-container_group-menu {
padding: 0px 16px;
border-image-slice: 0;
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
}
.table-container_group-menu-checkbox {
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: 8px;
`
: css`
margin-left: 8px;
`}
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.header-container-text {
font-size: 12px;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.table-container_header {
position: absolute;
}
.clear-icon {
margin-right: 8px;
}
.ec-desc {
max-width: 348px;
}
`;
const StyledRow = styled(Row)`
box-sizing: border-box;
min-height: 40px;
.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 = "result";
const RowView = ({
t,
sectionWidth,
accountsData,
typeOptions,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
}) => {
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const toggleAll = (isChecked) =>
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
const onClearFilter = () => setSearchValue("");
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<StyledRowContainer useReactWindow={false}>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<StyledRow key="Name" sectionWidth={sectionWidth}>
<Text className="row-header-title">{t("Common:Name")}</Text>
</StyledRow>
{accountsData.map((data) => (
<UsersTypeRow
key={data.key}
data={data}
sectionWidth={sectionWidth}
typeOptions={typeOptions}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</>
) : (
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
} = importAccountsStore;
return {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
};
})(observer(RowView));

View File

@ -1,137 +0,0 @@
// (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 { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `GoogleWorkspaceColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTypeTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
setHideColumns,
isIndeterminate,
isChecked,
} = props;
const defaultColumns = [
{
key: "Name",
title: t("Common:Name"),
resizable: true,
enable: true,
default: true,
active: true,
minWidth: 180,
onChange: onColumnChange,
},
{
key: "Type",
title: t("Common:Type"),
enable: true,
resizable: true,
minWidth: 100,
onChange: onColumnChange,
},
{
key: "Email",
title: t("Common:Email"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
setHideColumns={setHideColumns}
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTypeTableHeader));

View File

@ -1,147 +0,0 @@
// (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 styled from "styled-components";
import { TableRow } from "@docspace/shared/components/table";
import { TableCell } from "@docspace/shared/components/table";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { ComboBox } from "@docspace/shared/components/combobox";
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};
}
.user-type {
.combo-button {
border: none;
padding: 4px 8px;
justify-content: flex-start;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
}
}
`;
const UsersTypeTableRow = ({
id,
displayName,
email,
typeOptions,
isChecked,
toggleAccount,
type,
changeUserType,
}) => {
const userTypeRef = useRef();
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const handleAccountToggle = (e) => {
e.preventDefault();
e.stopPropagation();
e.target.closest(".dropdown-container") ||
userTypeRef.current?.contains(e.target) ||
toggleAccount();
};
return (
<StyledTableRow checked={isChecked} onClick={handleAccountToggle}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={handleAccountToggle} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<div ref={userTypeRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
</StyledTableRow>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersTypeTableRow));

View File

@ -1,300 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { Base } from "@docspace/shared/themes";
import styled, { css } from "styled-components";
import UsersTypeTableHeader from "./UsersTypeTableHeader";
import UsersTypeTableRow from "./UsersTypeTableRow";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { TableContainer } from "@docspace/shared/components/table";
import { TableBody } from "@docspace/shared/components/table";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const StyledTableContainer = styled(TableContainer)`
margin: 0 0 20px;
.table-group-menu {
height: 69px;
position: sticky;
z-index: 201;
width: calc(100% + 40px);
margin-top: -33px;
margin-left: -20px;
top: 0;
margin-bottom: -36px;
.table-container_group-menu {
border-image-slice: 0;
border-image-source: none;
border-bottom: ${(props) =>
props.theme.client.settings.migration.workspaceBorder};
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
padding: 0px;
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
.table-container_group-menu-separator {
margin: 0 16px;
}
.header-container-text {
font-size: 12px;
}
.checkboxWrapper {
padding: 0;
padding-inline-start: 8px;
}
.table-list-item {
cursor: pointer;
padding-left: 20px;
&:hover {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
.table-container_cell {
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
margin-left: -24px;
padding-left: 24px;
}
.checkboxWrapper {
padding-left: 32px;
}
.table-container_row-context-menu-wrapper {
margin-right: -20px;
padding-right: 20px;
}
}
}
.table-list-item:has(.selected-table-row) {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
}
.clear-icon {
margin-right: 8px;
margin-top: 2px;
}
.ec-desc {
max-width: 618px;
}
`;
StyledTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `googleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelGoogleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "result";
const TableView = ({
t,
userId,
sectionWidth,
accountsData,
typeOptions,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
}) => {
const tableRef = useRef(null);
const [hideColumns, setHideColumns] = useState(false);
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const toggleAll = (isChecked) =>
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
const onClearFilter = () => {
setSearchValue("");
};
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
checkboxOptions={[]}
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<UsersTypeTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
toggleAll={toggleAll}
setHideColumns={setHideColumns}
/>
<TableBody
itemHeight={49}
useReactWindow
infoPanelVisible={false}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
filesLength={accountsData.length}
hasMoreFiles={false}
itemCount={accountsData.length}
fetchMoreFiles={() => {}}
>
{accountsData.map((data) => (
<UsersTypeTableRow
key={data.key}
id={data.key}
type={data.userType}
displayName={data.displayName}
email={data.email}
typeOptions={typeOptions}
hideColumns={hideColumns}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
} = importAccountsStore;
return {
userId,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
};
})(observer(TableView));

View File

@ -1,107 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const checkedAccountType = "result";
const AccountsTable = ({
t,
viewAs,
accountsData,
changeGroupType,
UserTypes,
toggleAllAccounts,
}) => {
const typeOptions = [
{
key: UserTypes.PortalAdmin,
label: t("Common:PortalAdmin", { productName: PRODUCT_NAME }),
onClick: () => {
changeGroupType(UserTypes.PortalAdmin);
toggleAllAccounts(false, [], checkedAccountType);
},
},
{
key: UserTypes.RoomAdmin,
label: t("Common:RoomAdmin"),
onClick: () => {
changeGroupType(UserTypes.RoomAdmin);
toggleAllAccounts(false, [], checkedAccountType);
},
},
{
key: UserTypes.User,
label: t("Common:PowerUser"),
onClick: () => {
changeGroupType(UserTypes.User);
toggleAllAccounts(false, [], checkedAccountType);
},
},
];
return (
<Consumer>
{(context) =>
viewAs === "table" ? (
<TableView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
) : (
<RowView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
)
}
</Consumer>
);
};
export default inject(({ setup, importAccountsStore }) => {
const { viewAs } = setup;
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
return {
viewAs,
changeGroupType,
UserTypes,
toggleAllAccounts,
};
})(
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
);

View File

@ -1,142 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import styled from "styled-components";
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";
const StyledSearchInput = styled(SearchInput)`
margin-top: 20px;
`;
const SelectUsersTypeStep = ({
t,
onNextStep,
onPrevStep,
showReminder,
users,
checkedUsers,
searchValue,
setSearchValue,
filteredUsers,
}) => {
const [boundaries, setBoundaries] = useState([0, 25]);
const [dataPortion, setDataPortion] = useState(
filteredUsers.slice(...boundaries),
);
const handleDataChange = (leftBoundary, rightBoundary) => {
setBoundaries([leftBoundary, rightBoundary]);
setDataPortion(filteredUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
useEffect(() => {
setDataPortion(filteredUsers.slice(...boundaries));
}, [users]);
return (
<>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
{filteredUsers.length > 0 && (
<>
<StyledSearchInput
id="search-users-type-input"
placeholder={t("Common:Search")}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{filteredUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={filteredUsers.length}
setDataPortion={handleDataChange}
/>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
)}
</>
)}
</>
);
};
export default inject(({ importAccountsStore }) => {
const { users, checkedUsers, searchValue, setSearchValue, filteredUsers } =
importAccountsStore;
return {
users,
checkedUsers,
searchValue,
setSearchValue,
filteredUsers,
};
})(observer(SelectUsersTypeStep));

View File

@ -1,182 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { HelpButton } from "@docspace/shared/components/help-button";
import { toastr } from "@docspace/shared/components/toast";
import { Wrapper } from "../StyledStepper";
const ErrorText = styled(Text)`
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
margin-bottom: 16px;
`;
const InfoText = styled(Text)`
margin-bottom: 8px;
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
`;
const ImportCompleteStep = ({
t,
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
}) => {
const [isChecked, setIsChecked] = useState(false);
const [importResult, setImportResult] = useState({
succeedUsers: 0,
failedUsers: 0,
errors: [],
});
const navigate = useNavigate();
const [isSaving, setIsSaving] = useState(false);
const onDownloadLog = async () => {
try {
await getMigrationLog()
.then((response) => new Blob([response]))
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "migration.log";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
console.log(error);
}
};
const onChangeCheckbox = () => {
setIsChecked((prev) => !prev);
};
const onFinishClick = () => {
if (isChecked) {
sendWelcomeLetter({ isSendWelcomeEmail: true });
}
clearCheckedAccounts();
clearMigration();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
navigate("/portal-settings/data-import/migration");
}, 1000);
};
useEffect(() => {
try {
getMigrationStatus().then((res) =>
setImportResult({
succeedUsers: res.parseResult.successedUsers,
failedUsers: res.parseResult.failedUsers,
errors: res.parseResult.errors,
}),
);
} catch (error) {
toastr.error(error);
}
}, []);
return (
<Wrapper>
<InfoText>
{t("Settings:ImportedUsers", {
selectedUsers: importResult.succeedUsers,
importedUsers: importResult.succeedUsers + importResult.failedUsers,
})}
</InfoText>
{importResult.failedUsers > 0 && (
<ErrorText>
{t("Settings:ErrorsWereFound", { errors: importResult.failedUsers })}
</ErrorText>
)}
{importResult.errors?.length > 0 && (
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
)}
<div className="sendLetterBlockWrapper">
<Checkbox
label={t("Settings:SendInviteLetter")}
isChecked={isChecked}
onChange={onChangeCheckbox}
/>
<HelpButton
place="right"
offsetRight={0}
style={{ margin: "0px 5px" }}
tooltipContent={
<Text fontSize="12px">{t("Settings:InviteLetterTooltip")}</Text>
}
/>
</div>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onFinishClick}
onCancelClick={onDownloadLog}
saveButtonLabel={t("Common:Finish")}
cancelButtonLabel={t("Settings:DownloadLog")}
displaySettings
showReminder
isSaving={isSaving}
/>
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
} = importAccountsStore;
return {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
};
})(observer(ImportCompleteStep));

View File

@ -1,143 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { isTablet } from "@docspace/shared/utils/device";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import { Wrapper } from "../StyledStepper";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { Button } from "@docspace/shared/components/button";
import { toastr } from "@docspace/shared/components/toast";
const ImportProcessingStep = ({
t,
incrementStep,
isSixthStep,
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
}) => {
const [percent, setPercent] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const uploadInterval = useRef(null);
const handleFileMigration = async () => {
setIsLoading(true);
setPercent(0);
setIsVisible(true);
try {
await proceedFileMigration("Nextcloud");
uploadInterval.current = setInterval(async () => {
const res = await getMigrationStatus();
setPercent(res.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
if (res.isCompleted || res.progress === 100) {
clearInterval(uploadInterval.current);
setIsLoading(false);
setIsVisible(false);
setPercent(100);
setTimeout(() => {
incrementStep();
}, 1000);
}
}, 1000);
} catch (error) {
console.log(error);
toastr.error(error);
setIsLoading(false);
}
};
// const hideCancelDialog = () => setIsVisible(false);
// const onCancel = () => {
// setIsVisible(true);
// };
// const handleCancelMigration = () => {
// setIsLoading(false);
// cancelMigration();
// }
useEffect(() => {
handleFileMigration();
return () => clearInterval(uploadInterval.current);
}, []);
return (
<Wrapper>
<ProgressBar
percent={percent}
isInfiniteProgress={isVisible}
className="data-import-progress-bar"
/>
{/* <Button
size={isTablet() ? "medium" : "small"}
className="cancel-button"
label={t("Common:CancelButton")}
onClick={onCancel}
/>
{isVisible && (
<CancelUploadDialog
visible={isVisible}
loading={false}
isSixthStep={isSixthStep}
cancelMigration={handleCancelMigration}
onClose={hideCancelDialog}
/>
)} */}
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
} = importAccountsStore;
return {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
};
})(observer(ImportProcessingStep));

View File

@ -1,161 +0,0 @@
// (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 styled from "styled-components";
import ImportSection from "../../../sub-components/ImportSection";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import PeopleIcon from "PUBLIC_DIR/images/catalog.accounts.react.svg";
import AccountsIcon from "PUBLIC_DIR/images/catalog.accounts.react.svg";
import DocumentsIcon from "PUBLIC_DIR/images/catalog.documents.react.svg";
import RoomsIcon from "PUBLIC_DIR/images/catalog.rooms.react.svg";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const SectionsWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
margin-top: 16px;
.save-cancel-buttons {
margin-top: 4px;
}
`;
const ImportStep = ({
t,
incrementStep,
decrementStep,
importOptions,
setImportOptions,
}) => {
const onChange = (e, name) => {
const checked = e.target.checked;
setImportOptions({ [name]: checked });
};
const serviceName = "NextCloud";
const users =
t("Settings:Employees")[0].toUpperCase() + t("Settings:Employees").slice(1);
return (
<SectionsWrapper>
<ImportSection
isChecked
sectionName={users}
description={t("Settings:UsersSectionDescription")}
exportSection={{ sectionName: users, workspace: serviceName }}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: PeopleIcon,
}}
isDisabled
/>
<ImportSection
isChecked={importOptions.importGroups}
onChange={(e) => onChange(e, "importGroups")}
sectionName={t("Common:Groups")}
description={t("Settings:GroupsDescription", { serviceName })}
exportSection={{
sectionName: t("Common:Groups"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: AccountsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importPersonalFiles}
onChange={(e) => onChange(e, "importPersonalFiles")}
sectionName={t("Settings:PersonalFiles")}
description={t("Settings:PersonalFilesDescription")}
exportSection={{
sectionName: "Google Drive's Files",
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFiles}
onChange={(e) => onChange(e, "importSharedFiles")}
sectionName={t("Settings:SharedFiles")}
description={t("Settings:SharedFilesDescription")}
exportSection={{
sectionName: t("Settings:SharedFiles"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFolders}
onChange={(e) => onChange(e, "importSharedFolders")}
sectionName={t("Settings:SharedFolders")}
description={t("Settings:SharedFoldersDescription")}
exportSection={{
sectionName: t("Settings:SharedFolders"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Rooms"),
workspace: PRODUCT_NAME,
SectionIcon: RoomsIcon,
}}
/>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={incrementStep}
onCancelClick={decrementStep}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
showReminder
/>
</SectionsWrapper>
);
};
export default inject(({ importAccountsStore }) => {
const { importOptions, setImportOptions } = importAccountsStore;
return {
importOptions,
setImportOptions,
};
})(observer(ImportStep));

View File

@ -1,417 +0,0 @@
// (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, useRef, useEffect } from "react";
import { inject, observer } from "mobx-react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import { isTablet } from "@docspace/shared/utils/device";
import styled from "styled-components";
import { Text } from "@docspace/shared/components/text";
import { Button } from "@docspace/shared/components/button";
import { FileInput } from "@docspace/shared/components/file-input";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { Box } from "@docspace/shared/components/box";
import { Link } from "@docspace/shared/components/link";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
max-width: 700px;
margin-top: 16px;
.choose-backup-file {
font-weight: 600;
line-height: 20px;
margin-bottom: 4px;
}
.upload-backup-input {
height: 32px;
margin-bottom: 12px;
.icon-button_svg {
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.fileInputIconColor};
}
}
}
}
.upload-back-buttons {
margin-top: 16px;
}
.select-file-progress-text {
margin: 12px 0;
}
.select-file-progress-bar {
margin: 12px 0 16px;
}
`;
const FileUploadContainer = styled.div`
max-width: 350px;
`;
const ErrorBlock = styled.div`
max-width: 700px;
.complete-progress-bar {
margin: 12px 0 16px;
max-width: 350px;
}
.error-text {
font-size: 12px;
margin-bottom: 10px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
}
.save-cancel-buttons {
margin-top: 16px;
}
`;
const FAILS_TRIES = 1;
const SelectFileStep = ({
t,
incrementStep,
cancelDialogVisible,
setCancelDialogVisibile,
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
}) => {
const [isSaveDisabled, setIsSaveDisabled] = useState(true);
const [progress, setProgress] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const [isError, setIsError] = useState(false);
const [isFileError, setIsFileError] = useState(false);
const [fileName, setFileName] = useState(null);
const [searchParams] = useSearchParams();
const isAbort = useRef(false);
const uploadInterval = useRef(null);
const navigate = useNavigate();
const [failTries, setFailsTries] = useState(FAILS_TRIES);
const goBack = () => {
navigate("/portal-settings/data-import/migration");
};
const checkMigrationStatusAndUpdate = async () => {
try {
const res = await getMigrationStatus();
if (!res || res.parseResult.migratorName !== "Nextcloud") {
clearInterval(uploadInterval.current);
return;
}
if (res.parseResult.operation === "parse" && !res.isCompleted) {
setProgress(res.progress);
setIsFileLoading(true);
} else {
setIsFileLoading(false);
}
setIsFileError(false);
setIsSaveDisabled(false);
if (res.parseResult.files?.length > 0) {
setFileName(res.parseResult.files.join(", "));
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
toastr.error(res.error);
setIsFileError(true);
setIsSaveDisabled(false);
clearInterval(uploadInterval.current);
} else if (res.isCompleted || res.progress === 100) {
setUsers(res.parseResult);
setIsSaveDisabled(true);
incrementStep && incrementStep();
clearInterval(uploadInterval.current);
}
} catch (error) {
toastr.error(error.message);
setIsFileError(true);
clearInterval(uploadInterval.current);
}
};
useEffect(() => {
setIsSaveDisabled(false);
checkMigrationStatusAndUpdate();
uploadInterval.current = setInterval(() => {
checkMigrationStatusAndUpdate();
}, 1000);
return () => clearInterval(uploadInterval.current);
}, []);
const onUploadToServer = () => {
setIsSaveDisabled(false);
checkMigrationStatusAndUpdate();
};
const onUploadFile = async (file) => {
setIsVisible(true);
try {
if (Array.isArray(file)) throw new Error(t("Common:SomethingWentWrong"));
await singleFileUploading(file, setProgress, isAbort);
if (isAbort.current) return;
await initMigrationName(searchParams.get("service"));
uploadInterval.current = setInterval(async () => {
try {
const res = await getMigrationStatus();
if (!res && failTries) {
setFailsTries((tries) => tries - 1);
return;
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
clearInterval(uploadInterval.current);
setIsFileError(true);
setIsFileLoading(false);
toastr.error(res.error);
return;
}
if (res.isCompleted || res.parseResult.progress === 100) {
clearInterval(uploadInterval.current);
setIsFileLoading(false);
setIsVisible(false);
setUsers(res.parseResult);
setIsSaveDisabled(true);
}
setProgress(res.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
} catch (error) {
toastr.error(error || error.message);
setIsFileError(true);
setIsFileLoading(false);
setIsError(true);
clearInterval(uploadInterval.current);
} finally {
isAbort.current = false;
}
}, 1000);
} catch (error) {
toastr.error(error || error.message);
setIsFileError(true);
setIsFileLoading(false);
}
};
const onSelectFile = (file) => {
setProgress(0);
setIsFileError(false);
setIsSaveDisabled(false);
setIsFileLoading(true);
setFailsTries(FAILS_TRIES);
try {
onUploadFile(file);
} catch (error) {
toastr.error(error);
setIsFileLoading(false);
}
};
const onDownloadArchives = async () => {
try {
await getMigrationStatus()
.then(
(res) =>
new Blob([res.parseResult.failedArchives], {
type: "text/csv;charset=utf-8",
}),
)
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "unsupported_files";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
toastr.error(error);
}
};
const onCancel = () => {
setCancelDialogVisibile(true);
};
const handleCancelMigration = () => {
isAbort.current = true;
setProgress(0);
setIsFileLoading(false);
clearInterval(uploadInterval.current);
cancelMigration();
};
const hideCancelDialog = () => setCancelDialogVisibile(false);
return (
<Wrapper>
<FileUploadContainer>
<Text className="choose-backup-file">
{t("Settings:ChooseBackupFile")}
</Text>
<FileInput
scale
onInput={onSelectFile}
className="upload-backup-input"
placeholder={fileName || t("Settings:BackupFile")}
isDisabled={isFileLoading}
accept={[".zip"]}
/>
</FileUploadContainer>
{isFileLoading ? (
<FileUploadContainer>
<ProgressBar
percent={progress}
isInfiniteProgress={isVisible}
className="select-file-progress-bar"
label={t("Settings:BackupFileUploading")}
/>
<Button
size={isTablet() ? "medium" : "small"}
label={t("Common:CancelButton")}
onClick={onCancel}
/>
</FileUploadContainer>
) : (
<ErrorBlock>
{isFileError && (
<Box>
<ProgressBar
percent={100}
className="complete-progress-bar"
label={t("Common:LoadingIsComplete")}
/>
<Text className="error-text">
{t("Settings:UnsupportedFilesDescription")}
</Text>
<Link
type="action"
isHovered
fontWeight={600}
onClick={onDownloadArchives}
>
{t("Settings:CheckUnsupportedFiles")}
</Link>
</Box>
)}
{isError ? (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onUploadToServer}
onCancelClick={goBack}
saveButtonLabel={t("Settings:UploadToServer")}
cancelButtonLabel={t("Common:Back")}
isSaving={isSaveDisabled}
displaySettings
saveButtonDisabled={isSaveDisabled}
showReminder
/>
) : (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={incrementStep}
onCancelClick={goBack}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
saveButtonDisabled={!isSaveDisabled}
showReminder
/>
)}
</ErrorBlock>
)}
{cancelDialogVisible && (
<CancelUploadDialog
visible={cancelDialogVisible}
// loading={isFileLoading}
onClose={hideCancelDialog}
cancelMigration={handleCancelMigration}
/>
)}
</Wrapper>
);
};
export default inject(({ dialogsStore, importAccountsStore }) => {
const {
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
} = importAccountsStore;
const { cancelUploadDialogVisible, setCancelUploadDialogVisible } =
dialogsStore;
return {
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
cancelDialogVisible: cancelUploadDialogVisible,
setCancelDialogVisibile: setCancelUploadDialogVisible,
};
})(observer(SelectFileStep));

View File

@ -1,55 +0,0 @@
// (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";
const UsersRow = (props) => {
const { t, data, sectionWidth, isChecked, toggleAccount } = props;
return (
<Row
sectionWidth={sectionWidth}
data={data}
checkbox
checked={isChecked}
onClick={toggleAccount}
onSelect={toggleAccount}
contextButtonSpacerWidth="0"
>
<UsersRowContent
t={t}
data={data}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
/>
</Row>
);
};
export default UsersRow;

View File

@ -1,99 +0,0 @@
// (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";
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 = ({
t,
data,
sectionWidth,
displayName,
email,
isDuplicate,
}) => {
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

@ -1,191 +0,0 @@
// (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 } 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 UsersRow from "./UsersRow";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
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) => {
const {
t,
sectionWidth,
accountsData,
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props;
const toggleAll = (e) =>
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
const handleToggle = (user) => 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 sectionWidth={sectionWidth}>
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(RowView));

View File

@ -1,142 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `nextcloudSecondColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
setHideColumns,
isIndeterminate,
isChecked,
toggleAll,
} = props;
const defaultColumns = [
{
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 [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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
setHideColumns={setHideColumns}
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTableHeader));

View File

@ -1,100 +0,0 @@
// (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 } from "@docspace/shared/components/table";
import { 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";
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 = ({
t,
displayName,
email,
isDuplicate,
isChecked,
toggleAccount,
}) => {
return (
<StyledTableRow checked={isChecked} onClick={toggleAccount}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={toggleAccount} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
<TableCell>
{isDuplicate ? (
<Text className="user-existing">{t("Settings:AccountAlreadyExists")}</Text>
) : (
<Text className="not-existing">{NOT_EXIST}</Text>
)}
</TableCell>
</StyledTableRow>
);
};
export default UsersTableRow;

View File

@ -1,175 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { StyledTableContainer } from "../../../StyledStepper";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import UsersTableHeader from "./UsersTableHeader";
import UsersTableRow from "./UsersTableRow";
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";
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) => {
const {
t,
withEmailUsers,
userId,
sectionWidth,
accountsData,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props;
const [hideColumns, setHideColumns] = useState(false);
const tableRef = useRef(null);
const toggleAll = (e) =>
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
const handleToggle = (e, user) => {
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}`;
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{accountsData.length > 0 ? (
<>
<UsersTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
userId={userId}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
setHideColumns={setHideColumns}
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={() => {}}
>
{accountsData.map((data) => (
<UsersTableRow
t={t}
key={data.key}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
hideColumns={hideColumns}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={(e) => 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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
userId,
checkedUsers,
withEmailUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(TableView));

View File

@ -1,63 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
const AccountsTable = (props) => {
const { t, viewAs, accountsData } = props;
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(({ setup }) => {
const { viewAs } = setup;
return {
viewAs,
};
})(withTranslation(["People"])(observer(AccountsTable)));

View File

@ -1,187 +0,0 @@
// (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 AccountsTable from "./AccountsTable";
import AccountsPaging from "../../../sub-components/AccountsPaging";
import UsersInfoBlock from "../../../sub-components/UsersInfoBlock";
import { Wrapper } from "../StyledStepper";
import { parseQuota } from "../../../utils";
const SelectUsersStep = (props) => {
const {
t,
incrementStep,
decrementStep,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
quotaCharacteristics,
users,
} = props;
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
const [quota, setQuota] = useState({ used: 0, max: 0 });
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
setSearchValue("");
setQuota(parseQuota(quotaCharacteristics[1]));
}, []);
const handleDataChange = (leftBoundary, rightBoundary) => {
setDataPortion(withEmailUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
const goBack = () => {
cancelMigration();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
decrementStep();
}, 1000);
};
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={goBack}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
showReminder
displaySettings
isSaving={isSaving}
/>
{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}
/>
<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={goBack}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
showReminder
displaySettings
isSaving={isSaving}
/>
)}
</Wrapper>
);
};
export default inject(({ importAccountsStore, currentQuotaStore }) => {
const {
users,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
return {
users,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
quotaCharacteristics,
};
})(observer(SelectUsersStep));

View File

@ -1,63 +0,0 @@
// (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 { Row } from "@docspace/shared/components/row";
import UsersRowContent from "./UsersRowContent";
const UsersRow = (props) => {
const { data, sectionWidth, typeOptions, isChecked, toggleAccount } = props;
const roleSelectorRef = useRef();
const handleAccountToggle = (e) => {
roleSelectorRef.current?.contains(e.target) || toggleAccount();
};
return (
<Row
sectionWidth={sectionWidth}
key={data.key}
data={data}
checked={isChecked}
contextButtonSpacerWidth="0"
onRowClick={handleAccountToggle}
onSelect={handleAccountToggle}
>
<UsersRowContent
id={data.key}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
type={data.userType}
typeOptions={typeOptions}
roleSelectorRef={roleSelectorRef}
/>
</Row>
);
};
export default UsersRow;

View File

@ -1,154 +0,0 @@
// (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 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 { ComboBox } from "@docspace/shared/components/combobox";
const StyledRowContent = styled(RowContent)`
display: flex;
.row-main-container-wrapper {
width: 100%;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-left: 0px;
`
: css`
margin-right: 0px;
`}
}
.rowMainContainer {
height: 100%;
width: 100%;
}
.username {
font-size: 14px;
font-weight: 600;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.user-email {
margin-right: 5px;
font-size: 12px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.user-type {
.combo-button {
border: none;
padding: 4px 8px;
justify-content: flex-end;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
}
}
`;
const UsersRowContent = ({
id,
sectionWidth,
displayName,
email,
typeOptions,
roleSelectorRef,
type,
changeUserType,
}) => {
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const contentData = [
<Box
key={id}
displayProp="flex"
justifyContent="space-between"
alignItems="center"
>
<Box>
<Text className="username">{displayName}</Text>
<Text className="user-email">{email}</Text>
</Box>
<div ref={roleSelectorRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</Box>,
];
return (
<StyledRowContent sectionWidth={sectionWidth}>
{contentData}
</StyledRowContent>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersRowContent));

View File

@ -1,243 +0,0 @@
// (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 UsersRow from "./UsersRow";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { RowContainer } from "@docspace/shared/components/row-container";
import { Row } from "@docspace/shared/components/row";
import { Text } from "@docspace/shared/components/text";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const StyledRowContainer = styled(RowContainer)`
margin: 0 0 20px;
.table-group-menu {
height: 61px;
position: sticky;
z-index: 201;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: -16px;
`
: css`
margin-left: -16px;
`}
width: 100%;
margin-top: 20px;
top: 61px;
margin-bottom: -29.5px;
.table-container_group-menu {
padding: 0px 16px;
border-image-slice: 0;
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
}
.table-container_group-menu-checkbox {
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: 8px;
`
: css`
margin-left: 8px;
`}
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.header-container-text {
font-size: 12px;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.table-container_header {
position: absolute;
}
.clear-icon {
margin-right: 8px;
}
.ec-desc {
max-width: 348px;
}
`;
const StyledRow = styled(Row)`
box-sizing: border-box;
min-height: 40px;
.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 = "result";
const RowView = (props) => {
const {
t,
sectionWidth,
accountsData,
typeOptions,
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = props;
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const toggleAll = (isChecked) =>
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
const onClearFilter = () => setSearchValue("");
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<StyledRowContainer useReactWindow={false}>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<StyledRow key="Name" sectionWidth={sectionWidth}>
<Text className="row-header-title">{t("Common:Name")}</Text>
</StyledRow>
{accountsData.map((data) => (
<UsersRow
key={data.key}
data={data}
sectionWidth={sectionWidth}
typeOptions={typeOptions}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</>
) : (
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
} = importAccountsStore;
return {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
};
})(observer(RowView));

View File

@ -1,137 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `nextcloudFourthColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
setHideColumns,
isIndeterminate,
isChecked,
} = props;
const defaultColumns = [
{
key: "Name",
title: t("Common:Name"),
resizable: true,
enable: true,
default: true,
active: true,
minWidth: 180,
onChange: onColumnChange,
},
{
key: "Type",
title: t("Common:Type"),
enable: true,
resizable: true,
minWidth: 100,
onChange: onColumnChange,
},
{
key: "Email",
title: t("Common:Email"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
setHideColumns={setHideColumns}
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTableHeader));

View File

@ -1,147 +0,0 @@
// (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 styled from "styled-components";
import { TableRow } from "@docspace/shared/components/table";
import { TableCell } from "@docspace/shared/components/table";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { ComboBox } from "@docspace/shared/components/combobox";
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};
}
.user-type {
.combo-button {
border: none;
padding: 4px 8px;
justify-content: flex-start;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
}
}
`;
const UsersTypeTableRow = ({
id,
displayName,
email,
typeOptions,
isChecked,
toggleAccount,
type,
changeUserType,
}) => {
const userTypeRef = useRef();
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const handleAccountToggle = (e) => {
e.preventDefault();
e.stopPropagation();
e.target.closest(".dropdown-container") ||
userTypeRef.current?.contains(e.target) ||
toggleAccount();
};
return (
<StyledTableRow checked={isChecked} onClick={handleAccountToggle}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={handleAccountToggle} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<div ref={userTypeRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
</StyledTableRow>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersTypeTableRow));

View File

@ -1,242 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { Base } from "@docspace/shared/themes";
import styled, { css } from "styled-components";
import UsersTableHeader from "./UsersTableHeader";
import UsersTableRow from "./UsersTableRow";
import { StyledTableContainer } from "../../../StyledStepper";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { TableBody } from "@docspace/shared/components/table";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const UserSelectTableContainer = styled(StyledTableContainer)`
.table-group-menu {
height: 69px;
position: sticky;
z-index: 201;
width: calc(100% + 40px);
margin-top: -33px;
margin-left: -20px;
top: 0;
margin-bottom: -36px;
.table-container_group-menu {
border-image-slice: 0;
border-image-source: none;
border-bottom: ${(props) =>
props.theme.client.settings.migration.workspaceBorder};
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
padding: 0px;
}
.table-container_group-menu-separator {
margin: 0 16px;
}
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
}
`;
UserSelectTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `nextcloudFourthColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelNextcloudFourthColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "result";
const TableView = (props) => {
const {
t,
userId,
sectionWidth,
accountsData,
typeOptions,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
} = props;
const tableRef = useRef(null);
const [hideColumns, setHideColumns] = useState(false);
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const toggleAll = (isChecked) =>
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
const onClearFilter = () => {
setSearchValue("");
};
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<UserSelectTableContainer forwardedRef={tableRef} useReactWindow>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
checkboxOptions={[]}
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<UsersTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
isIndeterminate={isIndeterminate}
isChecked={checkedUsers.result.length === filteredUsers.length}
toggleAll={toggleAll}
setHideColumns={setHideColumns}
/>
<TableBody
itemHeight={49}
useReactWindow
infoPanelVisible={false}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
filesLength={accountsData.length}
hasMoreFiles={false}
itemCount={accountsData.length}
fetchMoreFiles={() => {}}
>
{accountsData.map((data) => (
<UsersTableRow
key={data.key}
id={data.key}
type={data.userType}
displayName={data.displayName}
email={data.email}
typeOptions={typeOptions}
hideColumns={hideColumns}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</UserSelectTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
} = importAccountsStore;
return {
userId,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
filteredUsers,
};
})(observer(TableView));

View File

@ -1,114 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const checkedAccountType = "result";
const AccountsTable = (props) => {
const {
t,
viewAs,
accountsData,
changeGroupType,
UserTypes,
toggleAllAccounts,
} = props;
const setTypePortalAdmin = () => {
changeGroupType(UserTypes.PortalAdmin);
toggleAllAccounts(false, [], checkedAccountType);
};
const setTypeRoomAdmin = () => {
changeGroupType(UserTypes.RoomAdmin);
toggleAllAccounts(false, [], checkedAccountType);
};
const setTypeUser = () => {
changeGroupType(UserTypes.User);
toggleAllAccounts(false, [], checkedAccountType);
};
const typeOptions = [
{
key: UserTypes.PortalAdmin,
label: t(`Common:PortalAdmin`, {
productName: PRODUCT_NAME,
}),
onClick: setTypePortalAdmin,
},
{
key: UserTypes.RoomAdmin,
label: t(`Common:${UserTypes.RoomAdmin}`),
onClick: setTypeRoomAdmin,
},
{
key: UserTypes.User,
label: t(`Common:PowerUser`),
onClick: setTypeUser,
},
];
return (
<Consumer>
{(context) =>
viewAs === "table" ? (
<TableView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
) : (
<RowView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
)
}
</Consumer>
);
};
export default inject(({ setup, importAccountsStore }) => {
const { viewAs } = setup;
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
return {
viewAs,
changeGroupType,
UserTypes,
toggleAllAccounts,
};
})(
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
);

View File

@ -1,140 +0,0 @@
// (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 { 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 { Wrapper } from "../StyledStepper";
const SelectUsersTypeStep = (props) => {
const {
t,
incrementStep,
decrementStep,
checkedUsers,
users,
searchValue,
setSearchValue,
filteredUsers,
} = props;
const [boundaries, setBoundaries] = useState([0, 25]);
const [dataPortion, setDataPortion] = useState(
filteredUsers.slice(...boundaries),
);
const handleDataChange = (leftBoundary, rightBoundary) => {
setBoundaries([leftBoundary, rightBoundary]);
setDataPortion(filteredUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
useEffect(() => {
setDataPortion(filteredUsers.slice(...boundaries));
}, [users]);
return (
<Wrapper>
<SaveCancelButtons
className="save-cancel-buttons upper-buttons"
onSaveClick={incrementStep}
onCancelClick={decrementStep}
showReminder={true}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
{filteredUsers.length > 0 && (
<>
<SearchInput
id="search-checkedUsers-type-input"
className="importUsersSearch"
placeholder={t("Common:Search")}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{filteredUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={filteredUsers.length}
setDataPortion={handleDataChange}
/>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={incrementStep}
onCancelClick={decrementStep}
showReminder={true}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
)}
</>
)}
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const { checkedUsers, users, searchValue, setSearchValue, filteredUsers } =
importAccountsStore;
return {
checkedUsers,
users,
searchValue,
setSearchValue,
filteredUsers,
};
})(observer(SelectUsersTypeStep));

View File

@ -1,160 +0,0 @@
// (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 { TableContainer } from "@docspace/shared/components/table";
import { Base } from "@docspace/shared/themes";
export const Wrapper = styled.div`
.users-without-email {
font-size: 12px;
margin: 0 0 16px;
}
.upper-buttons {
margin-top: 16px;
margin-bottom: 20px;
}
.data-import-progress-bar {
width: 350px;
margin: 12px 0 16px;
}
.save-cancel-buttons {
margin-bottom: 16px;
}
.mt-8 {
margin-top: 8px;
}
.mb-17 {
margin-bottom: 17px;
}
.importUsersSearch {
margin-top: 20px;
}
.sendLetterBlockWrapper {
display: flex;
align-items: center;
margin: 17px 0 16px;
.checkbox {
margin-right: 8px;
}
}
`;
export const UsersInfoBlock = styled.div`
display: flex;
align-items: center;
max-width: 660px;
background: #f8f9f9;
padding: 12px 16px;
border-radius: 6px;
margin: 16px 0;
.selected-users-count {
margin-right: 24px;
}
.selected-admins-count {
margin-right: 8px;
}
`;
export const StyledTableContainer = styled(TableContainer)`
margin: 0.5px 0px 20px;
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
.header-container-text {
font-size: 12px;
}
.checkboxWrapper {
padding: 0;
padding-inline-start: 8px;
}
.table-list-item {
cursor: pointer;
padding-left: 20px;
&:hover {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
.table-container_cell {
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
margin-left: -24px;
padding-left: 24px;
}
.checkboxWrapper {
padding-left: 32px;
}
.table-container_row-context-menu-wrapper {
margin-right: -20px;
padding-right: 20px;
}
}
}
.table-list-item:has(.selected-table-row) {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
}
.clear-icon {
margin-right: 8px;
margin-top: 2px;
}
.ec-desc {
max-width: 618px;
}
`;
StyledTableContainer.defaultProps = { theme: Base };

View File

@ -1,195 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { HelpButton } from "@docspace/shared/components/help-button";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
margin: 16px 0 16px;
display: flex;
align-items: center;
.checkbox-text {
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
`;
const InfoText = styled(Text)`
margin-top: -8px;
margin-bottom: 8px;
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
`;
const ErrorText = styled(Text)`
font-size: 12px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
margin-bottom: 8px;
`;
const ImportCompleteStep = ({
t,
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
}) => {
const [isChecked, setIsChecked] = useState(false);
const [importResult, setImportResult] = useState({
succeedUsers: 0,
failedUsers: 0,
errors: [],
});
const navigate = useNavigate();
const [isSaving, setIsSaving] = useState(false);
const onDownloadLog = async () => {
try {
await getMigrationLog()
.then((response) => new Blob([response]))
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "migration.log";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
console.log(error);
toastr.error(error);
}
};
const onChangeCheckbox = () => {
setIsChecked((prev) => !prev);
};
const onFinishClick = () => {
if (isChecked) {
sendWelcomeLetter({ isSendWelcomeEmail: true });
}
clearMigration();
clearCheckedAccounts();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
navigate("/portal-settings/data-import/migration")
}, 1000);
};
useEffect(() => {
try {
getMigrationStatus().then((res) =>
setImportResult({
succeedUsers: res.parseResult.successedUsers,
failedUsers: res.parseResult.failedUsers,
errors: res.parseResult.errors,
}),
);
} catch (error) {
toastr.error(error);
}
}, []);
return (
<>
<InfoText>
{t("Settings:ImportedUsers", {
selectedUsers: importResult.succeedUsers,
importedUsers: importResult.succeedUsers + importResult.failedUsers,
})}
</InfoText>
{importResult.failedUsers > 0 && (
<ErrorText>
{t("Settings:ErrorsWereFound", {
errors: importResult.failedUsers,
})}
</ErrorText>
)}
{importResult.errors?.length > 0 && (
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
)}
<Wrapper>
<Checkbox
label={t("Settings:SendInviteLetter")}
isChecked={isChecked}
onChange={onChangeCheckbox}
/>
<HelpButton
place="right"
offsetRight={0}
style={{ margin: "0px 5px" }}
tooltipContent={
<Text fontSize="12px">{t("Settings:InviteLetterTooltip")}</Text>
}
/>
</Wrapper>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onFinishClick}
onCancelClick={onDownloadLog}
saveButtonLabel={t("Common:Finish")}
cancelButtonLabel={t("Settings:DownloadLog")}
displaySettings
showReminder
isSaving={isSaving}
/>
</>
);
};
export default inject(({ importAccountsStore }) => {
const {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
} = importAccountsStore;
return {
getMigrationLog,
clearCheckedAccounts,
sendWelcomeLetter,
clearMigration,
getMigrationStatus,
};
})(observer(ImportCompleteStep));

View File

@ -1,150 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { isTablet } from "@docspace/shared/utils/device";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import styled from "styled-components";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { Button } from "@docspace/shared/components/button";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
max-width: 350px;
.data-import-progress-bar {
margin-top: -8px;
margin-bottom: 16px;
}
`;
const ImportProcessingStep = ({
t,
onNextStep,
isFifthStep,
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
}) => {
const [percent, setPercent] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const uploadInterval = useRef(null);
const handleFileMigration = async () => {
setIsLoading(true);
setPercent(0);
setIsVisible(true);
try {
await proceedFileMigration("Workspace");
uploadInterval.current = setInterval(async () => {
const res = await getMigrationStatus();
setPercent(res.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
if (res.isCompleted || res.progress === 100) {
clearInterval(uploadInterval.current);
setIsLoading(false);
setIsVisible(false);
setPercent(100);
setTimeout(() => {
onNextStep();
}, 1000);
}
}, 1000);
} catch (error) {
console.log(error);
toastr.error(error);
setIsLoading(false);
}
};
// const hideCancelDialog = () => setIsVisible(false);
// const onCancel = () => {
// setIsVisible(true);
// };
// const handleCancelMigration = () => {
// setIsLoading(false);
// cancelMigration();
// }
useEffect(() => {
handleFileMigration();
return () => clearInterval(uploadInterval.current);
}, []);
return (
<Wrapper>
<ProgressBar
percent={percent}
isInfiniteProgress={isVisible}
className="data-import-progress-bar"
/>
{/* <Button
size={isTablet() ? "medium" : "small"}
label={t("Common:CancelButton")}
onClick={onCancel}
/>
{isVisible && (
<CancelUploadDialog
visible={isVisible}
loading={false}
isFifthStep={isFifthStep}
cancelMigration={handleCancelMigration}
onClose={hideCancelDialog}
/>
)} */}
</Wrapper>
);
};
export default inject(({ importAccountsStore }) => {
const {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
} = importAccountsStore;
return {
setIsLoading,
proceedFileMigration,
cancelMigration,
getMigrationStatus,
};
})(observer(ImportProcessingStep));

View File

@ -1,209 +0,0 @@
// (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 styled from "styled-components";
import ImportSection from "../../../sub-components/ImportSection";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import AccountsIcon from "PUBLIC_DIR/images/catalog.accounts.react.svg";
import UserSolidIcon from "PUBLIC_DIR/images/catalog.user.solid.react.svg";
import SharedIcon from "PUBLIC_DIR/images/catalog.old.share.react.svg";
import RoomsIcon from "PUBLIC_DIR/images/catalog.rooms.react.svg";
import PortfolioIcon from "PUBLIC_DIR/images/catalog.portfolio.react.svg";
import ProjectsIcon from "PUBLIC_DIR/images/catalog.projects.react.svg";
import DocumentsIcon from "PUBLIC_DIR/images/catalog.documents.react.svg";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 12px;
.save-cancel-buttons {
margin-top: 4px;
}
`;
const ImportStep = ({
t,
onNextStep,
onPrevStep,
showReminder,
importOptions,
setImportOptions,
user,
}) => {
const onChange = (e, name) => {
const checked = e.target.checked;
setImportOptions({ [name]: checked });
};
const serviceName = "ONLYOFFICE Workspace";
const users =
t("Settings:Employees")[0].toUpperCase() + t("Settings:Employees").slice(1);
return (
<Wrapper>
<ImportSection
isChecked
sectionName={users}
description={t("Settings:UsersSectionDescription")}
exportSection={{
sectionName: t("Common:People"),
workspace: serviceName,
SectionIcon: UserSolidIcon,
}}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: AccountsIcon,
}}
isDisabled
/>
<ImportSection
isChecked={importOptions.importGroups}
onChange={(e) => onChange(e, "importGroups")}
sectionName={t("Common:Groups")}
description={t("Settings:GroupsDescription", { serviceName })}
exportSection={{
sectionName: t("Common:Groups"),
workspace: serviceName,
}}
importSection={{
sectionName: t("Common:Accounts"),
workspace: PRODUCT_NAME,
SectionIcon: AccountsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importPersonalFiles}
onChange={(e) => onChange(e, "importPersonalFiles")}
sectionName={t("Settings:PersonalFiles")}
description={t("Settings:PersonalFilesDescription")}
exportSection={{
sectionName: t("Common:MyDocuments"),
workspace: serviceName,
SectionIcon: UserSolidIcon,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFiles}
onChange={(e) => onChange(e, "importSharedFiles")}
sectionName={t("Settings:SharedFiles")}
description={t("Settings:SharedFilesDescription")}
exportSection={{
sectionName: t("Common:SharedWithMe"),
workspace: serviceName,
SectionIcon: SharedIcon,
}}
importSection={{
sectionName: t("Common:Documents"),
workspace: PRODUCT_NAME,
SectionIcon: DocumentsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importSharedFolders}
onChange={(e) => onChange(e, "importSharedFolders")}
sectionName={t("Settings:SharedFolders")}
description={t("Settings:SharedFoldersDescription")}
exportSection={{
sectionName: t("Common:SharedWithMe"),
workspace: serviceName,
SectionIcon: SharedIcon,
}}
importSection={{
sectionName: t("Common:Rooms"),
workspace: PRODUCT_NAME,
SectionIcon: RoomsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importCommonFiles}
onChange={(e) => onChange(e, "importCommonFiles")}
sectionName={t("Common:CommonFiles")}
description={t("Settings:CommonFilesDescription", {
user: user.displayName,
productName: PRODUCT_NAME,
})}
exportSection={{
sectionName: t("Common:Common"),
workspace: serviceName,
SectionIcon: PortfolioIcon,
}}
importSection={{
sectionName: t("Common:Rooms"),
workspace: PRODUCT_NAME,
SectionIcon: RoomsIcon,
}}
/>
<ImportSection
isChecked={importOptions.importProjectFiles}
onChange={(e) => onChange(e, "importProjectFiles")}
sectionName={t("Common:Projects")}
description={t("Settings:ProjectsDescription")}
exportSection={{
sectionName: t("Common:Projects"),
workspace: serviceName,
SectionIcon: ProjectsIcon,
}}
importSection={{
sectionName: t("Common:Rooms"),
workspace: PRODUCT_NAME,
SectionIcon: RoomsIcon,
}}
/>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
showReminder
/>
</Wrapper>
);
};
export default inject(({ importAccountsStore, userStore }) => {
const { importOptions, setImportOptions } = importAccountsStore;
const { user } = userStore;
return {
user,
importOptions,
setImportOptions,
};
})(observer(ImportStep));

View File

@ -1,420 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { CancelUploadDialog } from "SRC_DIR/components/dialogs";
import { isTablet } from "@docspace/shared/utils/device";
import styled from "styled-components";
import { Text } from "@docspace/shared/components/text";
import { Box } from "@docspace/shared/components/box";
import { Link } from "@docspace/shared/components/link";
import { Button } from "@docspace/shared/components/button";
import { FileInput } from "@docspace/shared/components/file-input";
import { ProgressBar } from "@docspace/shared/components/progress-bar";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { toastr } from "@docspace/shared/components/toast";
const Wrapper = styled.div`
max-width: 350px;
.select-file-title {
font-weight: 600;
line-height: 20px;
margin-bottom: 4px;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.select-file-input {
height: 32px;
margin-bottom: 16px;
.icon-button_svg {
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.fileInputIconColor};
}
}
}
}
.select-file-progress-bar {
margin: 12px 0 16px;
width: 350px;
}
`;
const ErrorBlock = styled.div`
max-width: 700px;
.complete-progress-bar {
margin: 12px 0 16px;
max-width: 350px;
}
.error-text {
font-size: 12px;
margin-bottom: 10px;
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
}
.save-cancel-buttons {
margin-top: 16px;
}
`;
const FAILS_TRIES = 1;
const SelectFileStep = ({
t,
onNextStep,
showReminder,
setShowReminder,
cancelDialogVisble,
setCancelDialogVisible,
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
}) => {
const [progress, setProgress] = useState(0);
const [isVisible, setIsVisible] = useState(false);
const [isError, setIsError] = useState(false);
const [showErrorText, setShowErrorText] = useState(false);
const [isFileError, setIsFileError] = useState(false);
const [fileName, setFileName] = useState(null);
const [searchParams] = useSearchParams();
const isAbort = useRef(false);
const uploadInterval = useRef(null);
const navigate = useNavigate();
const [failTries, setFailsTries] = useState(FAILS_TRIES);
const goBack = () => {
navigate("/portal-settings/data-import/migration");
};
const checkMigrationStatusAndUpdate = async () => {
try {
const res = await getMigrationStatus();
if (!res || res.parseResult.migratorName !== "Workspace") {
clearInterval(uploadInterval.current);
return;
}
if (res.parseResult.operation === "parse" && !res.isCompleted) {
setProgress(res.progress);
setIsFileLoading(true);
} else {
setIsFileLoading(false);
}
setIsFileError(false);
setShowReminder(true);
if (res.parseResult.files?.length > 0) {
setFileName(res.parseResult.files.join(", "));
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
setIsFileError(false);
setShowReminder(false);
setFileName(null);
clearInterval(uploadInterval.current);
} else if (res.isCompleted || res.progress === 100) {
setUsers(res.parseResult);
setShowReminder(true);
onNextStep && onNextStep();
clearInterval(uploadInterval.current);
}
} catch (error) {
toastr.error(error.message || t("Common:SomethingWentWrong"));
setIsFileError(true);
clearInterval(uploadInterval.current);
}
};
useEffect(() => {
setShowReminder(false);
checkMigrationStatusAndUpdate();
uploadInterval.current = setInterval(() => {
checkMigrationStatusAndUpdate();
}, 1000);
return () => clearInterval(uploadInterval.current);
}, []);
const onUploadToServer = () => {
setShowReminder(false);
checkMigrationStatusAndUpdate();
};
const onUploadFile = async (file) => {
setIsVisible(true);
try {
if (Array.isArray(file)) {
setShowErrorText(true);
throw new Error(t("Common:SomethingWentWrong"));
}
await singleFileUploading(file, setProgress, isAbort);
if (isAbort.current) return;
await initMigrationName(searchParams.get("service"));
uploadInterval.current = setInterval(async () => {
try {
const res = await getMigrationStatus();
if (!res && failTries) {
setFailsTries((tries) => tries - 1);
return;
}
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
toastr.error(res.error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
clearInterval(uploadInterval.current);
return;
}
if (res.isCompleted || res.parseResult.progress === 100) {
clearInterval(uploadInterval.current);
setIsFileLoading(false);
setIsVisible(false);
setUsers(res.parseResult);
setShowReminder(true);
}
setProgress(res.progress);
if (res.progress > 10) {
setIsVisible(false);
} else {
setIsVisible(true);
}
if (res.error) {
setShowErrorText(true);
} else {
setShowErrorText(false);
}
} catch (error) {
toastr.error(error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
setIsError(true);
clearInterval(uploadInterval.current);
} finally {
isAbort.current = false;
}
}, 1000);
} catch (error) {
toastr.error(error || t("Common:SomethingWentWrong"));
setIsFileError(true);
setIsFileLoading(false);
}
};
const onSelectFile = (file) => {
setProgress(0);
setIsFileError(false);
setShowReminder(false);
setIsFileLoading(true);
setFailsTries(FAILS_TRIES);
try {
onUploadFile(file);
} catch (error) {
toastr.error(error);
setIsFileLoading(false);
}
};
const onDownloadArchives = async () => {
try {
await getMigrationStatus()
.then(
(res) =>
new Blob([res.parseResult.failedArchives], {
type: "text/csv;charset=utf-8",
}),
)
.then((blob) => {
let a = document.createElement("a");
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = "unsupported_files";
a.click();
window.URL.revokeObjectURL(url);
});
} catch (error) {
toastr.error(error);
}
};
const onCancel = () => {
setCancelDialogVisible(true);
};
const handleCancelMigration = () => {
isAbort.current = true;
setProgress(0);
setIsFileLoading(false);
clearInterval(uploadInterval.current);
cancelMigration();
};
const hideCancelDialog = () => setCancelDialogVisible(false);
return (
<>
<Wrapper>
<Text className="select-file-title">
{t("Settings:ChooseBackupFile")}
</Text>
<FileInput
scale
onInput={onSelectFile}
className="select-file-input"
placeholder={fileName || t("Settings:BackupFile")}
isDisabled={isFileLoading}
accept={[".zip", ".tar", ".tar.gz"]}
/>
</Wrapper>
{isFileLoading ? (
<Wrapper>
<ProgressBar
percent={progress}
isInfiniteProgress={isVisible}
className="select-file-progress-bar"
label={t("Settings:BackupFileUploading")}
/>
<Button
size={isTablet() ? "medium" : "small"}
label={t("Common:CancelButton")}
onClick={onCancel}
/>
</Wrapper>
) : (
<ErrorBlock>
{isFileError && (
<Box>
<ProgressBar
percent={100}
className="complete-progress-bar"
label={t("Common:LoadingIsComplete")}
/>
<Text className="error-text">
{showErrorText
? t("Settings:UnsupportedFilesDescription")
: t("Settings:UnsupportedFilesWithUploadDesc")}
</Text>
<Link
type="action"
isHovered
fontWeight={600}
onClick={onDownloadArchives}
>
{t("Settings:CheckUnsupportedFiles")}
</Link>
</Box>
)}
{isError ? (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onUploadToServer}
onCancelClick={goBack}
saveButtonLabel={t("Settings:UploadToServer")}
cancelButtonLabel={t("Common:Back")}
isSaving={showReminder}
displaySettings
saveButtonDisabled={showReminder}
showReminder
/>
) : (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={goBack}
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
saveButtonDisabled={!showReminder}
showReminder
/>
)}
</ErrorBlock>
)}
{cancelDialogVisble && (
<CancelUploadDialog
visible={cancelDialogVisble}
// loading={isFileLoading}
onClose={hideCancelDialog}
cancelMigration={handleCancelMigration}
/>
)}
</>
);
};
export default inject(({ dialogsStore, importAccountsStore }) => {
const {
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
} = importAccountsStore;
const { cancelUploadDialogVisible, setCancelUploadDialogVisible } =
dialogsStore;
return {
initMigrationName,
singleFileUploading,
getMigrationStatus,
setUsers,
isFileLoading,
setIsFileLoading,
cancelMigration,
cancelDialogVisble: cancelUploadDialogVisible,
setCancelDialogVisible: setCancelUploadDialogVisible,
};
})(observer(SelectFileStep));

View File

@ -1,57 +0,0 @@
// (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";
const UsersRow = (props) => {
const { t, data, sectionWidth, isChecked, toggleAccount } = props;
return (
<>
<Row
sectionWidth={sectionWidth}
data={data}
checkbox
checked={isChecked}
onClick={toggleAccount}
onSelect={toggleAccount}
contextButtonSpacerWidth="0"
>
<UsersRowContent
t={t}
data={data}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
/>
</Row>
</>
);
};
export default UsersRow;

View File

@ -1,99 +0,0 @@
// (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";
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 = ({
t,
data,
sectionWidth,
displayName,
email,
isDuplicate,
}) => {
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

@ -1,195 +0,0 @@
// (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 { 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 } 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 UsersRow from "./UsersRow";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
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 = ({
t,
withEmailUsers,
sectionWidth,
accountsData,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
}) => {
const rowRef = useRef(null);
const toggleAll = (e) => {
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
};
const handleToggle = (user) => 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 forwardedRef={rowRef} useReactWindow={false}>
{accountsData.length > 0 ? (
<>
<StyledRow sectionWidth={sectionWidth}>
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
withEmailUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
withEmailUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(RowView));

View File

@ -1,140 +0,0 @@
// (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 { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `GoogleWorkspaceColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
isIndeterminate,
isChecked,
toggleAll,
} = props;
const defaultColumns = [
{
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: "Dublicate",
title: t("Settings:DuplicateNoun"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTableHeader));

View File

@ -1,100 +0,0 @@
// (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 } from "@docspace/shared/components/table";
import { 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";
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 = ({
t,
displayName,
email,
isDuplicate,
isChecked,
toggleAccount,
}) => {
return (
<StyledTableRow checked={isChecked} onClick={toggleAccount}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={toggleAccount} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
<TableCell>
{isDuplicate ? (
<Text className="user-existing">{t("Settings:AccountAlreadyExists")}</Text>
) : (
<Text className="not-existing">{NOT_EXIST}</Text>
)}
</TableCell>
</StyledTableRow>
);
};
export default UsersTableRow;

View File

@ -1,246 +0,0 @@
// (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 { Base } from "@docspace/shared/themes";
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 } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import UsersTableHeader from "./UsersTableHeader";
import UsersTableRow from "./UsersTableRow";
import { TableContainer } from "@docspace/shared/components/table";
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";
const StyledTableContainer = styled(TableContainer)`
margin: 0 0 20px;
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
.header-container-text {
font-size: 12px;
}
.checkboxWrapper {
padding: 0;
padding-inline-start: 8px;
}
.table-list-item {
cursor: pointer;
padding-left: 20px;
&:hover {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
.table-container_cell {
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
margin-left: -24px;
padding-left: 24px;
}
.checkboxWrapper {
padding-left: 32px;
}
.table-container_row-context-menu-wrapper {
margin-right: -20px;
padding-right: 20px;
}
}
}
.table-list-item:has(.selected-table-row) {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
}
.clear-icon {
margin-right: 8px;
margin-top: 2px;
}
.ec-desc {
max-width: 618px;
}
`;
StyledTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `googleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelGoogleWorkspaceColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "withEmail";
const TableView = ({
t,
withEmailUsers,
userId,
sectionWidth,
accountsData,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
}) => {
const tableRef = useRef(null);
const toggleAll = (e) => {
toggleAllAccounts(e.target.checked, withEmailUsers, checkedAccountType);
};
const handleToggle = (e, user) => {
e.stopPropagation();
toggleAccount(user, checkedAccountType);
};
const onClearFilter = () => {
setSearchValue("");
};
const isIndeterminate =
checkedUsers.withEmail.length > 0 &&
checkedUsers.withEmail.length !== withEmailUsers.length;
const isChecked = checkedUsers.withEmail.length === withEmailUsers.length;
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{accountsData.length > 0 ? (
<>
<UsersTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
userId={userId}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
isIndeterminate={isIndeterminate}
isChecked={isChecked}
toggleAll={toggleAll}
/>
<TableBody
itemHeight={49}
useReactWindow
infoPanelVisible={false}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
filesLength={accountsData.length}
hasMoreFiles={false}
itemCount={accountsData.length}
fetchMoreFiles={() => {}}
>
{accountsData.map((data) => (
<UsersTableRow
t={t}
key={data.key}
displayName={data.displayName}
email={data.email}
isDuplicate={data.isDuplicate}
data={data}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={(e) => 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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
withEmailUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
withEmailUsers,
userId,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(TableView));

View File

@ -1,62 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
const AccountsTable = ({ t, viewAs, accountsData }) => {
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(({ setup }) => {
const { viewAs } = setup;
return {
viewAs,
};
})(withTranslation(["People"])(observer(AccountsTable)));

View File

@ -1,185 +0,0 @@
// (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 AccountsTable from "./AccountsTable";
import AccountsPaging from "../../../sub-components/AccountsPaging";
import UsersInfoBlock from "./../../../sub-components/UsersInfoBlock";
import { parseQuota } from "../../../utils";
const SelectUsersStep = ({
t,
onNextStep,
onPrevStep,
withEmailUsers,
setResultUsers,
areCheckedUsersEmpty,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
quotaCharacteristics,
}) => {
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
const [quota, setQuota] = useState({ used: 0, max: 0 });
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
setSearchValue("");
setQuota(parseQuota(quotaCharacteristics[1]));
}, []);
const handleDataChange = (leftBoundary, rightBoundary) => {
setDataPortion(withEmailUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
const handleStepIncrement = () => {
setResultUsers();
onNextStep();
};
const goBack = () => {
cancelMigration();
setIsSaving(true);
setTimeout(() => {
setIsSaving(false);
onPrevStep();
}, 1000);
};
const totalUsedUsers =
quota.used +
checkedUsers.withEmail.filter((user) => !user.isDuplicate).length;
return (
<>
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={handleStepIncrement}
onCancelClick={goBack}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
saveButtonDisabled={
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
}
isSaving={isSaving}
/>
{quota.max && (
<UsersInfoBlock
t={t}
totalUsedUsers={totalUsedUsers}
selectedUsers={checkedUsers.withEmail.length}
totalUsers={withEmailUsers.length}
totalLicenceLimit={quota.max}
/>
)}
<SearchInput
id="search-users-input"
placeholder={t("Common:Search")}
style={{ marginTop: "20px" }}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{withEmailUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={withEmailUsers.length}
setDataPortion={handleDataChange}
/>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={handleStepIncrement}
onCancelClick={goBack}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
saveButtonDisabled={
areCheckedUsersEmpty || (quota.max && totalUsedUsers > quota.max)
}
isSaving={isSaving}
/>
)}
</>
);
};
export default inject(({ importAccountsStore, currentQuotaStore }) => {
const {
withEmailUsers,
searchValue,
setSearchValue,
setResultUsers,
areCheckedUsersEmpty,
cancelMigration,
checkedUsers,
} = importAccountsStore;
const { quotaCharacteristics } = currentQuotaStore;
return {
setResultUsers,
areCheckedUsersEmpty,
withEmailUsers,
searchValue,
setSearchValue,
cancelMigration,
checkedUsers,
quotaCharacteristics,
};
})(observer(SelectUsersStep));

View File

@ -1,67 +0,0 @@
// (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 { Row } from "@docspace/shared/components/row";
import UsersTypeRowContent from "./UsersTypeRowContent";
const UsersTypeRow = ({
data,
sectionWidth,
typeOptions,
isChecked,
toggleAccount,
}) => {
const roleSelectorRef = useRef();
const handleAccountToggle = (e) => {
roleSelectorRef.current?.contains(e.target) || toggleAccount();
};
return (
<Row
sectionWidth={sectionWidth}
key={data.key}
data={data}
checked={isChecked}
contextButtonSpacerWidth="0"
onRowClick={handleAccountToggle}
onSelect={handleAccountToggle}
>
<UsersTypeRowContent
id={data.key}
sectionWidth={sectionWidth}
displayName={data.displayName}
email={data.email}
type={data.userType}
typeOptions={typeOptions}
roleSelectorRef={roleSelectorRef}
/>
</Row>
);
};
export default UsersTypeRow;

View File

@ -1,154 +0,0 @@
// (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 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 { ComboBox } from "@docspace/shared/components/combobox";
const StyledRowContent = styled(RowContent)`
display: flex;
.row-main-container-wrapper {
width: 100%;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-left: 0px;
`
: css`
margin-right: 0px;
`}
}
.rowMainContainer {
height: 100%;
width: 100%;
}
.username {
font-size: 14px;
font-weight: 600;
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
}
.user-email {
margin-right: 5px;
font-size: 12px;
font-weight: 600;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.user-type {
.combo-button {
border: none;
padding: 5px;
justify-content: flex-end;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
}
}
`;
const UsersRowContent = ({
id,
sectionWidth,
displayName,
email,
typeOptions,
roleSelectorRef,
type,
changeUserType,
}) => {
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const contentData = [
<Box
key={id}
displayProp="flex"
justifyContent="space-between"
alignItems="center"
>
<Box>
<Text className="username">{displayName}</Text>
<Text className="user-email">{email}</Text>
</Box>
<div ref={roleSelectorRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</Box>,
];
return (
<StyledRowContent sectionWidth={sectionWidth}>
{contentData}
</StyledRowContent>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersRowContent));

View File

@ -1,245 +0,0 @@
// (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 UsersTypeRow from "./UsersTypeRow";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { RowContainer } from "@docspace/shared/components/row-container";
import { Row } from "@docspace/shared/components/row";
import { Text } from "@docspace/shared/components/text";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const StyledRowContainer = styled(RowContainer)`
margin: 0 0 20px;
.table-group-menu {
height: 61px;
position: sticky;
z-index: 201;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: -16px;
`
: css`
margin-left: -16px;
`}
width: 100%;
margin-top: 20px;
top: 61px;
margin-bottom: -29.5px;
.table-container_group-menu {
padding: 0px 16px;
border-image-slice: 0;
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
}
.table-container_group-menu-checkbox {
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-right: 8px;
`
: css`
margin-left: 8px;
`}
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.header-container-text {
font-size: 12px;
color: ${(props) =>
props.theme.client.settings.migration.tableRowTextColor};
}
.table-container_header {
position: absolute;
}
.clear-icon {
margin-right: 8px;
}
.ec-desc {
max-width: 348px;
}
`;
const StyledRow = styled(Row)`
box-sizing: border-box;
min-height: 40px;
.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 = "result";
const RowView = ({
t,
sectionWidth,
accountsData,
typeOptions,
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
}) => {
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const isChecked = checkedUsers.result.length === filteredUsers.length;
const toggleAll = (isChecked) =>
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
const onClearFilter = () => {
setSearchValue("");
};
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<StyledRowContainer useReactWindow={false}>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={isChecked}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<StyledRow key="Name" sectionWidth={sectionWidth} onClick={toggleAll}>
<Text className="row-header-title">{t("Common:Name")}</Text>
</StyledRow>
{accountsData.map((data) => (
<UsersTypeRow
key={data.key}
data={data}
sectionWidth={sectionWidth}
typeOptions={typeOptions}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</>
) : (
<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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledRowContainer>
);
};
export default inject(({ importAccountsStore }) => {
const {
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(RowView));

View File

@ -1,137 +0,0 @@
// (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 { inject, observer } from "mobx-react";
import { TableHeader } from "@docspace/shared/components/table";
const TABLE_VERSION = "6";
const TABLE_COLUMNS = `nextcloudFourthColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
const columns = [];
if (storageColumns) {
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;
}
};
const UsersTypeTableHeader = (props) => {
const {
t,
userId,
sectionWidth,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
setHideColumns,
isIndeterminate,
isChecked,
} = props;
const defaultColumns = [
{
key: "Name",
title: t("Common:Name"),
resizable: true,
enable: true,
default: true,
active: true,
minWidth: 180,
onChange: onColumnChange,
},
{
key: "Type",
title: t("Common:Type"),
enable: true,
resizable: true,
minWidth: 100,
onChange: onColumnChange,
},
{
key: "Email",
title: t("Common:Email"),
enable: true,
resizable: true,
onChange: onColumnChange,
},
];
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));
}, [isIndeterminate, isChecked]);
return (
<TableHeader
checkboxSize="48px"
containerRef={tableRef}
columns={columns}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
sectionWidth={sectionWidth}
checkboxMargin="12px"
showSettings={false}
useReactWindow
setHideColumns={setHideColumns}
infoPanelVisible={false}
/>
);
};
export default inject(({ userStore }) => {
return {
userId: userStore.user.id,
};
})(observer(UsersTypeTableHeader));

View File

@ -1,146 +0,0 @@
// (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 styled from "styled-components";
import { TableRow } from "@docspace/shared/components/table";
import { TableCell } from "@docspace/shared/components/table";
import { Text } from "@docspace/shared/components/text";
import { Checkbox } from "@docspace/shared/components/checkbox";
import { ComboBox } from "@docspace/shared/components/combobox";
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};
}
.user-type {
.combo-button {
border: none;
padding: 4px 8px;
justify-content: flex-start;
background-color: transparent;
}
.combo-button-label {
color: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
.combo-buttons_arrow-icon {
flex: initial;
margin-right: 0px;
}
svg {
path {
fill: ${(props) =>
props.theme.client.settings.migration.comboBoxLabelColor};
}
}
}
`;
const UsersTypeTableRow = ({
id,
displayName,
email,
typeOptions,
isChecked,
toggleAccount,
type,
changeUserType,
}) => {
const roleSelectorRef = useRef();
const onSelectUser = (e) => {
changeUserType(id, e.key);
};
const selectedOption =
typeOptions.find((option) => option.key === type) || {};
const handleAccountToggle = (e) => {
e.preventDefault();
e.stopPropagation();
e.target.closest(".dropdown-container") ||
roleSelectorRef.current?.contains(e.target) ||
toggleAccount(e);
};
return (
<StyledTableRow checked={isChecked} onClick={handleAccountToggle}>
<TableCell className="checkboxWrapper">
<Checkbox isChecked={isChecked} onChange={handleAccountToggle} />
<Text className="username">{displayName}</Text>
</TableCell>
<TableCell>
<div ref={roleSelectorRef}>
<ComboBox
className="user-type"
selectedOption={selectedOption}
options={typeOptions}
onSelect={onSelectUser}
scaled
size="content"
displaySelectedOption
modernView
manualWidth="fit-content"
/>
</div>
</TableCell>
<TableCell>
<Text className="user-email">{email}</Text>
</TableCell>
</StyledTableRow>
);
};
export default inject(({ importAccountsStore }) => {
const { changeUserType } = importAccountsStore;
return {
changeUserType,
};
})(observer(UsersTypeTableRow));

View File

@ -1,298 +0,0 @@
// (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, useRef } from "react";
import { inject, observer } from "mobx-react";
import { Base } from "@docspace/shared/themes";
import styled, { css } from "styled-components";
import UsersTypeTableHeader from "./UsersTypeTableHeader";
import UsersTypeTableRow from "./UsersTypeTableRow";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
import { Box } from "@docspace/shared/components/box";
import { TableGroupMenu } from "@docspace/shared/components/table";
import { TableContainer } from "@docspace/shared/components/table";
import { TableBody } from "@docspace/shared/components/table/TableBody";
import ChangeTypeReactSvgUrl from "PUBLIC_DIR/images/change.type.react.svg?url";
import EmptyScreenUserReactSvgUrl from "PUBLIC_DIR/images/empty_screen_user.react.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
const StyledTableContainer = styled(TableContainer)`
margin: 0 0 20px;
.table-group-menu {
height: 69px;
position: sticky;
z-index: 201;
width: calc(100% + 40px);
margin-top: -33px;
margin-left: -20px;
top: 0;
margin-bottom: -36px;
.table-container_group-menu {
border-image-slice: 0;
border-image-source: none;
border-bottom: ${(props) =>
props.theme.client.settings.migration.workspaceBorder};
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
padding: 0px;
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.table-container_header {
position: absolute;
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
padding: 0px 28px 0 15px;
`
: css`
padding: 0px 15px 0 28px;
`}
}
.header-container-text {
font-size: 12px;
}
.checkboxWrapper {
padding: 0;
padding-inline-start: 8px;
}
.table-list-item {
cursor: pointer;
padding-left: 20px;
&:hover {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
.table-container_cell {
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
margin-left: -24px;
padding-left: 24px;
}
.checkboxWrapper {
padding-left: 32px;
}
.table-container_row-context-menu-wrapper {
margin-right: -20px;
padding-right: 20px;
}
}
}
.table-list-item:has(.selected-table-row) {
background-color: ${(props) =>
props.theme.filesSection.tableView.row.backgroundActive};
}
.clear-icon {
margin-right: 8px;
margin-top: 2px;
}
.ec-desc {
max-width: 618px;
}
`;
StyledTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const COLUMNS_SIZE = `nextcloudFourthColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelNextcloudFourthColumnsSize_ver-${TABLE_VERSION}`;
const checkedAccountType = "result";
const TableView = ({
t,
userId,
sectionWidth,
accountsData,
typeOptions,
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
}) => {
const tableRef = useRef(null);
const [hideColumns, setHideColumns] = useState(false);
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
const isIndeterminate =
checkedUsers.result.length > 0 &&
checkedUsers.result.length !== filteredUsers.length;
const isChecked = checkedUsers.result.length === filteredUsers.length;
const toggleAll = (isChecked) => {
toggleAllAccounts(isChecked, filteredUsers, checkedAccountType);
};
const onClearFilter = () => {
setSearchValue("");
};
const headerMenu = [
{
id: "change-type",
key: "change-type",
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
disabled: false,
withDropDown: true,
options: typeOptions,
iconUrl: ChangeTypeReactSvgUrl,
onClick: () => {},
},
];
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{checkedUsers.result.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
checkboxOptions={[]}
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
isIndeterminate={isIndeterminate}
isChecked={isChecked}
onChange={toggleAll}
/>
</div>
)}
{accountsData.length > 0 ? (
<>
<UsersTypeTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
isIndeterminate={isIndeterminate}
isChecked={isChecked}
toggleAll={toggleAll}
setHideColumns={setHideColumns}
/>
<TableBody
itemHeight={49}
useReactWindow
infoPanelVisible={false}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
filesLength={accountsData.length}
hasMoreFiles={false}
itemCount={accountsData.length}
fetchMoreFiles={() => {}}
>
{accountsData.map((data) => (
<UsersTypeTableRow
key={data.key}
id={data.key}
type={data.userType}
displayName={data.displayName}
email={data.email}
typeOptions={typeOptions}
hideColumns={hideColumns}
isChecked={isAccountChecked(data.key, checkedAccountType)}
toggleAccount={() => toggleAccount(data, checkedAccountType)}
/>
))}
</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="action"
isHovered={true}
fontWeight="600"
onClick={onClearFilter}
>
{t("Common:ClearFilter")}
</Link>
</Box>
}
/>
)}
</StyledTableContainer>
);
};
export default inject(({ userStore, importAccountsStore }) => {
const { id: userId } = userStore.user;
const {
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
} = importAccountsStore;
return {
userId,
filteredUsers,
checkedUsers,
toggleAccount,
toggleAllAccounts,
isAccountChecked,
setSearchValue,
};
})(observer(TableView));

View File

@ -1,106 +0,0 @@
// (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 { withTranslation } from "react-i18next";
import { Consumer } from "@docspace/shared/utils/context";
import TableView from "./TableView";
import RowView from "./RowView";
import { PRODUCT_NAME } from "@docspace/shared/constants";
const checkedAccountType = "result";
const AccountsTable = ({
t,
viewAs,
accountsData,
changeGroupType,
UserTypes,
toggleAllAccounts,
}) => {
const typeOptions = [
{
key: UserTypes.PortalAdmin,
label: t("Common:PortalAdmin", { productName: PRODUCT_NAME }),
onClick: () => {
changeGroupType(UserTypes.PortalAdmin);
toggleAllAccounts(false, [], checkedAccountType);
},
},
{
key: UserTypes.RoomAdmin,
label: t("Common:RoomAdmin"),
onClick: () => {
changeGroupType(UserTypes.RoomAdmin);
toggleAllAccounts(false, [], checkedAccountType);
},
},
{
key: UserTypes.User,
label: t("Common:PowerUser"),
onClick: () => {
changeGroupType(UserTypes.User);
toggleAllAccounts(false, [], checkedAccountType);
},
},
];
return (
<Consumer>
{(context) =>
viewAs === "table" ? (
<TableView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
) : (
<RowView
t={t}
sectionWidth={context.sectionWidth}
accountsData={accountsData}
typeOptions={typeOptions}
/>
)
}
</Consumer>
);
};
export default inject(({ setup, importAccountsStore }) => {
const { viewAs } = setup;
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
return {
viewAs,
changeGroupType,
UserTypes,
toggleAllAccounts,
};
})(
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
);

View File

@ -1,137 +0,0 @@
// (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 { 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";
const SelectUsersTypeStep = ({
t,
onNextStep,
onPrevStep,
showReminder,
users,
checkedUsers,
searchValue,
setSearchValue,
filteredUsers,
}) => {
const [boundaries, setBoundaries] = useState([0, 25]);
const [dataPortion, setDataPortion] = useState(
filteredUsers.slice(...boundaries),
);
const handleDataChange = (leftBoundary, rightBoundary) => {
setBoundaries([leftBoundary, rightBoundary]);
setDataPortion(filteredUsers.slice(leftBoundary, rightBoundary));
};
const onChangeInput = (value) => {
setSearchValue(value);
};
const onClearSearchInput = () => {
setSearchValue("");
};
const filteredAccounts = dataPortion.filter(
(data) =>
data.firstName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.lastName?.toLowerCase().startsWith(searchValue.toLowerCase()) ||
data.email?.toLowerCase().startsWith(searchValue.toLowerCase()),
);
useEffect(() => {
setDataPortion(filteredUsers.slice(...boundaries));
}, [users]);
return (
<>
<SaveCancelButtons
className="save-cancel-buttons upper-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
{filteredUsers.length > 0 && (
<>
<SearchInput
id="search-users-type-input"
placeholder={t("Common:Search")}
style={{ marginTop: "20px" }}
value={searchValue}
onChange={onChangeInput}
refreshTimeout={100}
onClearSearch={onClearSearchInput}
/>
<AccountsTable t={t} accountsData={filteredAccounts} />
{filteredUsers.length > 25 && filteredAccounts.length > 0 && (
<AccountsPaging
t={t}
numberOfItems={filteredUsers.length}
setDataPortion={handleDataChange}
/>
)}
{filteredAccounts.length > 0 && (
<SaveCancelButtons
className="save-cancel-buttons"
onSaveClick={onNextStep}
onCancelClick={onPrevStep}
showReminder
saveButtonLabel={t("Settings:NextStep")}
cancelButtonLabel={t("Common:Back")}
displaySettings
/>
)}
</>
)}
</>
);
};
export default inject(({ importAccountsStore }) => {
const { users, checkedUsers, searchValue, setSearchValue, filteredUsers } =
importAccountsStore;
return {
users,
checkedUsers,
searchValue,
setSearchValue,
filteredUsers,
};
})(observer(SelectUsersTypeStep));