diff --git a/products/ASC.Files/Client/src/components/Article/Body/TreeFolders.js b/products/ASC.Files/Client/src/components/Article/Body/TreeFolders.js
index c0f5bb2eb03..b5b6011d324 100644
--- a/products/ASC.Files/Client/src/components/Article/Body/TreeFolders.js
+++ b/products/ASC.Files/Client/src/components/Article/Body/TreeFolders.js
@@ -436,13 +436,13 @@ class TreeFolders extends React.Component {
const {
selectedKeys,
isLoading,
- setIsLoading,
onSelect,
dragging,
expandedKeys,
expandedPanelKeys,
treeFolders,
data,
+ disabled,
} = this.props;
return (
@@ -450,7 +450,7 @@ class TreeFolders extends React.Component {
className="files-tree-menu"
checkable={false}
draggable={dragging}
- disabled={isLoading}
+ disabled={isLoading || disabled}
multiple={false}
showIcon
switcherIcon={this.switcherIcon}
diff --git a/products/ASC.Files/Client/src/components/dialogs/ConflictResolveDialog/index.js b/products/ASC.Files/Client/src/components/dialogs/ConflictResolveDialog/index.js
index 6efab2f9fb3..d71895efc1f 100644
--- a/products/ASC.Files/Client/src/components/dialogs/ConflictResolveDialog/index.js
+++ b/products/ASC.Files/Client/src/components/dialogs/ConflictResolveDialog/index.js
@@ -1,6 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
-import ModalDialogContainer from "../ModalDialogContainer";
import ModalDialog from "@appserver/components/modal-dialog";
import RadioButtonGroup from "@appserver/components/radio-button-group";
import Button from "@appserver/components/button";
@@ -9,6 +8,26 @@ import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { ConflictResolveType } from "@appserver/common/constants";
import toastr from "studio/toastr";
+import styled from "styled-components";
+
+const StyledModalDialog = styled(ModalDialog)`
+ .conflict-resolve-dialog-text {
+ padding-bottom: 8px;
+ }
+
+ .conflict-resolve-radio-button {
+ svg {
+ overflow: visible;
+ }
+ }
+
+ .modal-dialog-aside-footer {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 10px;
+ width: 90%;
+ }
+`;
const ConflictResolveDialog = (props) => {
const {
@@ -21,6 +40,8 @@ const ConflictResolveDialog = (props) => {
itemOperationToFolder,
activeFiles,
setActiveFiles,
+ setMoveToPanelVisible,
+ setThirdPartyMoveDialogVisible,
} = props;
const {
@@ -37,6 +58,11 @@ const ConflictResolveDialog = (props) => {
const onSelectResolveType = (e) => setResolveType(e.target.value);
const onClose = () => setConflictResolveDialogVisible(false);
+ const onClosePanels = () => {
+ setConflictResolveDialogVisible(false);
+ setMoveToPanelVisible(false);
+ setThirdPartyMoveDialogVisible(false);
+ };
const onCloseDialog = () => {
let newActiveFiles = activeFiles;
@@ -75,7 +101,7 @@ const ConflictResolveDialog = (props) => {
}
setActiveFiles(newActiveFiles);
- if (!folderIds.length && !newFileIds.length) return onClose();
+ if (!folderIds.length && !newFileIds.length) return onClosePanels();
const data = {
destFolderId,
@@ -87,7 +113,7 @@ const ConflictResolveDialog = (props) => {
translations,
};
- onClose();
+ onClosePanels();
try {
await itemOperationToFolder(data);
} catch (error) {
@@ -131,10 +157,11 @@ const ConflictResolveDialog = (props) => {
const file = items[0].title;
return (
-
{t("ConflictResolveTitle")}
@@ -167,6 +194,7 @@ const ConflictResolveDialog = (props) => {
label={t("Common:OKButton")}
size="medium"
primary
+ scale
onClick={onAcceptType}
//isLoading={isLoading}
/>
@@ -175,11 +203,12 @@ const ConflictResolveDialog = (props) => {
key="CancelButton"
label={t("Common:CancelButton")}
size="medium"
+ scale
onClick={onCloseDialog}
//isLoading={isLoading}
/>
-
+
);
};
@@ -189,6 +218,8 @@ export default inject(({ dialogsStore, uploadDataStore, filesStore }) => {
setConflictResolveDialogVisible,
conflictResolveDialogData,
conflictResolveDialogItems: items,
+ setMoveToPanelVisible,
+ setThirdPartyMoveDialogVisible,
} = dialogsStore;
const { itemOperationToFolder } = uploadDataStore;
@@ -202,6 +233,8 @@ export default inject(({ dialogsStore, uploadDataStore, filesStore }) => {
itemOperationToFolder,
activeFiles,
setActiveFiles,
+ setMoveToPanelVisible,
+ setThirdPartyMoveDialogVisible,
};
})(
withRouter(
diff --git a/products/ASC.Files/Client/src/components/dialogs/ModalDialogContainer.js b/products/ASC.Files/Client/src/components/dialogs/ModalDialogContainer.js
index 476dd3720a3..5ddffcd8e06 100644
--- a/products/ASC.Files/Client/src/components/dialogs/ModalDialogContainer.js
+++ b/products/ASC.Files/Client/src/components/dialogs/ModalDialogContainer.js
@@ -147,16 +147,6 @@ const ModalDialogContainer = styled(ModalDialog)`
width: 90%;
}
}
-
- .conflict-resolve-dialog-text {
- padding-bottom: 8px;
- }
-
- .conflict-resolve-radio-button {
- svg {
- overflow: visible;
- }
- }
`;
export default ModalDialogContainer;
diff --git a/products/ASC.Files/Client/src/components/dialogs/ThirdPartyMoveDialog/index.js b/products/ASC.Files/Client/src/components/dialogs/ThirdPartyMoveDialog/index.js
index 12a9f81f596..01e6c4a2d49 100644
--- a/products/ASC.Files/Client/src/components/dialogs/ThirdPartyMoveDialog/index.js
+++ b/products/ASC.Files/Client/src/components/dialogs/ThirdPartyMoveDialog/index.js
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useState } from "react";
import styled from "styled-components";
import { withTranslation } from "react-i18next";
@@ -6,11 +6,17 @@ import ModalDialog from "@appserver/components/modal-dialog";
import Text from "@appserver/components/text";
import Button from "@appserver/components/button";
import { inject, observer } from "mobx-react";
+import toastr from "@appserver/components/toast/toastr";
const StyledOperationDialog = styled(ModalDialog)`
.operation-button {
margin-right: 8px;
}
+
+ .modal-dialog-aside-footer {
+ display: flex;
+ width: 90%;
+ }
`;
const PureThirdPartyMoveContainer = ({
@@ -21,13 +27,16 @@ const PureThirdPartyMoveContainer = ({
selection,
destFolderId,
setDestFolderId,
- checkOperationConflict,
+ checkFileConflicts,
+ setConflictDialogData,
setThirdPartyMoveDialogVisible,
setBufferSelection,
}) => {
const zIndex = 310;
const deleteAfter = false; // TODO: get from settings
+ const [isLoading, setIsLoading] = useState(false);
+
const onClose = () => {
setBufferSelection(null);
setDestFolderId(false);
@@ -59,8 +68,22 @@ const PureThirdPartyMoveContainer = ({
},
};
- checkOperationConflict(data);
- onClose();
+ setIsLoading(true);
+ checkFileConflicts(destFolderId, folderIds, fileIds)
+ .then(async (conflicts) => {
+ if (conflicts.length) {
+ setConflictDialogData(conflicts, data);
+ setIsLoading(false);
+ } else {
+ setIsLoading(false);
+ onClose();
+ await itemOperationToFolder(data);
+ }
+ })
+ .catch((err) => toastr.error(err))
+ .finally(() => {
+ setIsLoading(false);
+ });
};
return (
@@ -69,6 +92,7 @@ const PureThirdPartyMoveContainer = ({
visible={visible}
zIndex={zIndex}
onClose={onClose}
+ displayType="aside"
>
{t("MoveConfirmation")}
@@ -82,21 +106,30 @@ const PureThirdPartyMoveContainer = ({
className="operation-button"
label={t("Translations:Move")}
size="big"
+ scale
primary
onClick={startOperation}
+ isLoading={isLoading}
+ isDisabled={isLoading}
/>
@@ -111,7 +144,7 @@ export default inject(({ filesStore, dialogsStore, filesActionsStore }) => {
setDestFolderId,
} = dialogsStore;
const { bufferSelection, setBufferSelection } = filesStore;
- const { checkOperationConflict } = filesActionsStore;
+ const { checkFileConflicts, setConflictDialogData } = filesActionsStore;
const selection = filesStore.selection.length
? filesStore.selection
@@ -123,9 +156,10 @@ export default inject(({ filesStore, dialogsStore, filesActionsStore }) => {
destFolderId,
setDestFolderId,
provider: selection[0].providerKey,
- checkOperationConflict,
+ checkFileConflicts,
selection,
setBufferSelection,
+ setConflictDialogData,
};
})(
withTranslation(["ThirdPartyMoveDialog", "Common", "Translations"])(
diff --git a/products/ASC.Files/Client/src/components/panels/OperationsPanel/index.js b/products/ASC.Files/Client/src/components/panels/OperationsPanel/index.js
index 6fa619142a7..e13d4c42237 100644
--- a/products/ASC.Files/Client/src/components/panels/OperationsPanel/index.js
+++ b/products/ASC.Files/Client/src/components/panels/OperationsPanel/index.js
@@ -1,11 +1,18 @@
-import React from "react";
+import React, { useState } from "react";
import { withRouter } from "react-router";
import ModalDialog from "@appserver/components/modal-dialog";
import { withTranslation } from "react-i18next";
-import { StyledAsidePanel } from "../StyledPanels";
import TreeFolders from "../../Article/Body/TreeFolders";
import { inject, observer } from "mobx-react";
import toastr from "studio/toastr";
+import Button from "@appserver/components/button";
+import styled from "styled-components";
+
+const StyledModalDialog = styled(ModalDialog)`
+ .modal-dialog-aside-footer {
+ width: 90%;
+ }
+`;
const OperationsPanelComponent = (props) => {
const {
@@ -23,7 +30,9 @@ const OperationsPanelComponent = (props) => {
setCopyPanelVisible,
setExpandedPanelKeys,
setMoveToPanelVisible,
- checkOperationConflict,
+ setConflictDialogData,
+ itemOperationToFolder,
+ checkFileConflicts,
setThirdPartyMoveDialogVisible,
} = props;
@@ -32,36 +41,40 @@ const OperationsPanelComponent = (props) => {
const expandedKeys = props.expandedKeys.map((item) => item.toString());
+ const [isLoading, setIsLoading] = useState(false);
+ const [selectedFolder, setSelectedFolder] = useState(null);
+ const [folderTitle, setFolderTitle] = useState(null);
+ const [providerKey, setProviderKey] = useState(null);
+
const onClose = () => {
isCopy ? setCopyPanelVisible(false) : setMoveToPanelVisible(false);
setExpandedPanelKeys(null);
};
- const onSelect = (folder, treeNode) => {
- const folderTitle = treeNode.node.props.title;
- const destFolderId = isNaN(+folder[0]) ? folder[0] : +folder[0];
-
- if (currentFolderId === destFolderId) {
- return onClose();
+ const onSubmit = () => {
+ if (currentFolderId === selectedFolder) {
+ return;
}
if (isCopy) {
- startOperation(isCopy, destFolderId, folderTitle);
+ startOperation(isCopy, selectedFolder, folderTitle);
} else {
- if (
- provider &&
- treeNode.node.props.providerKey !== provider.providerKey
- ) {
- setDestFolderId(destFolderId);
+ if (provider && providerKey !== provider.providerKey) {
+ setDestFolderId(selectedFolder);
setThirdPartyMoveDialogVisible(true);
} else {
- startOperation(isCopy, destFolderId, folderTitle);
+ startOperation(isCopy, selectedFolder, folderTitle);
}
}
- onClose();
};
- const startOperation = (isCopy, destFolderId, folderTitle) => {
+ const onSelect = (folder, treeNode) => {
+ setProviderKey(treeNode.node.props.providerKey);
+ setFolderTitle(treeNode.node.props.title);
+ setSelectedFolder(isNaN(+folder[0]) ? folder[0] : +folder[0]);
+ };
+
+ const startOperation = async (isCopy, destFolderId, folderTitle) => {
const isProviderFolder = selection.find((x) => !x.providerKey);
const items =
isProviderFolder && !isCopy
@@ -83,7 +96,7 @@ const OperationsPanelComponent = (props) => {
if (!folderIds.length && !fileIds.length) return;
- checkOperationConflict({
+ const operationData = {
destFolderId,
folderIds,
fileIds,
@@ -94,37 +107,64 @@ const OperationsPanelComponent = (props) => {
copy: t("Translations:CopyOperation"),
move: t("Translations:MoveToOperation"),
},
- });
+ };
+
+ setIsLoading(true);
+ checkFileConflicts(destFolderId, folderIds, fileIds).then(
+ async (conflicts) => {
+ if (conflicts.length) {
+ setConflictDialogData(conflicts, operationData);
+ setIsLoading(false);
+ } else {
+ setIsLoading(false);
+ onClose();
+ await itemOperationToFolder(operationData);
+ }
+ }
+ );
};
//console.log("Operations panel render");
return (
-
-
-
- {isRecycleBin
- ? t("Translations:Restore")
- : isCopy
- ? t("Translations:Copy")
- : t("Translations:Move")}
-
-
-
-
-
-
+
+
+ {isRecycleBin
+ ? t("Translations:Restore")
+ : isCopy
+ ? t("Translations:Copy")
+ : t("Translations:Move")}
+
+
+
+
+
+
+
+
);
};
@@ -139,6 +179,7 @@ export default inject(
selectedFolderStore,
dialogsStore,
filesActionsStore,
+ uploadDataStore,
}) => {
const { filter, selection, bufferSelection } = filesStore;
const {
@@ -147,7 +188,8 @@ export default inject(
setExpandedPanelKeys,
expandedPanelKeys,
} = treeFoldersStore;
- const { checkOperationConflict } = filesActionsStore;
+ const { setConflictDialogData, checkFileConflicts } = filesActionsStore;
+ const { itemOperationToFolder } = uploadDataStore;
const {
moveToPanelVisible,
@@ -178,8 +220,10 @@ export default inject(
setMoveToPanelVisible,
setDestFolderId,
setThirdPartyMoveDialogVisible,
- checkOperationConflict,
+ setConflictDialogData,
setExpandedPanelKeys,
+ itemOperationToFolder,
+ checkFileConflicts,
};
}
)(withRouter(observer(OperationsPanel)));
diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js
index 44033e56aeb..9b39c8281bc 100644
--- a/products/ASC.Files/Client/src/store/FilesActionsStore.js
+++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js
@@ -150,7 +150,7 @@ class FilesActionStore {
this.updateCurrentFolder(fileIds, folderIds);
if (isRecycleBinFolder) {
return toastr.success(translations.deleteFromTrash);
- }
+ }
if (selection.length > 1) {
return toastr.success(translations.deleteSelectedElem);
@@ -207,7 +207,8 @@ class FilesActionStore {
};
await this.uploadDataStore.loopFilesOperations(data, pbData);
toastr.success(translations.successOperation);
- this.updateCurrentFolder(fileIds, folderIds); });
+ this.updateCurrentFolder(fileIds, folderIds);
+ });
} catch (err) {
clearActiveOperations(fileIds, folderIds);
setSecondaryProgressBarData({
@@ -662,13 +663,17 @@ class FilesActionStore {
this.checkOperationConflict(operationData);
};
+ checkFileConflicts = (destFolderId, folderIds, fileIds) =>
+ checkFileConflicts(destFolderId, folderIds, fileIds);
+
+ setConflictDialogData = (conflicts, operationData) => {
+ this.dialogsStore.setConflictResolveDialogItems(conflicts);
+ this.dialogsStore.setConflictResolveDialogData(operationData);
+ this.dialogsStore.setConflictResolveDialogVisible(true);
+ };
+
checkOperationConflict = async (operationData) => {
const { destFolderId, folderIds, fileIds } = operationData;
- const {
- setConflictResolveDialogData,
- setConflictResolveDialogVisible,
- setConflictResolveDialogItems,
- } = this.dialogsStore;
const { setBufferSelection, addActiveItems } = this.filesStore;
addActiveItems(fileIds);
@@ -677,16 +682,18 @@ class FilesActionStore {
let conflicts;
try {
- conflicts = await checkFileConflicts(destFolderId, folderIds, fileIds);
+ conflicts = await this.checkFileConflicts(
+ destFolderId,
+ folderIds,
+ fileIds
+ );
} catch (err) {
setBufferSelection(null);
return toastr.error(err.message ? err.message : err);
}
if (conflicts.length) {
- setConflictResolveDialogItems(conflicts);
- setConflictResolveDialogData(operationData);
- setConflictResolveDialogVisible(true);
+ this.setConflictDialogData(conflicts, operationData);
} else {
try {
await this.uploadDataStore.itemOperationToFolder(operationData);
@@ -695,8 +702,6 @@ class FilesActionStore {
return toastr.error(err.message ? err.message : err);
}
}
-
- setBufferSelection(null);
};
isAvailableOption = (option) => {