From bac023f04cdcbb17f48679f435c287823bcd7105 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 14:54:17 +0300 Subject: [PATCH 01/24] Web:Files:Constants: add global events name --- products/ASC.Files/Client/src/helpers/constants.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/products/ASC.Files/Client/src/helpers/constants.js b/products/ASC.Files/Client/src/helpers/constants.js index f0668ad30a..40aba5bb72 100644 --- a/products/ASC.Files/Client/src/helpers/constants.js +++ b/products/ASC.Files/Client/src/helpers/constants.js @@ -10,3 +10,5 @@ export const thumbnailStatuses = { }; export const ADS_TIMEOUT = 300000; // 5 min + +export const Events = Object.freeze({ CREATE: "create", RENAME: "rename" }); From 1a34e82155392a3db447c25b21e514a382744a52 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 15:49:29 +0300 Subject: [PATCH 02/24] Web:Files:Article: change create file or folder from action store to global event --- .../components/Article/MainButton/index.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/products/ASC.Files/Client/src/components/Article/MainButton/index.js b/products/ASC.Files/Client/src/components/Article/MainButton/index.js index 476c2324ca..60dc9bcae6 100644 --- a/products/ASC.Files/Client/src/components/Article/MainButton/index.js +++ b/products/ASC.Files/Client/src/components/Article/MainButton/index.js @@ -18,6 +18,7 @@ import MobileView from "./MobileView"; import { combineUrl } from "@appserver/common/utils"; import config from "../../../../package.json"; import withLoader from "../../../HOCs/withLoader"; +import { Events } from "../../../helpers/constants"; const ArticleMainButtonContent = (props) => { const { @@ -51,11 +52,19 @@ const ArticleMainButtonContent = (props) => { const onCreate = React.useCallback( (e) => { const format = e.action || null; - setAction({ - type: FileAction.Create, - extension: format, - id: -1, - }); + + // TODO: remove after delete action store + // setAction({ + // type: FileAction.Create, + // extension: format, + // id: -1, + // }); + + const event = new Event(Events.CREATE); + event.extension = format; + event.id = -1; + + window.dispatchEvent(event); }, [setAction] ); From 0ab899d5c93d1a749befd0f0852a5fba7413d5f7 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 15:51:55 +0300 Subject: [PATCH 03/24] Web:Files: add GlobalEvents component --- products/ASC.Files/Client/src/Files.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/products/ASC.Files/Client/src/Files.jsx b/products/ASC.Files/Client/src/Files.jsx index 0612756bb3..1522b28190 100644 --- a/products/ASC.Files/Client/src/Files.jsx +++ b/products/ASC.Files/Client/src/Files.jsx @@ -29,6 +29,7 @@ import { ArticleMainButtonContent, } from "./components/Article"; import FormGallery from "./pages/FormGallery"; +import GlobalEvents from "./components/GlobalEvents"; const { proxyURL } = AppServerConfig; const homepage = config.homepage; @@ -169,6 +170,7 @@ class FilesContent extends React.Component { return ( <> + From a029abadf5e362d96fb39efeb452cb28301ee94f Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 16:00:15 +0300 Subject: [PATCH 04/24] Web:Files:EmptyContainer: change create file or folder from action store to global event --- .../src/components/EmptyContainer/index.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/products/ASC.Files/Client/src/components/EmptyContainer/index.js b/products/ASC.Files/Client/src/components/EmptyContainer/index.js index 13a18c2bf1..cfa666ede0 100644 --- a/products/ASC.Files/Client/src/components/EmptyContainer/index.js +++ b/products/ASC.Files/Client/src/components/EmptyContainer/index.js @@ -5,6 +5,7 @@ import EmptyFilterContainer from "./EmptyFilterContainer"; import EmptyFolderContainer from "./EmptyFolderContainer"; import { FileAction } from "@appserver/common/constants"; import { isMobile } from "react-device-detect"; +import { Events } from "../../helpers/constants"; const linkStyles = { isHovered: true, @@ -26,11 +27,17 @@ const EmptyContainer = ({ const onCreate = (e) => { const format = e.currentTarget.dataset.format || null; - setAction({ - type: FileAction.Create, - extension: format, - id: -1, - }); + // setAction({ + // type: FileAction.Create, + // extension: format, + // id: -1, + // }); + + const event = new Event(Events.CREATE); + event.extension = format; + event.id = -1; + + window.dispatchEvent(event); }; return isFiltered ? ( From 10a745c1e665b46e4018eb4f3eeba60d8a2bdc26 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 16:15:54 +0300 Subject: [PATCH 05/24] Web:Files:withHotkeys: change create file or folder from action store to global event --- .../ASC.Files/Client/src/HOCs/withHotkeys.js | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/products/ASC.Files/Client/src/HOCs/withHotkeys.js b/products/ASC.Files/Client/src/HOCs/withHotkeys.js index 9e69c38c94..d3f55cc64c 100644 --- a/products/ASC.Files/Client/src/HOCs/withHotkeys.js +++ b/products/ASC.Files/Client/src/HOCs/withHotkeys.js @@ -2,6 +2,7 @@ import React, { useEffect } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { observer, inject } from "mobx-react"; import { FileAction } from "@appserver/common/constants"; +import { Events } from "../helpers/constants"; const withHotkeys = (Component) => { const WithHotkeys = (props) => { @@ -55,6 +56,14 @@ const withHotkeys = (Component) => { const onKeyDown = (e) => activateHotkeys(e); + const onCreate = (extension) => { + const event = new Event(Events.CREATE); + event.extension = extension; + event.id = -1; + + window.dispatchEvent(event); + }; + useEffect(() => { window.addEventListener("keydown", onKeyDown); @@ -153,32 +162,25 @@ const withHotkeys = (Component) => { ); //Crete document - useHotkeys( - "Shift+d", - () => setAction({ type: FileAction.Create, extension: "docx", id: -1 }), - hotkeysFilter - ); + useHotkeys("Shift+d", () => onCreate("docx"), hotkeysFilter); //Crete spreadsheet - useHotkeys( - "Shift+s", - () => setAction({ type: FileAction.Create, extension: "xlsx", id: -1 }), - { ...hotkeysFilter, ...{ keyup: true } } - ); + useHotkeys("Shift+s", () => onCreate("xlsx"), { + ...hotkeysFilter, + ...{ keyup: true }, + }); //Crete presentation - useHotkeys( - "Shift+p", - () => setAction({ type: FileAction.Create, extension: "pptx", id: -1 }), - { ...hotkeysFilter, ...{ keyup: true } } - ); + useHotkeys("Shift+p", () => onCreate("pptx"), { + ...hotkeysFilter, + ...{ keyup: true }, + }); //Crete form template - useHotkeys( - "Shift+o", - () => setAction({ type: FileAction.Create, extension: "docxf", id: -1 }), - { ...hotkeysFilter, ...{ keyup: true } } - ); + useHotkeys("Shift+o", () => onCreate("docxf"), { + ...hotkeysFilter, + ...{ keyup: true }, + }); //Crete form template from file useHotkeys( @@ -188,11 +190,10 @@ const withHotkeys = (Component) => { ); //Crete folder - useHotkeys( - "Shift+f", - () => setAction({ type: FileAction.Create, id: -1 }), - { ...hotkeysFilter, ...{ keyup: true } } - ); + useHotkeys("Shift+f", () => onCreate(null), { + ...hotkeysFilter, + ...{ keyup: true }, + }); //Delete selection useHotkeys( From ae66c8e4f6a17a32ff05dda2acf79ca6fe50cd09 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 17 Jun 2022 16:16:14 +0300 Subject: [PATCH 06/24] Web:Files:Section:Header: change create file or folder from action store to global event --- .../src/pages/Home/Section/Header/index.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js index db4bf9beed..32c1ed5813 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js @@ -13,6 +13,7 @@ import { Consumer } from "@appserver/components/utils/context"; import { inject, observer } from "mobx-react"; import TableGroupMenu from "@appserver/components/table-container/TableGroupMenu"; import Navigation from "@appserver/common/components/Navigation"; +import { Events } from "../../../../helpers/constants"; const StyledContainer = styled.div` .table-container_group-menu { @@ -47,11 +48,18 @@ class SectionHeaderContent extends React.Component { } onCreate = (format) => { - this.props.setAction({ - type: FileAction.Create, - extension: format, - id: -1, - }); + const event = new Event(Events.CREATE); + event.extension = format; + event.id = -1; + + window.dispatchEvent(event); + + // TODO: remove it after removing action store + // this.props.setAction({ + // type: FileAction.Create, + // extension: format, + // id: -1, + // }); }; createDocument = () => this.onCreate("docx"); From 441786da218f95741b7684fab2d021946842af4c Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:02:48 +0300 Subject: [PATCH 07/24] Web:Files:Home: change create oform file from action store to global event --- .../ASC.Files/Client/src/pages/Home/index.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/products/ASC.Files/Client/src/pages/Home/index.js b/products/ASC.Files/Client/src/pages/Home/index.js index d22174c3f1..131276b11d 100644 --- a/products/ASC.Files/Client/src/pages/Home/index.js +++ b/products/ASC.Files/Client/src/pages/Home/index.js @@ -33,6 +33,7 @@ import { observer, inject } from "mobx-react"; import config from "../../../package.json"; import { Consumer } from "@appserver/components/utils/context"; import { FileAction } from "@appserver/common/constants"; +import { Events } from "../../helpers/constants"; class PureHome extends React.Component { componentDidMount() { @@ -167,13 +168,21 @@ class PureHome extends React.Component { .then(() => { if (gallerySelected) { setIsUpdatingRowItem(false); - setAction({ - type: FileAction.Create, - extension: "docxf", - fromTemplate: true, - title: gallerySelected.attributes.name_form, - id: -1, - }); + // setAction({ + // type: FileAction.Create, + // extension: "docxf", + // fromTemplate: true, + // title: gallerySelected.attributes.name_form, + // id: -1, + // }); + + const event = new Event(Events.CREATE); + event.extension = "docxf"; + event.id = -1; + event.fromTemplate = true; + event.title = gallerySelected.attributes.name_form; + + window.dispatchEvent(event); } }) .finally(() => { From fd3a45f30186ba4f19de41db7b18b1f809e37b5e Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:04:33 +0300 Subject: [PATCH 08/24] Web:Files:ContextOptionStore: change rename file or folder from action store to global event --- .../Client/src/store/ContextOptionsStore.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/products/ASC.Files/Client/src/store/ContextOptionsStore.js b/products/ASC.Files/Client/src/store/ContextOptionsStore.js index ecb71dc59a..d92b76c7bd 100644 --- a/products/ASC.Files/Client/src/store/ContextOptionsStore.js +++ b/products/ASC.Files/Client/src/store/ContextOptionsStore.js @@ -10,6 +10,7 @@ import { isMobile as isMobileUtils, isTablet as isTabletUtils, } from "@appserver/components/utils/device"; +import { Events } from "../helpers/constants"; class ContextOptionsStore { authStore; @@ -246,12 +247,17 @@ class ContextOptionsStore { }; onClickRename = (item) => { - const { id, fileExst } = item; - this.filesStore.fileActionStore.setAction({ - type: FileAction.Rename, - extension: fileExst, - id, - }); + const event = new Event(Events.RENAME); + event.item = item; + + window.dispatchEvent(event); + + // this.filesStore.fileActionStore.setAction({ + // type: FileAction.Rename, + // extension: fileExst, + // id, + // title, + // }); }; onChangeThirdPartyInfo = (providerKey) => { From 3703693b349198cd675981c0abc0878a436b52f8 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:05:31 +0300 Subject: [PATCH 09/24] Web:Files:DialogsStore: change create oform file from docx from action store to global event --- .../Client/src/store/DialogsStore.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/products/ASC.Files/Client/src/store/DialogsStore.js b/products/ASC.Files/Client/src/store/DialogsStore.js index 3f60f0b9ea..5c28c1b26e 100644 --- a/products/ASC.Files/Client/src/store/DialogsStore.js +++ b/products/ASC.Files/Client/src/store/DialogsStore.js @@ -1,6 +1,7 @@ import { getNewFiles } from "@appserver/common/api/files"; import { FileAction } from "@appserver/common/constants"; import { makeAutoObservable } from "mobx"; +import { Events } from "../helpers/constants"; class DialogsStore { authStore; @@ -209,13 +210,21 @@ class DialogsStore { let newTitle = fileInfo.title; newTitle = newTitle.substring(0, newTitle.lastIndexOf(".")); - setAction({ - type: FileAction.Create, - extension: "docxf", - id: -1, - title: `${newTitle}.docxf`, - templateId: fileInfo.id, - }); + // setAction({ + // type: FileAction.Create, + // extension: "docxf", + // id: -1, + // title: `${newTitle}.docxf`, + // templateId: fileInfo.id, + // }); + + const event = new Event(Events.CREATE); + event.extension = "docxf"; + event.id = -1; + event.title = `${newTitle}.docxf`; + event.templateId = fileInfo.id; + + window.dispatchEvent(event); }; get someDialogIsOpen() { From 71fea715318e8452bcc94a58b522abf7174d3e9e Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:07:07 +0300 Subject: [PATCH 10/24] Web:Files:FilesActionsStore: add type as argument to editCompleteAction and change setAction from fileActionStore to global event --- .../Client/src/store/FilesActionsStore.js | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js index d12a3dc1da..1b303cae1c 100644 --- a/products/ASC.Files/Client/src/store/FilesActionsStore.js +++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js @@ -20,7 +20,7 @@ import { import { makeAutoObservable } from "mobx"; import toastr from "studio/toastr"; -import { TIMEOUT } from "../helpers/constants"; +import { Events, TIMEOUT } from "../helpers/constants"; import { loopTreeFolders, checkProtocol } from "../helpers/files-helpers"; import { combineUrl } from "@appserver/common/utils"; import { AppServerConfig } from "@appserver/common/constants"; @@ -428,7 +428,7 @@ class FilesActionStore { return this.downloadFiles(fileIds, folderIds, label); }; - editCompleteAction = async (id, selectedItem, isCancelled = false) => { + editCompleteAction = async (id, selectedItem, isCancelled = false, type) => { const { filter, folders, @@ -437,7 +437,7 @@ class FilesActionStore { fetchFiles, setIsLoading, } = this.filesStore; - const { type, setAction } = fileActionStore; + const { setAction } = fileActionStore; const { treeFolders, setTreeFolders } = this.treeFoldersStore; const items = [...folders, ...files]; @@ -455,14 +455,26 @@ class FilesActionStore { setTreeFolders(treeFolders); } } - setAction({ - type: null, - id: null, - extension: null, - title: "", - templateId: null, - fromTemplate: null, - }); + + const event = new Event(Events.CREATE); + + event.id = null; + event.extension = null; + event.title = ""; + event.templateId = null; + event.fromTemplate = null; + + window.dispatchEvent(event); + + // setAction({ + // type: null, + // id: null, + // extension: null, + // title: "", + // templateId: null, + // fromTemplate: null, + // }); + setIsLoading(false); type === FileAction.Rename && this.onSelectItem({ From a71e637c984ffa8791c9586c43f8b2a88dbff3c7 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:08:28 +0300 Subject: [PATCH 11/24] Web:Files:FilesActionsStore: add type as argument to editCompleteAction and change setAction from fileActionStore to global event --- .../Client/src/store/FilesActionsStore.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js index 1b303cae1c..b436466783 100644 --- a/products/ASC.Files/Client/src/store/FilesActionsStore.js +++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js @@ -456,15 +456,23 @@ class FilesActionStore { } } - const event = new Event(Events.CREATE); + const createEvent = new Event(Events.CREATE); + const renameEvent = new Events(Events.RENAME); - event.id = null; - event.extension = null; - event.title = ""; - event.templateId = null; - event.fromTemplate = null; + createEvent.id = null; + createEvent.extension = null; + createEvent.title = ""; + createEvent.templateId = null; + createEvent.fromTemplate = null; - window.dispatchEvent(event); + renameEvent.id = null; + renameEvent.extension = null; + renameEvent.title = ""; + renameEvent.templateId = null; + renameEvent.fromTemplate = null; + + window.dispatchEvent(createEvent); + window.dispatchEvent(renameEvent); // setAction({ // type: null, From c3620c6c91fbf37f45cba31466074b024d31f79d Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:09:03 +0300 Subject: [PATCH 12/24] Web:Files:Components: add rename and create global events --- .../components/GlobalEvents/CreateEvent.js | 324 ++++++++++++++++++ .../components/GlobalEvents/RenameEvent.js | 227 ++++++++++++ .../src/components/GlobalEvents/index.js | 91 +++++ .../GlobalEvents/sub-components/Dialog.js | 96 ++++++ 4 files changed, 738 insertions(+) create mode 100644 products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js create mode 100644 products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js create mode 100644 products/ASC.Files/Client/src/components/GlobalEvents/index.js create mode 100644 products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js new file mode 100644 index 0000000000..a0dfa3bad9 --- /dev/null +++ b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js @@ -0,0 +1,324 @@ +import React from "react"; +import { inject, observer } from "mobx-react"; +import { useTranslation } from "react-i18next"; + +import toastr from "studio/toastr"; + +import { AppServerConfig } from "@appserver/common/constants"; +import { combineUrl } from "@appserver/common/utils"; + +import config from "../../../package.json"; + +import { getTitleWithoutExst } from "../../helpers/files-helpers"; +import { getDefaultFileName } from "../../helpers/utils"; + +import Dialog from "./sub-components/Dialog"; + +const CreateEvent = ({ + id, + type, + extension, + title, + templateId, + fromTemplate, + onClose, + + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + + parentId, + + isPrivacy, + isDesktop, + editCompleteAction, + + clearActiveOperations, + fileCopyAs, + + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + + replaceFileStream, + setEncryptionAccess, +}) => { + const [visible, setVisible] = React.useState(false); + const [headerTitle, setHeaderTitle] = React.useState(null); + const [startValue, setStartValue] = React.useState(""); + + const { t } = useTranslation(["Translations", "Common"]); + + React.useEffect(() => { + const defaultName = getDefaultFileName(extension); + + if (title) { + const item = { fileExst: extension, title: title }; + + setStartValue(getTitleWithoutExst(item, fromTemplate)); + } else { + setStartValue(defaultName); + } + + setHeaderTitle(defaultName); + setVisible(true); + }, [extension, title, fromTemplate]); + + const completeAction = (id, item) => { + const isCancel = + (id.currentTarget && id.currentTarget.dataset.action === "cancel") || + id.keyCode === 27; + + editCompleteAction(id, item, isCancel, type); + }; + + const onSave = (e, value, open = true) => { + let item; + let createdFileId, createdFolderId; + + const isMakeFormFromFile = templateId ? true : false; + + setIsLoading(true); + + const newValue = value; + + // delete it later + // const itemId = e.currentTarget.dataset.itemid; + + if (value.trim() === "") { + newValue = + templateId === null + ? getDefaultFileName(extension) + : getTitleWithoutExst({ fileExst: extension }); + + setStartValue(newValue); + } + + let tab = + !isDesktop && extension && open + ? window.open( + combineUrl(AppServerConfig.proxyURL, config.homepage, "/doceditor"), + "_blank" + ) + : null; + + if (!extension) { + createFolder(parentId, newValue) + .then((folder) => { + item = folder; + createdFolderId = folder.id; + addActiveItems(null, [folder.id]); + }) + .then(() => completeAction(id, item)) + .catch((e) => toastr.error(e)) + .finally(() => { + const folderIds = [+id]; + createdFolderId && folderIds.push(createdFolderId); + + clearActiveOperations(null, folderIds); + + return setIsLoading(false); + }); + } else { + if (isMakeFormFromFile) { + fileCopyAs(templateId, `${newValue}.${extension}`, parentId) + .then((file) => { + item = file; + createdFileId = file.id; + addActiveItems([file.id]); + + open && openDocEditor(file.id, file.providerKey, tab); + }) + .then(() => completeAction(id, item)) + .catch((err) => { + console.log("err", err); + const isPasswordError = new RegExp("password"); + + if (isPasswordError.test(err)) { + toastr.error( + t("Translations:FileProtected"), + t("Common:Warning") + ); + + setIsUpdatingRowItem(false); + + setVisible(false); + + setFormCreationInfo({ + newTitle: `${newValue}.${extension}`, + fromExst: ".docx", + toExst: extension, + open, + actionId: id, + fileInfo: { + id: templateId, + folderId: parentId, + fileExst: extension, + }, + }); + + setConvertPasswordDialogVisible(true); + + open && openDocEditor(null, null, tab); + } + }) + .finally(() => { + const fileIds = [+id]; + createdFileId && fileIds.push(createdFileId); + + clearActiveOperations(fileIds); + + return setIsLoading(false); + }); + } else if (fromTemplate) { + createFile( + parentId, + `${newValue}.${extension}`, + undefined, + gallerySelected.id + ) + .then((file) => { + item = file; + createdFileId = file.id; + addActiveItems([file.id]); + + return open && openDocEditor(file.id, file.providerKey, tab); + }) + .then(() => completeAction(id, item)) + .catch((e) => toastr.error(e)) + .finally(() => { + const fileIds = [+id]; + createdFileId && fileIds.push(createdFileId); + + clearActiveOperations(fileIds); + + return setIsLoading(false); + }); + } else { + createFile(parentId, `${newValue}.${extension}`) + .then((file) => { + createdFileId = file.id; + item = file; + addActiveItems([file.id]); + + if (isPrivacy) { + return setEncryptionAccess(file).then((encryptedFile) => { + if (!encryptedFile) return Promise.resolve(); + toastr.info(t("Translations:EncryptedFileSaving")); + + return replaceFileStream( + file.id, + encryptedFile, + true, + false + ).then( + () => open && openDocEditor(file.id, file.providerKey, tab) + ); + }); + } + + return open && openDocEditor(file.id, file.providerKey, tab); + }) + .then(() => completeAction(id, item)) + .catch((e) => toastr.error(e)) + .finally(() => { + const fileIds = [+id]; + createdFileId && fileIds.push(createdFileId); + + clearActiveOperations(fileIds); + + return setIsLoading(false); + }); + } + } + }; + + const onCancel = React.useCallback( + (e) => { + onClose && onClose(); + }, + [onClose] + ); + + return ( + + ); +}; + +export default inject( + ({ + auth, + filesStore, + filesActionsStore, + selectedFolderStore, + treeFoldersStore, + uploadDataStore, + dialogsStore, + }) => { + const { + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + } = filesStore; + + const { editCompleteAction } = filesActionsStore; + + const { clearActiveOperations, fileCopyAs } = uploadDataStore; + + const { isRecycleBinFolder, isPrivacyFolder } = treeFoldersStore; + + const { id: parentId } = selectedFolderStore; + + const { replaceFileStream, setEncryptionAccess } = auth; + + const { isDesktopClient } = auth.settingsStore; + + const { + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + } = dialogsStore; + + return { + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + + parentId, + + isDesktop: isDesktopClient, + isPrivacy: isPrivacyFolder, + isTrashFolder: isRecycleBinFolder, + editCompleteAction, + + clearActiveOperations, + fileCopyAs, + + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + + replaceFileStream, + setEncryptionAccess, + }; + } +)(observer(CreateEvent)); diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js new file mode 100644 index 0000000000..b05068f3b4 --- /dev/null +++ b/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js @@ -0,0 +1,227 @@ +import React from "react"; +import { inject, observer } from "mobx-react"; +import { useTranslation } from "react-i18next"; + +import toastr from "studio/toastr"; + +import { AppServerConfig } from "@appserver/common/constants"; +import { combineUrl } from "@appserver/common/utils"; + +import config from "../../../package.json"; + +import { getTitleWithoutExst } from "../../helpers/files-helpers"; +import { getDefaultFileName } from "../../helpers/utils"; + +import Dialog from "./sub-components/Dialog"; + +const RenameEvent = ({ + type, + item, + onClose, + + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + + updateFile, + renameFolder, + + parentId, + + isPrivacy, + isDesktop, + editCompleteAction, + + clearActiveOperations, + fileCopyAs, + + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + + replaceFileStream, + setEncryptionAccess, +}) => { + const [visible, setVisible] = React.useState(false); + + const [startValue, setStartValue] = React.useState(""); + + const { t } = useTranslation(["Home", "Translations", "Common"]); + + React.useEffect(() => { + setStartValue(getTitleWithoutExst(item, false)); + + setVisible(true); + }, [item]); + + const completeAction = (id) => { + const isCancel = + (id.currentTarget && id.currentTarget.dataset.action === "cancel") || + id.keyCode === 27; + + editCompleteAction(id, item, isCancel, type); + }; + + const onUpdate = React.useCallback((e, value) => { + const originalTitle = getTitleWithoutExst(item); + + setIsLoading(true); + let timerId; + + const isSameTitle = + originalTitle.trim() === value.trim() || value.trim() === ""; + + const isFile = item.fileExst || item.contentLength; + + if (isSameTitle) { + setStartValue(originalTitle); + + return editCompleteAction(item.id, item, isSameTitle, type); + } else { + timerId = setTimeout(() => { + isFile ? addActiveItems([item.id]) : addActiveItems(null, [item.id]); + }, 500); + } + + isFile + ? updateFile(item.id, value) + .then(() => completeAction(item.id)) + .then(() => + toastr.success( + t("FileRenamed", { + oldTitle: item.title, + newTitle: value + item.fileExst, + }) + ) + ) + .catch((err) => { + toastr.error(err); + completeAction(item.id); + }) + .finally(() => { + clearTimeout(timerId); + timerId = null; + clearActiveOperations([item.id]); + + setIsLoading(false); + onClose(); + }) + : renameFolder(item.id, value) + .then(() => completeAction(item.id)) + .then(() => + toastr.success( + t("FolderRenamed", { + folderTitle: item.title, + newFoldedTitle: value, + }) + ) + ) + .catch((err) => { + toastr.error(err); + completeAction(item.id); + }) + .finally(() => { + clearTimeout(timerId); + timerId = null; + clearActiveOperations(null, [item.id]); + + setIsLoading(false); + onClose(); + }); + }, []); + + const onCancel = React.useCallback( + (e) => { + onClose && onClose(); + }, + [onClose] + ); + + return ( + + ); +}; + +export default inject( + ({ + auth, + filesStore, + filesActionsStore, + selectedFolderStore, + treeFoldersStore, + uploadDataStore, + dialogsStore, + }) => { + const { + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + + updateFile, + renameFolder, + } = filesStore; + + const { editCompleteAction } = filesActionsStore; + + const { clearActiveOperations, fileCopyAs } = uploadDataStore; + + const { isRecycleBinFolder, isPrivacyFolder } = treeFoldersStore; + + const { id: parentId } = selectedFolderStore; + + const { replaceFileStream, setEncryptionAccess } = auth; + + const { isDesktopClient } = auth.settingsStore; + + const { + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + } = dialogsStore; + + return { + setIsLoading, + createFile, + createFolder, + addActiveItems, + openDocEditor, + setIsUpdatingRowItem, + gallerySelected, + + updateFile, + renameFolder, + + parentId, + + isDesktop: isDesktopClient, + isPrivacy: isPrivacyFolder, + isTrashFolder: isRecycleBinFolder, + editCompleteAction, + + clearActiveOperations, + fileCopyAs, + + setConvertPasswordDialogVisible, + setConvertItem, + setFormCreationInfo, + + replaceFileStream, + setEncryptionAccess, + }; + } +)(observer(RenameEvent)); diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/index.js b/products/ASC.Files/Client/src/components/GlobalEvents/index.js new file mode 100644 index 0000000000..0b28629de4 --- /dev/null +++ b/products/ASC.Files/Client/src/components/GlobalEvents/index.js @@ -0,0 +1,91 @@ +import React from "react"; + +import { FileAction } from "@appserver/common/constants"; + +import { Events } from "../../helpers/constants"; + +import CreateEvent from "./CreateEvent"; +import RenameEvent from "./RenameEvent"; + +const GlobalEvents = () => { + const [createDialogProps, setCreateDialogProps] = React.useState({ + visible: false, + id: null, + type: null, + extension: null, + title: "", + templateId: null, + fromTemplate: null, + onClose: null, + }); + + const [renameDialogProps, setRenameDialogProps] = React.useState({ + visible: false, + item: null, + onClose: null, + }); + + const onCreate = React.useCallback((e) => { + const visible = e.id ? true : false; + + setCreateDialogProps({ + visible: visible, + id: e.id, + type: FileAction.Create, + extension: e.extension, + title: e.title || null, + templateId: e.templateId || null, + fromTemplate: e.fromTemplate || null, + onClose: () => { + setCreateDialogProps({ + visible: false, + id: null, + type: null, + extension: null, + title: "", + templateId: null, + fromTemplate: null, + onClose: null, + }); + }, + }); + }, []); + + const onRename = React.useCallback((e) => { + const visible = e.item ? true : false; + + setRenameDialogProps({ + visible: visible, + type: FileAction.Rename, + item: e.item, + onClose: () => { + setRenameDialogProps({ + visible: false, + typ: null, + item: null, + }); + }, + }); + }, []); + + React.useEffect(() => { + window.addEventListener(Events.CREATE, onCreate); + window.addEventListener(Events.RENAME, onRename); + + return () => { + window.removeEventListener(Events.CREATE, onCreate); + window.removeEventListener(Events.RENAME, onRename); + }; + }, [onRename, onCreate]); + + return [ + createDialogProps.visible && ( + + ), + renameDialogProps.visible && ( + + ), + ]; +}; + +export default React.memo(GlobalEvents); diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js new file mode 100644 index 0000000000..e92de7c9a5 --- /dev/null +++ b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js @@ -0,0 +1,96 @@ +import React from "react"; + +import styled from "styled-components"; + +import ModalDialog from "@appserver/components/modal-dialog"; +import TextInput from "@appserver/components/text-input"; +import SaveCancelButtons from "@appserver/components/save-cancel-buttons"; + +const StyledSaveCancelButtons = styled(SaveCancelButtons)` + position: relative !important; + + padding: 8px 0 0; + + .buttons-flex { + width: 100%; + + display: grid; + align-items: center; + grid-template-columns: 1fr 1fr; + grid-gap: 8px; + } + + button { + width: 100%; + } +`; + +const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { + const [value, setValue] = React.useState(""); + const [isDisabled, setIsDisabled] = React.useState(false); + + React.useEffect(() => { + if (startValue) setValue(startValue); + }, [startValue]); + + const onChange = React.useCallback((e) => { + const newValue = e.target.value; + + setValue(newValue); + }, []); + + const onFocus = React.useCallback((e) => { + e.target.select(); + }, []); + + const onBlur = React.useCallback((e) => {}, []); + + const onSaveAction = React.useCallback( + (e) => { + setIsDisabled(true); + onSave && onSave(e, value); + }, + [onSave, value] + ); + + const onCancelAction = React.useCallback((e) => { + onCancel && onCancel(e); + }, []); + + return ( + + {title} + + + + + + + + ); +}; + +export default React.memo(Dialog); From 0bfa280c386f3474529dece7829403e34264b830 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 10:34:59 +0300 Subject: [PATCH 13/24] Web:Files:FilesActionsStore: fix rename event --- products/ASC.Files/Client/src/store/FilesActionsStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js index b436466783..cacf89bc01 100644 --- a/products/ASC.Files/Client/src/store/FilesActionsStore.js +++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js @@ -457,7 +457,7 @@ class FilesActionStore { } const createEvent = new Event(Events.CREATE); - const renameEvent = new Events(Events.RENAME); + const renameEvent = new Event(Events.RENAME); createEvent.id = null; createEvent.extension = null; From 991e3cc0125d3e3b47a8de1c4e23183b7dcb6a87 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 11:05:58 +0300 Subject: [PATCH 14/24] Web:Files:GlobalEvents: refactoring rename and create events --- .../components/GlobalEvents/CreateEvent.js | 23 +--- .../components/GlobalEvents/RenameEvent.js | 122 +++--------------- .../GlobalEvents/sub-components/Dialog.js | 3 - 3 files changed, 23 insertions(+), 125 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js index a0dfa3bad9..22f3fe3446 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js @@ -41,7 +41,6 @@ const CreateEvent = ({ fileCopyAs, setConvertPasswordDialogVisible, - setConvertItem, setFormCreationInfo, replaceFileStream, @@ -68,14 +67,6 @@ const CreateEvent = ({ setVisible(true); }, [extension, title, fromTemplate]); - const completeAction = (id, item) => { - const isCancel = - (id.currentTarget && id.currentTarget.dataset.action === "cancel") || - id.keyCode === 27; - - editCompleteAction(id, item, isCancel, type); - }; - const onSave = (e, value, open = true) => { let item; let createdFileId, createdFolderId; @@ -86,9 +77,6 @@ const CreateEvent = ({ const newValue = value; - // delete it later - // const itemId = e.currentTarget.dataset.itemid; - if (value.trim() === "") { newValue = templateId === null @@ -113,7 +101,7 @@ const CreateEvent = ({ createdFolderId = folder.id; addActiveItems(null, [folder.id]); }) - .then(() => completeAction(id, item)) + .then(() => editCompleteAction(id, item, false, type)) .catch((e) => toastr.error(e)) .finally(() => { const folderIds = [+id]; @@ -133,7 +121,7 @@ const CreateEvent = ({ open && openDocEditor(file.id, file.providerKey, tab); }) - .then(() => completeAction(id, item)) + .then(() => editCompleteAction(id, item, false, type)) .catch((err) => { console.log("err", err); const isPasswordError = new RegExp("password"); @@ -188,7 +176,7 @@ const CreateEvent = ({ return open && openDocEditor(file.id, file.providerKey, tab); }) - .then(() => completeAction(id, item)) + .then(() => editCompleteAction(id, item, false, type)) .catch((e) => toastr.error(e)) .finally(() => { const fileIds = [+id]; @@ -223,7 +211,7 @@ const CreateEvent = ({ return open && openDocEditor(file.id, file.providerKey, tab); }) - .then(() => completeAction(id, item)) + .then(() => editCompleteAction(id, item, false, type)) .catch((e) => toastr.error(e)) .finally(() => { const fileIds = [+id]; @@ -290,7 +278,7 @@ export default inject( const { setConvertPasswordDialogVisible, - setConvertItem, + setFormCreationInfo, } = dialogsStore; @@ -314,7 +302,6 @@ export default inject( fileCopyAs, setConvertPasswordDialogVisible, - setConvertItem, setFormCreationInfo, replaceFileStream, diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js index b05068f3b4..6a25a5ed9e 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/RenameEvent.js @@ -4,13 +4,7 @@ import { useTranslation } from "react-i18next"; import toastr from "studio/toastr"; -import { AppServerConfig } from "@appserver/common/constants"; -import { combineUrl } from "@appserver/common/utils"; - -import config from "../../../package.json"; - import { getTitleWithoutExst } from "../../helpers/files-helpers"; -import { getDefaultFileName } from "../../helpers/utils"; import Dialog from "./sub-components/Dialog"; @@ -20,37 +14,19 @@ const RenameEvent = ({ onClose, setIsLoading, - createFile, - createFolder, addActiveItems, - openDocEditor, - setIsUpdatingRowItem, - gallerySelected, updateFile, renameFolder, - parentId, - - isPrivacy, - isDesktop, editCompleteAction, - clearActiveOperations, - fileCopyAs, - - setConvertPasswordDialogVisible, - setConvertItem, - setFormCreationInfo, - - replaceFileStream, - setEncryptionAccess, }) => { const [visible, setVisible] = React.useState(false); const [startValue, setStartValue] = React.useState(""); - const { t } = useTranslation(["Home", "Translations", "Common"]); + const { t } = useTranslation(["Home"]); React.useEffect(() => { setStartValue(getTitleWithoutExst(item, false)); @@ -58,14 +34,6 @@ const RenameEvent = ({ setVisible(true); }, [item]); - const completeAction = (id) => { - const isCancel = - (id.currentTarget && id.currentTarget.dataset.action === "cancel") || - id.keyCode === 27; - - editCompleteAction(id, item, isCancel, type); - }; - const onUpdate = React.useCallback((e, value) => { const originalTitle = getTitleWithoutExst(item); @@ -89,7 +57,7 @@ const RenameEvent = ({ isFile ? updateFile(item.id, value) - .then(() => completeAction(item.id)) + .then(() => editCompleteAction(item.id, item, false, type)) .then(() => toastr.success( t("FileRenamed", { @@ -100,7 +68,7 @@ const RenameEvent = ({ ) .catch((err) => { toastr.error(err); - completeAction(item.id); + editCompleteAction(item.id, item, false, type); }) .finally(() => { clearTimeout(timerId); @@ -111,7 +79,7 @@ const RenameEvent = ({ onClose(); }) : renameFolder(item.id, value) - .then(() => completeAction(item.id)) + .then(() => editCompleteAction(item.id, item, false, type)) .then(() => toastr.success( t("FolderRenamed", { @@ -122,7 +90,7 @@ const RenameEvent = ({ ) .catch((err) => { toastr.error(err); - completeAction(item.id); + editCompleteAction(item.id, item, false, type); }) .finally(() => { clearTimeout(timerId); @@ -153,75 +121,21 @@ const RenameEvent = ({ ); }; -export default inject( - ({ - auth, - filesStore, - filesActionsStore, - selectedFolderStore, - treeFoldersStore, - uploadDataStore, - dialogsStore, - }) => { - const { - setIsLoading, - createFile, - createFolder, - addActiveItems, - openDocEditor, - setIsUpdatingRowItem, - gallerySelected, +export default inject(({ filesStore, filesActionsStore, uploadDataStore }) => { + const { setIsLoading, addActiveItems, updateFile, renameFolder } = filesStore; - updateFile, - renameFolder, - } = filesStore; + const { editCompleteAction } = filesActionsStore; - const { editCompleteAction } = filesActionsStore; + const { clearActiveOperations } = uploadDataStore; - const { clearActiveOperations, fileCopyAs } = uploadDataStore; + return { + setIsLoading, + addActiveItems, + updateFile, + renameFolder, - const { isRecycleBinFolder, isPrivacyFolder } = treeFoldersStore; + editCompleteAction, - const { id: parentId } = selectedFolderStore; - - const { replaceFileStream, setEncryptionAccess } = auth; - - const { isDesktopClient } = auth.settingsStore; - - const { - setConvertPasswordDialogVisible, - setConvertItem, - setFormCreationInfo, - } = dialogsStore; - - return { - setIsLoading, - createFile, - createFolder, - addActiveItems, - openDocEditor, - setIsUpdatingRowItem, - gallerySelected, - - updateFile, - renameFolder, - - parentId, - - isDesktop: isDesktopClient, - isPrivacy: isPrivacyFolder, - isTrashFolder: isRecycleBinFolder, - editCompleteAction, - - clearActiveOperations, - fileCopyAs, - - setConvertPasswordDialogVisible, - setConvertItem, - setFormCreationInfo, - - replaceFileStream, - setEncryptionAccess, - }; - } -)(observer(RenameEvent)); + clearActiveOperations, + }; +})(observer(RenameEvent)); diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js index e92de7c9a5..b8b3b1eaba 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js @@ -43,8 +43,6 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { e.target.select(); }, []); - const onBlur = React.useCallback((e) => {}, []); - const onSaveAction = React.useCallback( (e) => { setIsDisabled(true); @@ -76,7 +74,6 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { tabIndex={1} onChange={onChange} onFocus={onFocus} - onBlur={onBlur} isDisabled={isDisabled} /> From efa8a383d79bc281f5da7f382ae3a799ea8fafa9 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 11:29:47 +0300 Subject: [PATCH 15/24] Web:Files:GlobalEvents: change dialog styles for device width less than 400px --- .../GlobalEvents/sub-components/Dialog.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js index b8b3b1eaba..bc1241635f 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js @@ -6,6 +6,14 @@ import ModalDialog from "@appserver/components/modal-dialog"; import TextInput from "@appserver/components/text-input"; import SaveCancelButtons from "@appserver/components/save-cancel-buttons"; +const StyledModalDialog = styled(ModalDialog)` + width: 400px; + + @media (max-width: 400px) { + width: 100%; + } +`; + const StyledSaveCancelButtons = styled(SaveCancelButtons)` position: relative !important; @@ -56,10 +64,9 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { }, []); return ( - @@ -86,7 +93,7 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { showReminder={!isDisabled} /> - + ); }; From 413962bbaa25d0001ae5a7559f4cb23ab5e5254e Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 12:14:49 +0300 Subject: [PATCH 16/24] Web:Files:GlobalEvents: add title validation on rename --- .../components/GlobalEvents/CreateEvent.js | 1 + .../components/GlobalEvents/RenameEvent.js | 1 + .../GlobalEvents/sub-components/Dialog.js | 30 ++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js index 22f3fe3446..63153d63ac 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js @@ -234,6 +234,7 @@ const CreateEvent = ({ return ( { +const Dialog = ({ + t, + title, + startValue, + visible, + folderFormValidation, + onSave, + onCancel, + onClose, +}) => { const [value, setValue] = React.useState(""); const [isDisabled, setIsDisabled] = React.useState(false); @@ -42,7 +52,15 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { }, [startValue]); const onChange = React.useCallback((e) => { - const newValue = e.target.value; + let newValue = e.target.value; + + if (newValue.match(folderFormValidation)) { + toastr.warning(t("ContainsSpecCharacter")); + } + + newValue = newValue.replace(folderFormValidation, "_"); + + console.log(newValue); setValue(newValue); }, []); @@ -97,4 +115,8 @@ const Dialog = ({ title, startValue, visible, onSave, onCancel, onClose }) => { ); }; -export default React.memo(Dialog); +export default inject(({ auth }) => { + const { folderFormValidation } = auth.settingsStore; + + return { folderFormValidation }; +})(observer(Dialog)); From fe4f4ac80df1b1a47e5a7b8c608c2218bdf2d716 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 15:06:04 +0300 Subject: [PATCH 17/24] Web:Files:GlobalEvents: delete console log --- .../Client/src/components/GlobalEvents/sub-components/Dialog.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js index 8bdf8e4f56..132e49191b 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/sub-components/Dialog.js @@ -60,8 +60,6 @@ const Dialog = ({ newValue = newValue.replace(folderFormValidation, "_"); - console.log(newValue); - setValue(newValue); }, []); From 9a58baa4352b92e5a658c6e8b090bbc50a11c92f Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 20 Jun 2022 19:01:10 +0300 Subject: [PATCH 18/24] Web:Files: delete filesActionStore and useless code after adding global events for create and rename file/folder --- .../ASC.Files/Client/src/HOCs/withContent.js | 427 +----------------- .../Client/src/HOCs/withFileActions.js | 18 +- .../ASC.Files/Client/src/HOCs/withHotkeys.js | 11 +- .../Client/src/HOCs/withQuickButtons.js | 14 +- .../components/Article/MainButton/index.js | 16 +- .../src/components/EmptyContainer/index.js | 7 - .../Client/src/components/ItemIcon.js | 41 +- .../src/pages/Home/Section/Body/index.js | 6 +- .../src/pages/Home/Section/Header/index.js | 13 +- .../ASC.Files/Client/src/pages/Home/index.js | 19 +- .../Client/src/store/ContextOptionsStore.js | 13 +- .../Client/src/store/DialogsStore.js | 10 - .../Client/src/store/FileActionStore.js | 27 -- .../Client/src/store/FilesActionsStore.js | 13 +- .../ASC.Files/Client/src/store/FilesStore.js | 11 +- products/ASC.Files/Client/src/store/index.js | 2 - 16 files changed, 57 insertions(+), 591 deletions(-) delete mode 100644 products/ASC.Files/Client/src/store/FileActionStore.js diff --git a/products/ASC.Files/Client/src/HOCs/withContent.js b/products/ASC.Files/Client/src/HOCs/withContent.js index 348f7d4181..43711145b2 100644 --- a/products/ASC.Files/Client/src/HOCs/withContent.js +++ b/products/ASC.Files/Client/src/HOCs/withContent.js @@ -21,381 +21,19 @@ export default function withContent(WrappedContent) { constructor(props) { super(props); - const { - item, - fileActionId, - fileActionExt, - fileActionTemplateId, - fromTemplate, - } = props; let titleWithoutExt = props.titleWithoutExt; - if ( - fileActionId === -1 && - item.id === fileActionId && - fileActionTemplateId === null && - !fromTemplate - ) { - titleWithoutExt = getDefaultFileName(fileActionExt); - } this.state = { itemTitle: titleWithoutExt }; } componentDidUpdate(prevProps) { - const { - fileActionId, - fileActionExt, - setIsUpdatingRowItem, - isUpdatingRowItem, - isEdit, - titleWithoutExt, - } = this.props; - if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) { - const itemTitle = getDefaultFileName(fileActionExt); - this.setState({ itemTitle }); - } - if (fileActionId === null && prevProps.fileActionId !== fileActionId) { - isUpdatingRowItem && setIsUpdatingRowItem(false); - } + const { titleWithoutExt } = this.props; - if (!isEdit && titleWithoutExt !== this.state.itemTitle) { + if (titleWithoutExt !== this.state.itemTitle) { this.setState({ itemTitle: titleWithoutExt }); } } - completeAction = (id) => { - const { editCompleteAction, item } = this.props; - - const isCancel = - (id.currentTarget && id.currentTarget.dataset.action === "cancel") || - id.keyCode === 27; - editCompleteAction(id, item, isCancel); - }; - - updateItem = () => { - const { - t, - updateFile, - renameFolder, - item, - setIsLoading, - fileActionId, - editCompleteAction, - addActiveItems, - clearActiveOperations, - } = this.props; - - const { itemTitle } = this.state; - const originalTitle = getTitleWithoutExst(item); - - setIsLoading(true); - let timerId; - - const isSameTitle = - originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === ""; - - const isFile = item.fileExst || item.contentLength; - - if (isSameTitle) { - this.setState({ - itemTitle: originalTitle, - }); - return editCompleteAction(fileActionId, item, isSameTitle); - } else { - timerId = setTimeout(() => { - isFile ? addActiveItems([item.id]) : addActiveItems(null, [item.id]); - }, 500); - } - - isFile - ? updateFile(fileActionId, itemTitle) - .then(() => this.completeAction(fileActionId)) - .then(() => - toastr.success( - t("FileRenamed", { - oldTitle: item.title, - newTitle: itemTitle + item.fileExst, - }) - ) - ) - .catch((err) => { - toastr.error(err); - this.completeAction(fileActionId); - }) - .finally(() => { - clearTimeout(timerId); - timerId = null; - clearActiveOperations([item.id]); - - setIsLoading(false); - }) - : renameFolder(fileActionId, itemTitle) - .then(() => this.completeAction(fileActionId)) - .then(() => - toastr.success( - t("FolderRenamed", { - folderTitle: item.title, - newFoldedTitle: itemTitle, - }) - ) - ) - .catch((err) => { - toastr.error(err); - this.completeAction(fileActionId); - }) - .finally(() => { - clearTimeout(timerId); - timerId = null; - clearActiveOperations(null, [item.id]); - - setIsLoading(false); - }); - }; - - cancelUpdateItem = (e) => { - const { item } = this.props; - - const originalTitle = getTitleWithoutExst(item); - this.setState({ - itemTitle: originalTitle, - }); - - return this.completeAction(e); - }; - - onClickUpdateItem = (e, open = true) => { - const { - fileActionType, - setIsUpdatingRowItem, - addActiveItems, - item, - } = this.props; - - setIsUpdatingRowItem(true); - - if (fileActionType === FileAction.Create) { - !item.fileExst && !item.contentLength - ? addActiveItems(null, [item.id]) - : addActiveItems([item.id]); - this.createItem(e, open); - } else { - this.updateItem(e); - } - }; - - createItem = (e, open) => { - const { - createFile, - createFolder, - fileActionTemplateId, - isDesktop, - isPrivacy, - item, - openDocEditor, - replaceFileStream, - setEncryptionAccess, - setIsLoading, - t, - setConvertPasswordDialogVisible, - setFormCreationInfo, - setIsUpdatingRowItem, - clearActiveOperations, - addActiveItems, - fileCopyAs, - fromTemplate, - gallerySelected, - setCreatedItem, - } = this.props; - const { itemTitle } = this.state; - const { parentId, fileExst } = item; - - const isMakeFormFromFile = fileActionTemplateId ? true : false; - - let title = itemTitle; - - setIsLoading(true); - - const itemId = e.currentTarget.dataset.itemid; - - let createdFileId, createdFolderId; - - if (itemTitle.trim() === "") { - title = - fileActionTemplateId === null - ? getDefaultFileName(item.fileExst) - : getTitleWithoutExst(item); - - this.setState({ - itemTitle: title, - }); - } - - let tab = - !isDesktop && item.fileExst && open - ? window.open( - combineUrl( - AppServerConfig.proxyURL, - config.homepage, - "/doceditor" - ), - "_blank" - ) - : null; - - if (!item.fileExst && !item.contentLength) { - createFolder(item.parentId, title) - .then((folder) => { - createdFolderId = folder.id; - addActiveItems(null, [folder.id]); - setCreatedItem({ id: createdFolderId, type: "folder" }); - }) - .then(() => this.completeAction(itemId)) - .catch((e) => { - toastr.error(e); - this.completeAction(itemId); - }) - .finally(() => { - const folderIds = [+itemId]; - createdFolderId && folderIds.push(createdFolderId); - - clearActiveOperations(null, folderIds); - - return setIsLoading(false); - }); - } else { - if (isMakeFormFromFile) { - fileCopyAs( - fileActionTemplateId, - `${title}.${item.fileExst}`, - item.parentId - ) - .then((file) => { - createdFileId = file.id; - addActiveItems([file.id]); - - open && openDocEditor(file.id, file.providerKey, tab); - }) - .then(() => this.completeAction(itemId)) - .catch((err) => { - console.log("err", err); - const isPasswordError = new RegExp(/\(password\)*$/); - - if (isPasswordError.test(err)) { - toastr.error( - t("Translations:FileProtected"), - t("Common:Warning") - ); - setIsUpdatingRowItem(false); - - setFormCreationInfo({ - newTitle: `${title}.${item.fileExst}`, - fromExst: ".docx", - toExst: item.fileExst, - open, - actionId: itemId, - fileInfo: { - id: fileActionTemplateId, - folderId: item.parentId, - fileExst: item.fileExst, - }, - }); - setConvertPasswordDialogVisible(true); - - open && openDocEditor(null, null, tab); - } - }) - .finally(() => { - const fileIds = [+itemId]; - createdFileId && fileIds.push(createdFileId); - - clearActiveOperations(fileIds); - - return setIsLoading(false); - }); - } else if (fromTemplate) { - createFile( - parentId, - `${itemTitle}.${fileExst}`, - undefined, - gallerySelected.id - ) - .then((file) => { - createdFileId = file.id; - setCreatedItem({ id: createdFileId, type: "file" }); - addActiveItems([file.id]); - - return open && openDocEditor(file.id, file.providerKey, tab); - }) - .then(() => this.completeAction(itemId)) - .catch((e) => { - toastr.error(e); - tab && tab.close(); - this.completeAction(itemId); - }) - .finally(() => { - const fileIds = [+itemId]; - createdFileId && fileIds.push(createdFileId); - - clearActiveOperations(fileIds); - - return setIsLoading(false); - }); - } else { - createFile(item.parentId, `${title}.${item.fileExst}`) - .then((file) => { - createdFileId = file.id; - setCreatedItem({ id: createdFileId, type: "file" }); - addActiveItems([file.id]); - - if (isPrivacy) { - return setEncryptionAccess(file).then((encryptedFile) => { - if (!encryptedFile) return Promise.resolve(); - toastr.info(t("Translations:EncryptedFileSaving")); - return replaceFileStream( - file.id, - encryptedFile, - true, - false - ).then( - () => open && openDocEditor(file.id, file.providerKey, tab) - ); - }); - } - return open && openDocEditor(file.id, file.providerKey, tab); - }) - .then(() => this.completeAction(itemId)) - .catch((e) => { - toastr.error(e); - tab && tab.close(); - this.completeAction(itemId); - }) - .finally(() => { - const fileIds = [+itemId]; - createdFileId && fileIds.push(createdFileId); - - clearActiveOperations(fileIds); - - return setIsLoading(false); - }); - } - } - }; - - renameTitle = (e) => { - const { t, folderFormValidation } = this.props; - - let title = e.target.value; - //const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate - - if (title.match(folderFormValidation)) { - toastr.warning(t("ContainsSpecCharacter")); - } - - title = title.replace(folderFormValidation, "_"); - - return this.setState({ itemTitle: title }); - }; - getStatusByDate = (create) => { const { culture, item, personal } = this.props; const { created, updated } = item; @@ -410,7 +48,6 @@ export default function withContent(WrappedContent) { }; render() { - const { itemTitle } = this.state; const { element, isDesktop, @@ -418,23 +55,13 @@ export default function withContent(WrappedContent) { item, onFilesClick, t, - viewAs, + viewer, - isUpdatingRowItem, - passwordEntryProcess, - isEdit, + titleWithoutExt, } = this.props; - const { - access, - createdBy, - fileExst, - fileStatus, - href, - icon, - id, - isFolder, - } = item; + + const { access, createdBy, fileExst, fileStatus, href, icon, id } = item; const updatedDate = this.getStatusByDate(false); const createdDate = this.getStatusByDate(true); @@ -459,27 +86,8 @@ export default function withContent(WrappedContent) { const newItems = item.new || (fileStatus & FileStatus.IsNew) === FileStatus.IsNew; const showNew = !!newItems; - const elementIcon = element ? ( - element - ) : ( - - ); - return isEdit ? ( - - ) : ( + return ( @@ -278,7 +271,7 @@ export default function withFileActions(WrappedFileItem) { selection, setTooltipPosition, setStartDrag, - fileActionStore, + getFolderInfo, viewAs, bufferSelection, @@ -290,7 +283,6 @@ export default function withFileActions(WrappedFileItem) { } = filesStore; const { startUpload } = uploadDataStore; - const { type, extension, id } = fileActionStore; const selectedItem = selection.find( (x) => x.id === item.id && x.fileExst === item.fileExst @@ -338,9 +330,7 @@ export default function withFileActions(WrappedFileItem) { setStartDrag, isFolder, allowShareIn: filesStore.canShare, - actionType: type, - actionExtension: extension, - actionId: id, + checked: !!selectedItem, //parentFolder: selectedFolderStore.parentId, setParentId: selectedFolderStore.setParentId, diff --git a/products/ASC.Files/Client/src/HOCs/withHotkeys.js b/products/ASC.Files/Client/src/HOCs/withHotkeys.js index d3f55cc64c..03bf8ab829 100644 --- a/products/ASC.Files/Client/src/HOCs/withHotkeys.js +++ b/products/ASC.Files/Client/src/HOCs/withHotkeys.js @@ -12,7 +12,6 @@ const withHotkeys = (Component) => { setSelected, viewAs, setViewAs, - setAction, setHotkeyPanelVisible, confirmDelete, setDeleteDialogVisible, @@ -259,14 +258,7 @@ const withHotkeys = (Component) => { hotkeyStore, mediaViewerDataStore, }) => { - const { - setSelected, - viewAs, - setViewAs, - fileActionStore, - enabledHotkeys, - } = filesStore; - const { setAction } = fileActionStore; + const { setSelected, viewAs, setViewAs, enabledHotkeys } = filesStore; const { selectFile, @@ -306,7 +298,6 @@ const withHotkeys = (Component) => { setSelected, viewAs, setViewAs, - setAction, setHotkeyPanelVisible, setDeleteDialogVisible, diff --git a/products/ASC.Files/Client/src/HOCs/withQuickButtons.js b/products/ASC.Files/Client/src/HOCs/withQuickButtons.js index b59eb25668..f3d7e3cde5 100644 --- a/products/ASC.Files/Client/src/HOCs/withQuickButtons.js +++ b/products/ASC.Files/Client/src/HOCs/withQuickButtons.js @@ -67,8 +67,6 @@ export default function withQuickButtons(WrappedComponent) { isTrashFolder, isAdmin, showShare, - fileActionExt, - fileActionId, sectionWidth, viewAs, } = this.props; @@ -79,9 +77,7 @@ export default function withQuickButtons(WrappedComponent) { access === ShareAccessRights.FullAccess || access === ShareAccessRights.None; // TODO: fix access type for owner (now - None) - const isEdit = id === fileActionId && fileExst === fileActionExt; - - const quickButtonsComponent = !isEdit ? ( + const quickButtonsComponent = ( - ) : null; + ); return ( { (e) => { const format = e.action || null; - // TODO: remove after delete action store - // setAction({ - // type: FileAction.Create, - // extension: format, - // id: -1, - // }); - const event = new Event(Events.CREATE); event.extension = format; event.id = -1; @@ -327,13 +320,7 @@ export default inject( treeFoldersStore, selectedFolderStore, }) => { - const { - isLoaded, - firstLoad, - isLoading, - fileActionStore, - canCreate, - } = filesStore; + const { isLoaded, firstLoad, isLoading, canCreate } = filesStore; const { isPrivacyFolder, isFavoritesFolder, @@ -362,7 +349,6 @@ export default inject( isShareFolder, canCreate, - setAction: fileActionStore.setAction, startUpload, setSelectFileDialogVisible, diff --git a/products/ASC.Files/Client/src/components/EmptyContainer/index.js b/products/ASC.Files/Client/src/components/EmptyContainer/index.js index cfa666ede0..ddd5ab7a1a 100644 --- a/products/ASC.Files/Client/src/components/EmptyContainer/index.js +++ b/products/ASC.Files/Client/src/components/EmptyContainer/index.js @@ -17,7 +17,6 @@ const linkStyles = { const EmptyContainer = ({ isFiltered, - setAction, isPrivacyFolder, parentId, isEncryptionSupport, @@ -27,11 +26,6 @@ const EmptyContainer = ({ const onCreate = (e) => { const format = e.currentTarget.dataset.format || null; - // setAction({ - // type: FileAction.Create, - // extension: format, - // id: -1, - // }); const event = new Event(Events.CREATE); event.extension = format; @@ -66,7 +60,6 @@ export default inject( isEncryptionSupport: auth.settingsStore.isEncryptionSupport, theme: auth.settingsStore.theme, isFiltered, - setAction: filesStore.fileActionStore.setAction, isPrivacyFolder, parentId: selectedFolderStore.parentId, }; diff --git a/products/ASC.Files/Client/src/components/ItemIcon.js b/products/ASC.Files/Client/src/components/ItemIcon.js index 173e052e27..1d97c5918a 100644 --- a/products/ASC.Files/Client/src/components/ItemIcon.js +++ b/products/ASC.Files/Client/src/components/ItemIcon.js @@ -23,35 +23,42 @@ const ItemIcon = ({ fileExst, isPrivacy, viewAs, - actionType, - actionExtension, - actionId, + // actionType, + // actionExtension, + // actionId, }) => { - const isEdit = - (actionType !== null && actionId === id && fileExst === actionExtension) || - id <= 0; + // const isEdit = + // (actionType !== null && actionId === id && fileExst === actionExtension) || + // id <= 0; + + // return ( + // <> + // + // {isPrivacy && fileExst && ( + // + // )} + // + // ); return ( <> - - {isPrivacy && fileExst && ( - - )} + + {isPrivacy && fileExst && } ); }; export default inject(({ filesStore, treeFoldersStore }) => { - const { type, extension, id } = filesStore.fileActionStore; + // const { type, extension, id } = filesStore.fileActionStore; return { viewAs: filesStore.viewAs, isPrivacy: treeFoldersStore.isPrivacyFolder, - actionType: type, - actionExtension: extension, - actionId: id, + // actionType: type, + // actionExtension: extension, + // actionId: id, }; })(observer(ItemIcon)); diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js index 5bda4ba56b..4162834bf2 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js @@ -20,7 +20,6 @@ const SectionBodyContent = (props) => { const { t, tReady, - fileActionId, isEmptyFilesList, folderId, dragging, @@ -233,7 +232,7 @@ const SectionBodyContent = (props) => { return ( {(context) => - (!fileActionId && isEmptyFilesList) || null ? ( + isEmptyFilesList || null ? ( <> @@ -266,7 +265,6 @@ export default inject( filesActionsStore, }) => { const { - fileActionStore, isEmptyFilesList, dragging, setDragging, @@ -288,7 +286,7 @@ export default inject( dragging, startDrag, setStartDrag, - fileActionId: fileActionStore.id, + isEmptyFilesList, setDragging, folderId: selectedFolderStore.id, diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js index 32c1ed5813..c770707a8a 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js @@ -53,13 +53,6 @@ class SectionHeaderContent extends React.Component { event.id = -1; window.dispatchEvent(event); - - // TODO: remove it after removing action store - // this.props.setAction({ - // type: FileAction.Create, - // extension: format, - // id: -1, - // }); }; createDocument = () => this.onCreate("docx"); @@ -424,7 +417,7 @@ export default inject( const { setSelected, setSelection, - fileActionStore, + canCreate, isHeaderVisible, isHeaderIndeterminate, @@ -441,7 +434,7 @@ export default inject( activeFiles, activeFolders, } = filesStore; - const { setAction } = fileActionStore; + const { setSharingPanelVisible, setMoveToPanelVisible, @@ -486,7 +479,7 @@ export default inject( setSelected, setSelection, - setAction, + setSharingPanelVisible, setMoveToPanelVisible, setCopyPanelVisible, diff --git a/products/ASC.Files/Client/src/pages/Home/index.js b/products/ASC.Files/Client/src/pages/Home/index.js index 131276b11d..64622fca6b 100644 --- a/products/ASC.Files/Client/src/pages/Home/index.js +++ b/products/ASC.Files/Client/src/pages/Home/index.js @@ -32,7 +32,6 @@ import DragTooltip from "../../components/DragTooltip"; import { observer, inject } from "mobx-react"; import config from "../../../package.json"; import { Consumer } from "@appserver/components/utils/context"; -import { FileAction } from "@appserver/common/constants"; import { Events } from "../../helpers/constants"; class PureHome extends React.Component { @@ -49,7 +48,6 @@ class PureHome extends React.Component { isMediaOrImage, getFileInfo, gallerySelected, - setAction, setIsUpdatingRowItem, } = this.props; @@ -168,13 +166,6 @@ class PureHome extends React.Component { .then(() => { if (gallerySelected) { setIsUpdatingRowItem(false); - // setAction({ - // type: FileAction.Create, - // extension: "docxf", - // fromTemplate: true, - // title: gallerySelected.attributes.name_form, - // id: -1, - // }); const event = new Event(Events.CREATE); event.extension = "docxf"; @@ -297,7 +288,7 @@ class PureHome extends React.Component { //console.log("Home render"); const { viewAs, - fileActionId, + firstLoad, isHeaderVisible, isPrivacyFolder, @@ -344,9 +335,7 @@ class PureHome extends React.Component { clearUploadedFilesHistory={clearUploadedFilesHistory} viewAs={viewAs} hideAside={ - !!fileActionId || - primaryProgressDataVisible || - secondaryProgressDataStoreVisible //TODO: use hideArticle action + primaryProgressDataVisible || secondaryProgressDataStoreVisible //TODO: use hideArticle action } isLoaded={!firstLoad} isHeaderVisible={isHeaderVisible} @@ -419,7 +408,6 @@ export default inject( firstLoad, setFirstLoad, fetchFiles, - fileActionStore, selection, setSelections, dragging, @@ -432,7 +420,6 @@ export default inject( setIsUpdatingRowItem, } = filesStore; - const { id, setAction } = fileActionStore; const { isRecycleBinFolder, isPrivacyFolder, @@ -485,7 +472,6 @@ export default inject( homepage: config.homepage, firstLoad, dragging, - fileActionId: id, viewAs, uploaded, converted, @@ -534,7 +520,6 @@ export default inject( isMediaOrImage: settingsStore.isMediaOrImage, getFileInfo, gallerySelected, - setAction, setIsUpdatingRowItem, }; } diff --git a/products/ASC.Files/Client/src/store/ContextOptionsStore.js b/products/ASC.Files/Client/src/store/ContextOptionsStore.js index d92b76c7bd..af1bc4c4dc 100644 --- a/products/ASC.Files/Client/src/store/ContextOptionsStore.js +++ b/products/ASC.Files/Client/src/store/ContextOptionsStore.js @@ -251,13 +251,6 @@ class ContextOptionsStore { event.item = item; window.dispatchEvent(event); - - // this.filesStore.fileActionStore.setAction({ - // type: FileAction.Rename, - // extension: fileExst, - // id, - // title, - // }); }; onChangeThirdPartyInfo = (providerKey) => { @@ -794,13 +787,11 @@ class ContextOptionsStore { getModel = (item, t) => { const { selection } = this.filesStore; - const { type, id, extension } = this.filesStore.fileActionStore; + const { fileExst, contextOptions } = item; - const isEdit = !!type && id === item.id && fileExst === extension; - const contextOptionsProps = - !isEdit && contextOptions && contextOptions.length > 0 + contextOptions && contextOptions.length > 0 ? selection.length > 1 ? this.getGroupContextOptions(t) : this.getFilesContextOptions(item, t) diff --git a/products/ASC.Files/Client/src/store/DialogsStore.js b/products/ASC.Files/Client/src/store/DialogsStore.js index 5c28c1b26e..adf20c64d0 100644 --- a/products/ASC.Files/Client/src/store/DialogsStore.js +++ b/products/ASC.Files/Client/src/store/DialogsStore.js @@ -205,19 +205,9 @@ class DialogsStore { }; createMasterForm = async (fileInfo) => { - const { setAction } = this.filesStore.fileActionStore; - let newTitle = fileInfo.title; newTitle = newTitle.substring(0, newTitle.lastIndexOf(".")); - // setAction({ - // type: FileAction.Create, - // extension: "docxf", - // id: -1, - // title: `${newTitle}.docxf`, - // templateId: fileInfo.id, - // }); - const event = new Event(Events.CREATE); event.extension = "docxf"; event.id = -1; diff --git a/products/ASC.Files/Client/src/store/FileActionStore.js b/products/ASC.Files/Client/src/store/FileActionStore.js deleted file mode 100644 index 04c88143ae..0000000000 --- a/products/ASC.Files/Client/src/store/FileActionStore.js +++ /dev/null @@ -1,27 +0,0 @@ -import { makeAutoObservable } from "mobx"; - -class FileActionStore { - id = null; - type = null; - extension = null; - title = ""; - templateId = null; - fromTemplate = null; - - constructor() { - makeAutoObservable(this); - } - - setAction = (fileAction) => { - if (fileAction.fromTemplate === undefined && this.fromTemplate) return; - - const fileActionItems = Object.keys(fileAction); - for (let key of fileActionItems) { - if (key in this) { - this[key] = fileAction[key]; - } - } - }; -} - -export default new FileActionStore(); diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js index cacf89bc01..ccc0eef9e6 100644 --- a/products/ASC.Files/Client/src/store/FilesActionsStore.js +++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js @@ -433,11 +433,11 @@ class FilesActionStore { filter, folders, files, - fileActionStore, + fetchFiles, setIsLoading, } = this.filesStore; - const { setAction } = fileActionStore; + const { treeFolders, setTreeFolders } = this.treeFoldersStore; const items = [...folders, ...files]; @@ -474,15 +474,6 @@ class FilesActionStore { window.dispatchEvent(createEvent); window.dispatchEvent(renameEvent); - // setAction({ - // type: null, - // id: null, - // extension: null, - // title: "", - // templateId: null, - // fromTemplate: null, - // }); - setIsLoading(false); type === FileAction.Rename && this.onSelectItem({ diff --git a/products/ASC.Files/Client/src/store/FilesStore.js b/products/ASC.Files/Client/src/store/FilesStore.js index 6c9e3cb717..fab36717cb 100644 --- a/products/ASC.Files/Client/src/store/FilesStore.js +++ b/products/ASC.Files/Client/src/store/FilesStore.js @@ -26,7 +26,7 @@ class FilesStore { authStore; settingsStore; userStore; - fileActionStore; + selectedFolderStore; treeFoldersStore; filesSettingsStore; @@ -77,7 +77,7 @@ class FilesStore { authStore, settingsStore, userStore, - fileActionStore, + selectedFolderStore, treeFoldersStore, filesSettingsStore @@ -89,7 +89,7 @@ class FilesStore { this.authStore = authStore; this.settingsStore = settingsStore; this.userStore = userStore; - this.fileActionStore = fileActionStore; + this.selectedFolderStore = selectedFolderStore; this.treeFoldersStore = treeFoldersStore; this.filesSettingsStore = filesSettingsStore; @@ -637,7 +637,6 @@ class FilesStore { }); if (clearFilter) { - this.fileActionStore.setAction({ type: null }); if (clearSelection) { this.setSelected("close"); } @@ -1651,10 +1650,6 @@ class FilesStore { }; }); - if (this.fileActionStore.type === FileAction.Create) { - this.onCreateAddTempItem(newItem); - } - return newItem; } diff --git a/products/ASC.Files/Client/src/store/index.js b/products/ASC.Files/Client/src/store/index.js index 41ed33cbb4..b056c9c27a 100644 --- a/products/ASC.Files/Client/src/store/index.js +++ b/products/ASC.Files/Client/src/store/index.js @@ -1,5 +1,4 @@ import FilesStore from "./FilesStore"; -import fileActionStore from "./FileActionStore"; import SelectedFolderStore from "./SelectedFolderStore"; import TreeFoldersStore from "./TreeFoldersStore"; import thirdPartyStore from "./ThirdPartyStore"; @@ -26,7 +25,6 @@ const filesStore = new FilesStore( store.auth, store.auth.settingsStore, store.auth.userStore, - fileActionStore, selectedFolderStore, treeFoldersStore, settingsStore, From c4de30ee0fe1948c042af436d716576257cc6afc Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Tue, 21 Jun 2022 11:28:44 +0300 Subject: [PATCH 19/24] Web:Files:HOCs: fix warning after removing fileActionStore --- products/ASC.Files/Client/src/HOCs/withFileActions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/products/ASC.Files/Client/src/HOCs/withFileActions.js b/products/ASC.Files/Client/src/HOCs/withFileActions.js index ed0edc44e9..872f6cba05 100644 --- a/products/ASC.Files/Client/src/HOCs/withFileActions.js +++ b/products/ASC.Files/Client/src/HOCs/withFileActions.js @@ -288,8 +288,7 @@ export default function withFileActions(WrappedFileItem) { (x) => x.id === item.id && x.fileExst === item.fileExst ); - const draggable = - !isRecycleBinFolder && selectedItem && selectedItem.id !== id; + const draggable = !isRecycleBinFolder && selectedItem; const isFolder = selectedItem ? false : !item.isFolder ? false : true; const canWebEdit = settingsStore.canWebEdit(item.fileExst); From 7726b8f9ef23f855f8ddad46a4d27cc1cde57475 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Tue, 21 Jun 2022 11:29:31 +0300 Subject: [PATCH 20/24] Web:Files:CreateEvent: add onClose function after user click save button --- .../Client/src/components/GlobalEvents/CreateEvent.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js index 63153d63ac..3486d792c0 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js @@ -108,7 +108,7 @@ const CreateEvent = ({ createdFolderId && folderIds.push(createdFolderId); clearActiveOperations(null, folderIds); - + onClose(); return setIsLoading(false); }); } else { @@ -152,6 +152,8 @@ const CreateEvent = ({ setConvertPasswordDialogVisible(true); open && openDocEditor(null, null, tab); + } else { + toastr.error(e); } }) .finally(() => { @@ -159,7 +161,7 @@ const CreateEvent = ({ createdFileId && fileIds.push(createdFileId); clearActiveOperations(fileIds); - + onClose(); return setIsLoading(false); }); } else if (fromTemplate) { @@ -183,7 +185,7 @@ const CreateEvent = ({ createdFileId && fileIds.push(createdFileId); clearActiveOperations(fileIds); - + onClose(); return setIsLoading(false); }); } else { @@ -218,7 +220,7 @@ const CreateEvent = ({ createdFileId && fileIds.push(createdFileId); clearActiveOperations(fileIds); - + onClose(); return setIsLoading(false); }); } From 3f1623716dda144dcb5543c708cba7a7f39693d1 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Tue, 21 Jun 2022 11:30:26 +0300 Subject: [PATCH 21/24] Web:Files: move global event args to one payload --- .../ASC.Files/Client/src/HOCs/withHotkeys.js | 9 +++++++-- .../src/components/Article/MainButton/index.js | 8 ++++++-- .../src/components/EmptyContainer/index.js | 8 ++++++-- .../src/components/GlobalEvents/index.js | 14 ++++++++------ .../src/pages/Home/Section/Header/index.js | 9 +++++++-- .../ASC.Files/Client/src/pages/Home/index.js | 13 +++++++++---- .../Client/src/store/ContextOptionsStore.js | 1 + .../ASC.Files/Client/src/store/DialogsStore.js | 13 +++++++++---- .../Client/src/store/FilesActionsStore.js | 18 ------------------ 9 files changed, 53 insertions(+), 40 deletions(-) diff --git a/products/ASC.Files/Client/src/HOCs/withHotkeys.js b/products/ASC.Files/Client/src/HOCs/withHotkeys.js index 03bf8ab829..489788fe40 100644 --- a/products/ASC.Files/Client/src/HOCs/withHotkeys.js +++ b/products/ASC.Files/Client/src/HOCs/withHotkeys.js @@ -57,8 +57,13 @@ const withHotkeys = (Component) => { const onCreate = (extension) => { const event = new Event(Events.CREATE); - event.extension = extension; - event.id = -1; + + const payload = { + extension: format, + id: -1, + }; + + event.payload = payload; window.dispatchEvent(event); }; diff --git a/products/ASC.Files/Client/src/components/Article/MainButton/index.js b/products/ASC.Files/Client/src/components/Article/MainButton/index.js index 0d0a27a5fb..2d72b90c84 100644 --- a/products/ASC.Files/Client/src/components/Article/MainButton/index.js +++ b/products/ASC.Files/Client/src/components/Article/MainButton/index.js @@ -54,8 +54,12 @@ const ArticleMainButtonContent = (props) => { const format = e.action || null; const event = new Event(Events.CREATE); - event.extension = format; - event.id = -1; + + const payload = { + extension: format, + id: -1, + }; + event.payload = payload; window.dispatchEvent(event); }, diff --git a/products/ASC.Files/Client/src/components/EmptyContainer/index.js b/products/ASC.Files/Client/src/components/EmptyContainer/index.js index ddd5ab7a1a..a6f2035ff0 100644 --- a/products/ASC.Files/Client/src/components/EmptyContainer/index.js +++ b/products/ASC.Files/Client/src/components/EmptyContainer/index.js @@ -28,8 +28,12 @@ const EmptyContainer = ({ const format = e.currentTarget.dataset.format || null; const event = new Event(Events.CREATE); - event.extension = format; - event.id = -1; + + const payload = { + extension: format, + id: -1, + }; + event.payload = payload; window.dispatchEvent(event); }; diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/index.js b/products/ASC.Files/Client/src/components/GlobalEvents/index.js index 0b28629de4..d45d38a8b2 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/index.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/index.js @@ -26,16 +26,18 @@ const GlobalEvents = () => { }); const onCreate = React.useCallback((e) => { - const visible = e.id ? true : false; + const { payload } = e; + + const visible = payload.id ? true : false; setCreateDialogProps({ visible: visible, - id: e.id, + id: payload.id, type: FileAction.Create, - extension: e.extension, - title: e.title || null, - templateId: e.templateId || null, - fromTemplate: e.fromTemplate || null, + extension: payload.extension, + title: payload.title || null, + templateId: payload.templateId || null, + fromTemplate: payload.fromTemplate || null, onClose: () => { setCreateDialogProps({ visible: false, diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js index c770707a8a..d68caac102 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js @@ -49,8 +49,13 @@ class SectionHeaderContent extends React.Component { onCreate = (format) => { const event = new Event(Events.CREATE); - event.extension = format; - event.id = -1; + + const payload = { + extension: format, + id: -1, + }; + + event.payload = payload; window.dispatchEvent(event); }; diff --git a/products/ASC.Files/Client/src/pages/Home/index.js b/products/ASC.Files/Client/src/pages/Home/index.js index 64622fca6b..ea383fb77a 100644 --- a/products/ASC.Files/Client/src/pages/Home/index.js +++ b/products/ASC.Files/Client/src/pages/Home/index.js @@ -168,10 +168,15 @@ class PureHome extends React.Component { setIsUpdatingRowItem(false); const event = new Event(Events.CREATE); - event.extension = "docxf"; - event.id = -1; - event.fromTemplate = true; - event.title = gallerySelected.attributes.name_form; + + const payload = { + extension: "docxf", + id: -1, + fromTemplate: true, + title: gallerySelected.attributes.name_form, + }; + + event.payload = payload; window.dispatchEvent(event); } diff --git a/products/ASC.Files/Client/src/store/ContextOptionsStore.js b/products/ASC.Files/Client/src/store/ContextOptionsStore.js index af1bc4c4dc..6b85ec1243 100644 --- a/products/ASC.Files/Client/src/store/ContextOptionsStore.js +++ b/products/ASC.Files/Client/src/store/ContextOptionsStore.js @@ -248,6 +248,7 @@ class ContextOptionsStore { onClickRename = (item) => { const event = new Event(Events.RENAME); + event.item = item; window.dispatchEvent(event); diff --git a/products/ASC.Files/Client/src/store/DialogsStore.js b/products/ASC.Files/Client/src/store/DialogsStore.js index adf20c64d0..e29129fbc6 100644 --- a/products/ASC.Files/Client/src/store/DialogsStore.js +++ b/products/ASC.Files/Client/src/store/DialogsStore.js @@ -209,10 +209,15 @@ class DialogsStore { newTitle = newTitle.substring(0, newTitle.lastIndexOf(".")); const event = new Event(Events.CREATE); - event.extension = "docxf"; - event.id = -1; - event.title = `${newTitle}.docxf`; - event.templateId = fileInfo.id; + + const payload = { + extension: "docxf", + id: -1, + title: `${newTitle}.docxf`, + templateId: fileInfo.id, + }; + + event.payload = payload; window.dispatchEvent(event); }; diff --git a/products/ASC.Files/Client/src/store/FilesActionsStore.js b/products/ASC.Files/Client/src/store/FilesActionsStore.js index ccc0eef9e6..6a00f62ef4 100644 --- a/products/ASC.Files/Client/src/store/FilesActionsStore.js +++ b/products/ASC.Files/Client/src/store/FilesActionsStore.js @@ -456,24 +456,6 @@ class FilesActionStore { } } - const createEvent = new Event(Events.CREATE); - const renameEvent = new Event(Events.RENAME); - - createEvent.id = null; - createEvent.extension = null; - createEvent.title = ""; - createEvent.templateId = null; - createEvent.fromTemplate = null; - - renameEvent.id = null; - renameEvent.extension = null; - renameEvent.title = ""; - renameEvent.templateId = null; - renameEvent.fromTemplate = null; - - window.dispatchEvent(createEvent); - window.dispatchEvent(renameEvent); - setIsLoading(false); type === FileAction.Rename && this.onSelectItem({ From 4bf70be27d150c9ed94900635f5ef5245fb1a459 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Tue, 21 Jun 2022 14:09:58 +0300 Subject: [PATCH 22/24] Web:Files: applied changes from 610f738 --- .../components/GlobalEvents/CreateEvent.js | 56 +++++++++---------- .../dialogs/ConvertPasswordDialog/index.js | 42 +++++++------- .../Client/src/store/ContextOptionsStore.js | 23 ++++---- 3 files changed, 58 insertions(+), 63 deletions(-) diff --git a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js index 3486d792c0..ce9fd3a5ce 100644 --- a/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js +++ b/products/ASC.Files/Client/src/components/GlobalEvents/CreateEvent.js @@ -123,38 +123,32 @@ const CreateEvent = ({ }) .then(() => editCompleteAction(id, item, false, type)) .catch((err) => { - console.log("err", err); - const isPasswordError = new RegExp("password"); - - if (isPasswordError.test(err)) { - toastr.error( - t("Translations:FileProtected"), - t("Common:Warning") - ); - - setIsUpdatingRowItem(false); - - setVisible(false); - - setFormCreationInfo({ - newTitle: `${newValue}.${extension}`, - fromExst: ".docx", - toExst: extension, - open, - actionId: id, - fileInfo: { - id: templateId, - folderId: parentId, - fileExst: extension, - }, - }); - - setConvertPasswordDialogVisible(true); - - open && openDocEditor(null, null, tab); - } else { - toastr.error(e); + if (err.indexOf("password") == -1) { + toastr.error(err, t("Common:Warning")); + return; } + + toastr.error(t("Translations:FileProtected"), t("Common:Warning")); + + setIsUpdatingRowItem(false); + + setVisible(false); + + setFormCreationInfo({ + newTitle: `${newValue}.${extension}`, + fromExst: ".docx", + toExst: extension, + open, + actionId: id, + fileInfo: { + id: templateId, + folderId: parentId, + fileExst: extension, + }, + }); + setConvertPasswordDialogVisible(true); + + open && openDocEditor(null, null, tab); }) .finally(() => { const fileIds = [+id]; diff --git a/products/ASC.Files/Client/src/components/dialogs/ConvertPasswordDialog/index.js b/products/ASC.Files/Client/src/components/dialogs/ConvertPasswordDialog/index.js index c320a690bd..0e5f5fd80c 100644 --- a/products/ASC.Files/Client/src/components/dialogs/ConvertPasswordDialog/index.js +++ b/products/ASC.Files/Client/src/components/dialogs/ConvertPasswordDialog/index.js @@ -92,17 +92,18 @@ const ConvertPasswordDialogComponent = (props) => { onClose(); }) .catch((err) => { - console.log("err", err); - - const isPasswordError = new RegExp(/\(password\)*$/); - - if (isPasswordError.test(err)) { - toastr.error(t("CreationError"), t("Common:Warning")); - if (_isMounted) { - setPasswordValid(false); - focusInput(); - } + if (err.indexOf("password") == -1) { + toastr.error(err, t("Common:Warning")); + return; } + + toastr.error(t("CreationError"), t("Common:Warning")); + if (_isMounted) { + setPasswordValid(false); + focusInput(); + } + }) + .finally(() => { _isMounted && setIsLoading(false); }); } else { @@ -116,17 +117,18 @@ const ConvertPasswordDialogComponent = (props) => { editCompleteAction(actionId, fileInfo, false); }) .catch((err) => { - console.log("err", err); - const isPasswordError = new RegExp(/\(password\)*$/); - - if (isPasswordError.test(err)) { - toastr.error(t("CreationError"), t("Common:Warning")); - open && openDocEditor(null, null, tab); - if (_isMounted) { - setPasswordValid(false); - focusInput(); - } + if (err.indexOf("password") == -1) { + toastr.error(err, t("Common:Warning")); + return; } + toastr.error(t("CreationError"), t("Common:Warning")); + open && openDocEditor(null, null, tab); + if (_isMounted) { + setPasswordValid(false); + focusInput(); + } + }) + .finally(() => { _isMounted && setIsLoading(false); }); } diff --git a/products/ASC.Files/Client/src/store/ContextOptionsStore.js b/products/ASC.Files/Client/src/store/ContextOptionsStore.js index 6b85ec1243..860b6aa24a 100644 --- a/products/ASC.Files/Client/src/store/ContextOptionsStore.js +++ b/products/ASC.Files/Client/src/store/ContextOptionsStore.js @@ -69,19 +69,18 @@ class ContextOptionsStore { this.settingsStore.extsWebRestrictedEditing[0]; this.uploadDataStore.copyAsAction(id, newTitle, folderId).catch((err) => { - console.log("err", err); - const isPasswordError = new RegExp(/\(password\)*$/); - - if (isPasswordError.test(err)) { - toastr.error(t("Translations:FileProtected"), t("Common:Warning")); - setFormCreationInfo({ - newTitle, - fromExst: fileExst, - toExst: this.settingsStore.extsWebRestrictedEditing[0], - fileInfo: item, - }); - setConvertPasswordDialogVisible(true); + if (err.indexOf("password") == -1) { + toastr.error(err, t("Common:Warning")); + return; } + toastr.error(t("Translations:FileProtected"), t("Common:Warning")); + setFormCreationInfo({ + newTitle, + fromExst: fileExst, + toExst: this.settingsStore.extsWebRestrictedEditing[0], + fileInfo: item, + }); + setConvertPasswordDialogVisible(true); }); }; From a0651ecca419c8167d5523201192004b026508e1 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 11 Jul 2022 16:36:46 +0300 Subject: [PATCH 23/24] Web:Files:HOCs: fix create operation with hotkeys --- products/ASC.Files/Client/src/HOCs/withHotkeys.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/products/ASC.Files/Client/src/HOCs/withHotkeys.js b/products/ASC.Files/Client/src/HOCs/withHotkeys.js index 2342224b35..b686547d67 100644 --- a/products/ASC.Files/Client/src/HOCs/withHotkeys.js +++ b/products/ASC.Files/Client/src/HOCs/withHotkeys.js @@ -66,10 +66,11 @@ const withHotkeys = (Component) => { isFavoritesFolder || isRecentFolder || isTrashFolder; const onCreate = (extension) => { + if (folderWithNoAction) return; const event = new Event(Events.CREATE); const payload = { - extension: format, + extension: extension, id: -1, }; From 58bd9509a1af9a318b5963dc81bbb3f824621407 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Mon, 11 Jul 2022 17:13:51 +0300 Subject: [PATCH 24/24] Web:Files:Hocs: fix keyup on create docx after merge --- products/ASC.Files/Client/src/HOCs/withHotkeys.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/products/ASC.Files/Client/src/HOCs/withHotkeys.js b/products/ASC.Files/Client/src/HOCs/withHotkeys.js index b686547d67..8dd86ea7d3 100644 --- a/products/ASC.Files/Client/src/HOCs/withHotkeys.js +++ b/products/ASC.Files/Client/src/HOCs/withHotkeys.js @@ -177,7 +177,10 @@ const withHotkeys = (Component) => { ); //Crete document - useHotkeys("Shift+d", () => onCreate("docx"), hotkeysFilter); + useHotkeys("Shift+d", () => onCreate("docx"), { + ...hotkeysFilter, + ...{ keyup: true }, + }); //Crete spreadsheet useHotkeys("Shift+s", () => onCreate("xlsx"), {