Web: Client: Data Import: remove old steps
This commit is contained in:
parent
b01b9915ca
commit
1adfb662fa
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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)));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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)),
|
||||
);
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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)));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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)),
|
||||
);
|
@ -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));
|
@ -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 };
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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)));
|
@ -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));
|
@ -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;
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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));
|
@ -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)),
|
||||
);
|
@ -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));
|
Loading…
Reference in New Issue
Block a user