From 813e17cac274c7c80c8dfee76cdb07c8c1a1cd80 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 03:12:50 +0300 Subject: [PATCH 01/19] Web: Files: created withFileaActions HOC, refactoring SimpleFilesRow --- .../Section/Body/FilesRow/SimpleFilesRow.js | 659 +--------------- .../Home/Section/Body/hoc/withFileActions.js | 710 ++++++++++++++++++ .../Home/Section/Body/sub-components/icons.js | 10 + 3 files changed, 740 insertions(+), 639 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js index cadd767582..e191384d2e 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js @@ -1,21 +1,15 @@ -import React, { useCallback } from "react"; -import { ReactSVG } from "react-svg"; +import React from "react"; import styled from "styled-components"; import { inject, observer } from "mobx-react"; import { withTranslation } from "react-i18next"; -import IconButton from "@appserver/components/icon-button"; -import Text from "@appserver/components/text"; import DragAndDrop from "@appserver/components/drag-and-drop"; import Row from "@appserver/components/row"; import FilesRowContent from "./FilesRowContent"; import { withRouter } from "react-router-dom"; -import toastr from "studio/toastr"; -import { FileAction, AppServerConfig } from "@appserver/common/constants"; -import copy from "copy-to-clipboard"; -import config from "../../../../../../../package.json"; -import { combineUrl } from "@appserver/common/utils"; import { createSelectable } from "react-selectable-fast"; +import withFileActions from "../hoc/withFileActions"; + const StyledSimpleFilesRow = styled(Row)` margin-top: -2px; ${(props) => @@ -52,517 +46,26 @@ const StyledSimpleFilesRow = styled(Row)` } `; -const EncryptedFileIcon = styled.div` - background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent; - height: 16px; - position: absolute; - width: 16px; - margin-top: 14px; - margin-left: ${(props) => (props.isEdit ? "40px" : "12px")}; -`; - -const svgLoader = () =>
; - const SimpleFilesRow = createSelectable((props) => { const { - t, item, sectionWidth, - actionType, - actionExtension, - isPrivacy, - isRecycleBin, dragging, - checked, - canShare, - isFolder, - draggable, - isRootFolder, - homepage, - isTabletView, - actionId, - selectedFolderId, - - setSharingPanelVisible, - setChangeOwnerPanelVisible, - setDeleteThirdPartyDialogVisible, - setRemoveItem, - setMoveToPanelVisible, - setCopyPanelVisible, - openDocEditor, - setIsVerHistoryPanel, - fetchFileVersions, - setAction, - deleteFileAction, - deleteFolderAction, - lockFileAction, - duplicateAction, - finalizeVersionAction, - setFavoriteAction, - openLocationAction, - selectRowAction, - setThirdpartyInfo, - setMediaViewerData, - setDragging, - setStartDrag, - startUpload, - onSelectItem, - history, - setTooltipPosition, - setDownloadDialogVisible, - downloadAction, - confirmDelete, - setDeleteDialogVisible, + onContentRowSelect, + rowContextClick, + onDrop, + onMouseDown, + className, + isDragging, + value, + displayShareButton, + isPrivacy, + sharedButton, + contextOptionsProps, + checkedProps, + element, } = props; - const { - id, - title, - fileExst, - contentLength, - shared, - access, - contextOptions, - icon, - providerKey, - folderId, - viewUrl, - webUrl, - canOpenPlayer, - locked, - parentId, - } = item; - - const isThirdPartyFolder = providerKey && isRootFolder; - - const onContentRowSelect = (checked, file) => { - if (!file) return; - - selectRowAction(checked, file); - }; - - const onClickShare = () => { - onSelectItem(item); - setSharingPanelVisible(true); - }; - const onOwnerChange = () => setChangeOwnerPanelVisible(true); - const onMoveAction = () => setMoveToPanelVisible(true); - const onCopyAction = () => setCopyPanelVisible(true); - - const getSharedButton = (shared) => { - const color = shared ? "#657077" : "#a3a9ae"; - return ( - - - {t("Share")} - - ); - }; - - const getItemIcon = (isEdit) => { - return ( - <> - - {isPrivacy && fileExst && } - - ); - }; - - const onOpenLocation = () => { - const locationId = isFolder ? id : folderId; - openLocationAction(locationId, isFolder); - }; - - const showVersionHistory = () => { - if (!isTabletView) { - fetchFileVersions(id + ""); - setIsVerHistoryPanel(true); - } else { - history.push( - combineUrl(AppServerConfig.proxyURL, homepage, `/${id}/history`) - ); - } - }; - - const finalizeVersion = () => - finalizeVersionAction(id).catch((err) => toastr.error(err)); - - const onClickFavorite = (e) => { - const data = (e.currentTarget && e.currentTarget.dataset) || e; - const { action } = data; - - setFavoriteAction(action, id) - .then(() => - action === "mark" - ? toastr.success(t("MarkedAsFavorite")) - : toastr.success(t("RemovedFromFavorites")) - ) - .catch((err) => toastr.error(err)); - }; - - const lockFile = () => - lockFileAction(id, !locked).catch((err) => toastr.error(err)); - - const onClickLinkForPortal = () => { - const isFile = !!fileExst; - copy( - isFile - ? canOpenPlayer - ? `${window.location.href}&preview=${id}` - : webUrl - : `${window.location.origin + homepage}/filter?folder=${id}` - ); - - toastr.success(t("LinkCopySuccess")); - }; - - const onClickLinkEdit = () => openDocEditor(id, providerKey); - - const onClickDownload = () => { - const isFile = !!fileExst && contentLength; - isFile - ? window.open(viewUrl, "_blank") - : downloadAction(t("ArchivingData")).catch((err) => toastr.error(err)); - }; - - const onClickDownloadAs = () => setDownloadDialogVisible(true); - - const onDuplicate = () => - duplicateAction(item, t("CopyOperation")).catch((err) => toastr.error(err)); - - const onClickRename = () => { - setAction({ - type: FileAction.Rename, - extension: fileExst, - id, - }); - }; - - const onChangeThirdPartyInfo = () => setThirdpartyInfo(providerKey); - - const onMediaFileClick = (fileId) => { - const itemId = typeof fileId !== "object" ? fileId : id; - setMediaViewerData({ visible: true, id: itemId }); - }; - - const onClickDelete = () => { - if (isThirdPartyFolder) { - const splitItem = id.split("-"); - setRemoveItem({ id: splitItem[splitItem.length - 1], title }); - setDeleteThirdPartyDialogVisible(true); - return; - } - - if (confirmDelete) { - setDeleteDialogVisible(true); - } else { - const translations = { - deleteOperation: t("DeleteOperation"), - }; - - fileExst || contentLength - ? deleteFileAction(id, folderId, translations) - .then(() => toastr.success(t("FileRemoved"))) - .catch((err) => toastr.error(err)) - : deleteFolderAction(id, parentId, translations) - .then(() => toastr.success(t("FolderRemoved"))) - .catch((err) => toastr.error(err)); - } - }; - - const rowContextClick = () => { - onSelectItem(item); - }; - - const getFilesContextOptions = useCallback(() => { - const isSharable = access !== 1 && access !== 0; - return contextOptions.map((option) => { - switch (option) { - case "open": - return { - key: option, - label: t("Open"), - icon: "images/catalog.folder.react.svg", - onClick: onOpenLocation, - disabled: false, - }; - case "show-version-history": - return { - key: option, - label: t("ShowVersionHistory"), - icon: "images/history.react.svg", - onClick: showVersionHistory, - disabled: false, - }; - case "finalize-version": - return { - key: option, - label: t("FinalizeVersion"), - icon: "images/history-finalized.react.svg", - onClick: finalizeVersion, - disabled: false, - }; - case "separator0": - case "separator1": - case "separator2": - case "separator3": - return { key: option, isSeparator: true }; - case "open-location": - return { - key: option, - label: t("OpenLocation"), - icon: "images/download-as.react.svg", - onClick: onOpenLocation, - disabled: false, - }; - case "mark-as-favorite": - return { - key: option, - label: t("MarkAsFavorite"), - icon: "images/favorites.react.svg", - onClick: onClickFavorite, - disabled: false, - "data-action": "mark", - action: "mark", - }; - case "block-unblock-version": - return { - key: option, - label: t("UnblockVersion"), - icon: "images/lock.react.svg", - onClick: lockFile, - disabled: false, - }; - case "sharing-settings": - return { - key: option, - label: t("SharingSettings"), - icon: "images/catalog.shared.react.svg", - onClick: onClickShare, - disabled: isSharable, - }; - case "send-by-email": - return { - key: option, - label: t("SendByEmail"), - icon: "/static/images/mail.react.svg", - disabled: true, - }; - case "owner-change": - return { - key: option, - label: t("ChangeOwner"), - icon: "images/catalog.user.react.svg", - onClick: onOwnerChange, - disabled: false, - }; - case "link-for-portal-users": - return { - key: option, - label: t("LinkForPortalUsers"), - icon: "/static/images/invitation.link.react.svg", - onClick: onClickLinkForPortal, - disabled: false, - }; - case "edit": - return { - key: option, - label: t("Edit"), - icon: "/static/images/access.edit.react.svg", - onClick: onClickLinkEdit, - disabled: false, - }; - case "preview": - return { - key: option, - label: t("Preview"), - icon: "EyeIcon", - onClick: onClickLinkEdit, - disabled: true, - }; - case "view": - return { - key: option, - label: t("View"), - icon: "/static/images/eye.react.svg", - onClick: onMediaFileClick, - disabled: false, - }; - case "download": - return { - key: option, - label: t("Download"), - icon: "images/download.react.svg", - onClick: onClickDownload, - disabled: false, - }; - case "download-as": - return { - key: option, - label: t("DownloadAs"), - icon: "images/download-as.react.svg", - onClick: onClickDownloadAs, - disabled: false, - }; - case "move-to": - return { - key: option, - label: t("MoveTo"), - icon: "images/move.react.svg", - onClick: onMoveAction, - disabled: false, - }; - case "restore": - return { - key: option, - label: t("Restore"), - icon: "images/move.react.svg", - onClick: onMoveAction, - disabled: false, - }; - case "copy-to": - return { - key: option, - label: t("Copy"), - icon: "/static/images/copy.react.svg", - onClick: onCopyAction, - disabled: false, - }; - case "copy": - return { - key: option, - label: t("Duplicate"), - icon: "/static/images/copy.react.svg", - onClick: onDuplicate, - disabled: false, - }; - case "rename": - return { - key: option, - label: t("Rename"), - icon: "images/rename.react.svg", - onClick: onClickRename, - disabled: false, - }; - case "change-thirdparty-info": - return { - key: option, - label: t("ThirdPartyInfo"), - icon: "/static/images/access.edit.react.svg", - onClick: onChangeThirdPartyInfo, - disabled: false, - }; - case "delete": - return { - key: option, - label: isThirdPartyFolder ? t("DeleteThirdParty") : t("Delete"), - icon: "/static/images/catalog.trash.react.svg", - onClick: onClickDelete, - disabled: false, - }; - case "remove-from-favorites": - return { - key: option, - label: t("RemoveFromFavorites"), - icon: "images/favorites.react.svg", - onClick: onClickFavorite, - disabled: false, - "data-action": "remove", - action: "remove", - }; - default: - break; - } - - return undefined; - }); - }, [contextOptions, item]); - - const onDropZoneUpload = (files, uploadToFolder) => { - const folderId = uploadToFolder ? uploadToFolder : selectedFolderId; - - dragging && setDragging(false); - startUpload(files, folderId, t); - }; - - const onDrop = (items) => { - if (!fileExst) { - onDropZoneUpload(items, id); - } else { - onDropZoneUpload(items, selectedFolderId); - } - }; - - const onMouseDown = (e) => { - if (!draggable) { - return; - } - - if ( - window.innerWidth < 1025 || - e.target.tagName === "rect" || - e.target.tagName === "path" - ) { - return; - } - const mouseButton = e.which - ? e.which !== 1 - : e.button - ? e.button !== 0 - : false; - const label = e.currentTarget.getAttribute("label"); - if (mouseButton || e.currentTarget.tagName !== "DIV" || label) { - return; - } - - setTooltipPosition(e.pageX, e.pageY); - setStartDrag(true); - }; - - const isMobile = sectionWidth < 500; - const isEdit = - !!actionType && actionId === id && fileExst === actionExtension; - const contextOptionsProps = - !isEdit && contextOptions && contextOptions.length > 0 - ? { - contextOptions: getFilesContextOptions(), - } - : {}; - - const isDragging = isFolder && access < 2 && !isRecycleBin; - const checkedProps = isEdit || id <= 0 ? {} : { checked }; - const element = getItemIcon(isEdit || id <= 0); - const displayShareButton = isMobile ? "26px" : !canShare ? "38px" : "96px"; - let className = isDragging ? " droppable" : ""; - if (draggable) className += " draggable not-selectable"; - - let value = fileExst || contentLength ? `file_${id}` : `folder_${id}`; - value += draggable ? "_draggable" : ""; - - const sharedButton = - !canShare || (isPrivacy && !fileExst) || isEdit || id <= 0 || isMobile - ? null - : getSharedButton(shared); - return (
{ {...contextOptionsProps} > { ); }); -export default inject( - ( - { - auth, - filesStore, - treeFoldersStore, - selectedFolderStore, - dialogsStore, - versionHistoryStore, - filesActionsStore, - mediaViewerDataStore, - uploadDataStore, - settingsStore, - }, - { item } - ) => { - const { isTabletView } = auth.settingsStore; - const { type, extension, id } = filesStore.fileActionStore; - const { isRecycleBinFolder, isPrivacyFolder } = treeFoldersStore; - - const { - setSharingPanelVisible, - setChangeOwnerPanelVisible, - setRemoveItem, - setDeleteThirdPartyDialogVisible, - setMoveToPanelVisible, - setCopyPanelVisible, - setDownloadDialogVisible, - setDeleteDialogVisible, - } = dialogsStore; - - const { - selection, - canShare, - openDocEditor, - fileActionStore, - dragging, - setDragging, - setStartDrag, - setTooltipPosition, - isFileSelected, - } = filesStore; - - const { isRootFolder, id: selectedFolderId } = selectedFolderStore; - const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; - const { setAction } = fileActionStore; - - const selectedItem = selection.find( - (x) => x.id === item.id && x.fileExst === item.fileExst - ); - - const isFolder = selectedItem - ? false - : item.fileExst || item.contentLength - ? false - : true; - - const draggable = - !isRecycleBinFolder && selectedItem && selectedItem.id !== id; - - const { - deleteFileAction, - deleteFolderAction, - lockFileAction, - finalizeVersionAction, - duplicateAction, - setFavoriteAction, - openLocationAction, - selectRowAction, - setThirdpartyInfo, - onSelectItem, - downloadAction, - } = filesActionsStore; - - const { setMediaViewerData } = mediaViewerDataStore; - const { startUpload } = uploadDataStore; - - return { - dragging, - actionType: type, - actionExtension: extension, - isPrivacy: isPrivacyFolder, - isRecycleBin: isRecycleBinFolder, - isRootFolder, - canShare, - checked: isFileSelected(item.id, item.parentId), - isFolder, - draggable, - isItemsSelected: !!selection.length, - homepage: config.homepage, - isTabletView, - actionId: fileActionStore.id, - setSharingPanelVisible, - setChangeOwnerPanelVisible, - setRemoveItem, - setDeleteThirdPartyDialogVisible, - setMoveToPanelVisible, - setCopyPanelVisible, - setDownloadDialogVisible, - openDocEditor, - setIsVerHistoryPanel, - fetchFileVersions, - setAction, - deleteFileAction, - deleteFolderAction, - lockFileAction, - finalizeVersionAction, - duplicateAction, - setFavoriteAction, - openLocationAction, - selectRowAction, - setThirdpartyInfo, - setMediaViewerData, - selectedFolderId, - setDragging, - setStartDrag, - startUpload, - onSelectItem, - setTooltipPosition, - downloadAction, - confirmDelete: settingsStore.confirmDelete, - setDeleteDialogVisible, - }; - } -)(withTranslation("Home")(observer(withRouter(SimpleFilesRow)))); +export default withTranslation("Home")( + withFileActions(withRouter(SimpleFilesRow)) +); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js new file mode 100644 index 0000000000..a6e65be7e2 --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js @@ -0,0 +1,710 @@ +import React from "react"; +import { inject, observer } from "mobx-react"; +import { ReactSVG } from "react-svg"; +import copy from "copy-to-clipboard"; + +import IconButton from "@appserver/components/icon-button"; +import Text from "@appserver/components/text"; +import { combineUrl } from "@appserver/common/utils"; +import { FileAction, AppServerConfig } from "@appserver/common/constants"; +import toastr from "studio/toastr"; + +import { EncryptedFileIcon } from "../sub-components/icons"; +import config from "../../../../../../../package.json"; + +const svgLoader = () =>
; +export default function withFileActions(WrappedFileItem) { + class WithFileActions extends React.Component { + onContentRowSelect = (checked, file) => { + const { selectRowAction } = this.props; + if (!file) return; + selectRowAction(checked, file); + }; + + onClickShare = () => { + const { onSelectItem, setSharingPanelVisible, item } = this.props; + onSelectItem(item); + setSharingPanelVisible(true); + }; + + rowContextClick = () => { + const { onSelectItem, item } = this.props; + onSelectItem(item); + }; + + getSharedButton = (shared) => { + const { t } = this.props; + const color = shared ? "#657077" : "#a3a9ae"; + return ( + + + {t("Share")} + + ); + }; + + getItemIcon = (isEdit) => { + const { item, isPrivacy } = this.props; + const { icon, fileExst } = item; + return ( + <> + + {isPrivacy && fileExst && } + + ); + }; + + onDropZoneUpload = (files, uploadToFolder) => { + const { + selectedFolderId, + dragging, + setDragging, + startUpload, + } = this.props; + + const folderId = uploadToFolder ? uploadToFolder : selectedFolderId; + dragging && setDragging(false); + startUpload(files, folderId, t); + }; + + onDrop = (items) => { + const { item, selectedFolderId } = this.props; + const { fileExst, id } = item; + + if (!fileExst) { + this.onDropZoneUpload(items, id); + } else { + this.onDropZoneUpload(items, selectedFolderId); + } + }; + + onMouseDown = (e) => { + const { draggable, setTooltipPosition, setStartDrag } = this.props; + if (!draggable) { + return; + } + + if ( + window.innerWidth < 1025 || + e.target.tagName === "rect" || + e.target.tagName === "path" + ) { + return; + } + const mouseButton = e.which + ? e.which !== 1 + : e.button + ? e.button !== 0 + : false; + const label = e.currentTarget.getAttribute("label"); + if (mouseButton || e.currentTarget.tagName !== "DIV" || label) { + return; + } + + setTooltipPosition(e.pageX, e.pageY); + setStartDrag(true); + }; + + onOpenLocation = () => { + const { isFolder, item, openLocationAction } = this.props; + const { id, folderId, fileExst } = item; + + const locationId = !fileExst ? id : folderId; + console.log(locationId, id, folderId, isFolder); + openLocationAction(locationId, !fileExst); + }; + + onOwnerChange = () => { + const { setChangeOwnerPanelVisible } = this.props; + setChangeOwnerPanelVisible(true); + }; + onMoveAction = () => { + const { setMoveToPanelVisible } = this.props; + setMoveToPanelVisible(true); + }; + onCopyAction = () => { + const { setCopyPanelVisible } = this.props; + setCopyPanelVisible(true); + }; + + showVersionHistory = () => { + const { + item, + isTabletView, + fetchFileVersions, + setIsVerHistoryPanel, + history, + homepage, + } = this.props; + const { id } = item; + + if (!isTabletView) { + fetchFileVersions(id + ""); + setIsVerHistoryPanel(true); + } else { + history.push( + combineUrl(AppServerConfig.proxyURL, homepage, `/${id}/history`) + ); + } + }; + + finalizeVersion = () => { + const { item, finalizeVersionAction } = this.props; + const { id } = item; + finalizeVersionAction(id).catch((err) => toastr.error(err)); + }; + + onClickFavorite = (e) => { + const { item, setFavoriteAction, t } = this.props; + const { id } = item; + const data = (e.currentTarget && e.currentTarget.dataset) || e; + const { action } = data; + + setFavoriteAction(action, id) + .then(() => + action === "mark" + ? toastr.success(t("MarkedAsFavorite")) + : toastr.success(t("RemovedFromFavorites")) + ) + .catch((err) => toastr.error(err)); + }; + + lockFile = () => { + const { item, lockFileAction } = this.props; + const { id, locked } = item; + lockFileAction(id, !locked).catch((err) => toastr.error(err)); + }; + + onClickLinkForPortal = () => { + const { item, homepage, t } = this.props; + const { fileExst, canOpenPlayer, webUrl } = item; + + const isFile = !!fileExst; + copy( + isFile + ? canOpenPlayer + ? `${window.location.href}&preview=${id}` + : webUrl + : `${window.location.origin + homepage}/filter?folder=${id}` + ); + + toastr.success(t("LinkCopySuccess")); + }; + + onClickLinkEdit = () => { + const { item, openDocEditor } = this.props; + const { id, providerKey } = item; + openDocEditor(id, providerKey); + }; + + onClickDownload = () => { + const { item, downloadAction, t } = this.props; + const { fileExst, contentLength, viewUrl } = item; + const isFile = !!fileExst && contentLength; + isFile + ? window.open(viewUrl, "_blank") + : downloadAction(t("ArchivingData")).catch((err) => toastr.error(err)); + }; + + onClickDownloadAs = () => { + const { setDownloadDialogVisible } = this.props; + setDownloadDialogVisible(true); + }; + + onDuplicate = () => { + const { duplicateAction, t, item } = this.props; + duplicateAction(item, t("CopyOperation")).catch((err) => + toastr.error(err) + ); + }; + + onClickRename = () => { + const { item, setAction } = this.props; + const { id, fileExst } = item; + setAction({ + type: FileAction.Rename, + extension: fileExst, + id, + }); + }; + + onChangeThirdPartyInfo = () => { + const { item, setThirdpartyInfo } = this.props; + const { providerKey } = item; + setThirdpartyInfo(providerKey); + }; + + onMediaFileClick = (fileId) => { + const { item, setMediaViewerData } = this.props; + const itemId = typeof fileId !== "object" ? fileId : item.id; + setMediaViewerData({ visible: true, id: itemId }); + }; + + onClickDelete = () => { + const { + item, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + confirmDelete, + setDeleteDialogVisible, + t, + deleteFileAction, + deleteFolderAction, + isThirdPartyFolder, + } = this.props; + const { id, title, fileExst, contentLength, folderId, parentId } = item; + + if (isThirdPartyFolder) { + const splitItem = id.split("-"); + setRemoveItem({ id: splitItem[splitItem.length - 1], title }); + setDeleteThirdPartyDialogVisible(true); + return; + } + + if (confirmDelete) { + setDeleteDialogVisible(true); + } else { + const translations = { + deleteOperation: t("DeleteOperation"), + }; + + fileExst || contentLength + ? deleteFileAction(id, folderId, translations) + .then(() => toastr.success(t("FileRemoved"))) + .catch((err) => toastr.error(err)) + : deleteFolderAction(id, parentId, translations) + .then(() => toastr.success(t("FolderRemoved"))) + .catch((err) => toastr.error(err)); + } + }; + + getFilesContextOptions = () => { + const { item, t, isThirdPartyFolder } = this.props; + const { access, contextOptions } = item; + const isSharable = access !== 1 && access !== 0; + return contextOptions.map((option) => { + switch (option) { + case "open": + return { + key: option, + label: t("Open"), + icon: "images/catalog.folder.react.svg", + onClick: this.onOpenLocation, + disabled: false, + }; + case "show-version-history": + return { + key: option, + label: t("ShowVersionHistory"), + icon: "images/history.react.svg", + onClick: this.showVersionHistory, + disabled: false, + }; + case "finalize-version": + return { + key: option, + label: t("FinalizeVersion"), + icon: "images/history-finalized.react.svg", + onClick: this.finalizeVersion, + disabled: false, + }; + case "separator0": + case "separator1": + case "separator2": + case "separator3": + return { key: option, isSeparator: true }; + case "open-location": + return { + key: option, + label: t("OpenLocation"), + icon: "images/download-as.react.svg", + onClick: this.onOpenLocation, + disabled: false, + }; + case "mark-as-favorite": + return { + key: option, + label: t("MarkAsFavorite"), + icon: "images/favorites.react.svg", + onClick: this.onClickFavorite, + disabled: false, + "data-action": "mark", + action: "mark", + }; + case "block-unblock-version": + return { + key: option, + label: t("UnblockVersion"), + icon: "images/lock.react.svg", + onClick: this.lockFile, + disabled: false, + }; + case "sharing-settings": + return { + key: option, + label: t("SharingSettings"), + icon: "images/catalog.shared.react.svg", + onClick: this.onClickShare, + disabled: isSharable, + }; + case "send-by-email": + return { + key: option, + label: t("SendByEmail"), + icon: "/static/images/mail.react.svg", + disabled: true, + }; + case "owner-change": + return { + key: option, + label: t("ChangeOwner"), + icon: "images/catalog.user.react.svg", + onClick: this.onOwnerChange, + disabled: false, + }; + case "link-for-portal-users": + return { + key: option, + label: t("LinkForPortalUsers"), + icon: "/static/images/invitation.link.react.svg", + onClick: this.onClickLinkForPortal, + disabled: false, + }; + case "edit": + return { + key: option, + label: t("Edit"), + icon: "/static/images/access.edit.react.svg", + onClick: this.onClickLinkEdit, + disabled: false, + }; + case "preview": + return { + key: option, + label: t("Preview"), + icon: "EyeIcon", + onClick: this.onClickLinkEdit, + disabled: true, + }; + case "view": + return { + key: option, + label: t("View"), + icon: "/static/images/eye.react.svg", + onClick: this.onMediaFileClick, + disabled: false, + }; + case "download": + return { + key: option, + label: t("Download"), + icon: "images/download.react.svg", + onClick: this.onClickDownload, + disabled: false, + }; + case "download-as": + return { + key: option, + label: t("DownloadAs"), + icon: "images/download-as.react.svg", + onClick: this.onClickDownloadAs, + disabled: false, + }; + case "move-to": + return { + key: option, + label: t("MoveTo"), + icon: "images/move.react.svg", + onClick: this.onMoveAction, + disabled: false, + }; + case "restore": + return { + key: option, + label: t("Restore"), + icon: "images/move.react.svg", + onClick: this.onMoveAction, + disabled: false, + }; + case "copy-to": + return { + key: option, + label: t("Copy"), + icon: "/static/images/copy.react.svg", + onClick: this.onCopyAction, + disabled: false, + }; + case "copy": + return { + key: option, + label: t("Duplicate"), + icon: "/static/images/copy.react.svg", + onClick: this.onDuplicate, + disabled: false, + }; + case "rename": + return { + key: option, + label: t("Rename"), + icon: "images/rename.react.svg", + onClick: this.onClickRename, + disabled: false, + }; + case "change-thirdparty-info": + return { + key: option, + label: t("ThirdPartyInfo"), + icon: "/static/images/access.edit.react.svg", + onClick: this.onChangeThirdPartyInfo, + disabled: false, + }; + case "delete": + return { + key: option, + label: isThirdPartyFolder ? t("DeleteThirdParty") : t("Delete"), + icon: "/static/images/catalog.trash.react.svg", + onClick: this.onClickDelete, + disabled: false, + }; + case "remove-from-favorites": + return { + key: option, + label: t("RemoveFromFavorites"), + icon: "images/favorites.react.svg", + onClick: this.onClickFavorite, + disabled: false, + "data-action": "remove", + action: "remove", + }; + default: + break; + } + + return undefined; + }); + }; + + render() { + const { + item, + isRecycleBin, + draggable, + canShare, + isPrivacy, + actionType, + actionExtension, + actionId, + sectionWidth, + checked, + dragging, + } = this.props; + const { + fileExst, + access, + contentLength, + id, + shared, + contextOptions, + } = item; + + const isEdit = + !!actionType && actionId === id && fileExst === actionExtension; + + const isDragging = !fileExst && access < 2 && !isRecycleBin; + + let className = isDragging ? " droppable" : ""; + if (draggable) className += " draggable not-selectable"; + + let value = fileExst || contentLength ? `file_${id}` : `folder_${id}`; + value += draggable ? "_draggable" : ""; + + const isMobile = sectionWidth < 500; + const displayShareButton = isMobile + ? "26px" + : !canShare + ? "38px" + : "96px"; + + const sharedButton = + !canShare || (isPrivacy && !fileExst) || isEdit || id <= 0 || isMobile + ? null + : this.getSharedButton(shared); + + const contextOptionsProps = + !isEdit && contextOptions && contextOptions.length > 0 + ? { + contextOptions: this.getFilesContextOptions(), + } + : {}; + + const checkedProps = isEdit || id <= 0 ? {} : { checked }; + const element = this.getItemIcon(isEdit || id <= 0); + + return ( + + ); + } + } + + return inject( + ( + { + filesActionsStore, + dialogsStore, + treeFoldersStore, + selectedFolderStore, + filesStore, + uploadDataStore, + auth, + mediaViewerDataStore, + settingsStore, + versionHistoryStore, + }, + { item, t, history } + ) => { + const { + selectRowAction, + onSelectItem, + openLocationAction, + finalizeVersionAction, + setFavoriteAction, + lockFileAction, + downloadAction, + duplicateAction, + setThirdpartyInfo, + deleteFileAction, + deleteFolderAction, + } = filesActionsStore; + const { + setSharingPanelVisible, + setChangeOwnerPanelVisible, + setMoveToPanelVisible, + setCopyPanelVisible, + setDownloadDialogVisible, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + setDeleteDialogVisible, + } = dialogsStore; + const { isPrivacyFolder, isRecycleBinFolder } = treeFoldersStore; + const { id: selectedFolderId, isRootFolder } = selectedFolderStore; + const { + dragging, + setDragging, + selection, + setTooltipPosition, + setStartDrag, + openDocEditor, + fileActionStore, + canShare, + isFileSelected, + } = filesStore; + const { setAction } = fileActionStore; + const { startUpload } = uploadDataStore; + const { type, extension, id } = filesStore.fileActionStore; + const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; + const { isTabletView } = auth.settingsStore; + const { setMediaViewerData } = mediaViewerDataStore; + + const selectedItem = selection.find( + (x) => x.id === item.id && x.fileExst === item.fileExst + ); + + const draggable = + !isRecycleBinFolder && selectedItem && selectedItem.id !== id; + + const isFolder = selectedItem + ? false + : item.fileExst || item.contentLength + ? false + : true; + + const isThirdPartyFolder = item.providerKey && isRootFolder; + + return { + t, + item, + selectRowAction, + onSelectItem, + setSharingPanelVisible, + isPrivacy: isPrivacyFolder, + selectedFolderId, + dragging, + setDragging, + startUpload, + draggable, + setTooltipPosition, + setStartDrag, + history, + isFolder, + openLocationAction, + setChangeOwnerPanelVisible, + setMoveToPanelVisible, + setCopyPanelVisible, + isTabletView, + fetchFileVersions, + setIsVerHistoryPanel, + homepage: config.homepage, + finalizeVersionAction, + setFavoriteAction, + lockFileAction, + openDocEditor, + setDownloadDialogVisible, + downloadAction, + duplicateAction, + setAction, + setThirdpartyInfo, + setMediaViewerData, + isRootFolder, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + confirmDelete: settingsStore.confirmDelete, + setDeleteDialogVisible, + deleteFileAction, + deleteFolderAction, + isThirdPartyFolder, + canShare, + actionType: type, + actionExtension: extension, + actionId: fileActionStore.id, + checked: isFileSelected(item.id, item.parentId), + }; + } + )(observer(WithFileActions)); +} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js new file mode 100644 index 0000000000..269b65c366 --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js @@ -0,0 +1,10 @@ +import styled from "styled-components"; + +export const EncryptedFileIcon = styled.div` + background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent; + height: 16px; + position: absolute; + width: 16px; + margin-top: 14px; + margin-left: ${(props) => (props.isEdit ? "40px" : "12px")}; +`; From 0131520988cd08b7ba1547ed96573d178ff0e948 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 11:42:19 +0300 Subject: [PATCH 02/19] Web: Files: refactoring Tile, fix drag, moved EditingWraperComponent to sub-components --- .../Section/Body/FilesRow/FilesRowContent.js | 2 +- .../Section/Body/FilesRow/SimpleFilesRow.js | 1 - .../Body/{ => FilesTile}/BadgesFileTile.js | 0 .../Home/Section/Body/FilesTile/FileTile.js | 64 +++++++++++++++++++ .../Body/{ => FilesTile}/FilesTileContent.js | 2 +- .../{ => FilesTile/sub-components}/Tile.js | 0 .../sub-components}/TileContainer.js | 0 .../sub-components}/TileContent.js | 0 .../Home/Section/Body/hoc/withFileActions.js | 5 +- .../EditingWrapperComponent.js | 0 10 files changed, 69 insertions(+), 5 deletions(-) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => FilesTile}/BadgesFileTile.js (100%) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => FilesTile}/FilesTileContent.js (99%) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => FilesTile/sub-components}/Tile.js (100%) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => FilesTile/sub-components}/TileContainer.js (100%) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => FilesTile/sub-components}/TileContent.js (100%) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/{ => sub-components}/EditingWrapperComponent.js (100%) diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index 9934c1d5ed..27e90bbec7 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -26,7 +26,7 @@ import CrossIcon from "../../../../../../../../../../public/images/cross.react.s import { TIMEOUT } from "../../../../../../helpers/constants"; import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; import { ConvertDialog } from "../../../../../dialogs"; -import EditingWrapperComponent from "../EditingWrapperComponent"; +import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; import { isMobile } from "react-device-detect"; import { observer, inject } from "mobx-react"; import config from "../../../../../../../package.json"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js index e191384d2e..638c02eb94 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js @@ -1,6 +1,5 @@ import React from "react"; import styled from "styled-components"; -import { inject, observer } from "mobx-react"; import { withTranslation } from "react-i18next"; import DragAndDrop from "@appserver/components/drag-and-drop"; import Row from "@appserver/components/row"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/BadgesFileTile.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/BadgesFileTile.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/BadgesFileTile.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/BadgesFileTile.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js new file mode 100644 index 0000000000..868c7e560d --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js @@ -0,0 +1,64 @@ +import React from "react"; +import styled from "styled-components"; +import { withTranslation } from "react-i18next"; +import DragAndDrop from "@appserver/components/drag-and-drop"; + +import Tile from "./sub-components/Tile"; +import FilesTileContent from "./FilesTileContent"; +import { withRouter } from "react-router-dom"; +import { createSelectable } from "react-selectable-fast"; + +import withFileActions from "../hoc/withFileActions"; + +const FilesTile = createSelectable((props) => { + const { + item, + sectionWidth, + dragging, + onContentRowSelect, + rowContextClick, + onDrop, + onMouseDown, + className, + isDragging, + value, + displayShareButton, + isPrivacy, + sharedButton, + contextOptionsProps, + checkedProps, + element, + } = props; + + return ( +
+ + + + + +
+ ); +}); + +export default withTranslation("Home")(withFileActions(withRouter(FilesTile))); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTileContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js similarity index 99% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTileContent.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js index bde292e9ab..0c5e427622 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTileContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js @@ -10,7 +10,7 @@ import { FileAction, AppServerConfig } from "@appserver/common/constants"; import toastr from "studio/toastr"; import { getTitleWithoutExst } from "../../../../../helpers/files-helpers"; import { NewFilesPanel } from "../../../../panels"; -import EditingWrapperComponent from "./EditingWrapperComponent"; +import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; import TileContent from "./TileContent"; import { isMobile } from "react-device-detect"; import { inject, observer } from "mobx-react"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/Tile.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/Tile.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/Tile.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/Tile.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/TileContainer.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/TileContainer.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/TileContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContent.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/TileContent.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContent.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js index a6e65be7e2..61d02032b8 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js @@ -516,6 +516,7 @@ export default function withFileActions(WrappedFileItem) { sectionWidth, checked, dragging, + isFolder, } = this.props; const { fileExst, @@ -529,7 +530,7 @@ export default function withFileActions(WrappedFileItem) { const isEdit = !!actionType && actionId === id && fileExst === actionExtension; - const isDragging = !fileExst && access < 2 && !isRecycleBin; + const isDragging = isFolder && access < 2 && !isRecycleBin; let className = isDragging ? " droppable" : ""; if (draggable) className += " draggable not-selectable"; @@ -651,7 +652,7 @@ export default function withFileActions(WrappedFileItem) { const isFolder = selectedItem ? false - : item.fileExst || item.contentLength + : item.fileExst //|| item.contentLength ? false : true; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EditingWrapperComponent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EditingWrapperComponent.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js From 6381a0c524261845a15df2ccc51f796ee8698a71 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 16:00:19 +0300 Subject: [PATCH 03/19] Web: Files: refactoring FilesRowContent, withContentActions --- .../Section/Body/FilesRow/FilesRowContent.js | 1041 ++++------------- .../Section/Body/hoc/withContentActions.js | 624 ++++++++++ .../Home/Section/Body/sub-components/icons.js | 53 + 3 files changed, 896 insertions(+), 822 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index 27e90bbec7..d3da858337 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -1,77 +1,24 @@ import React from "react"; import { withRouter } from "react-router"; -import { Trans, withTranslation } from "react-i18next"; +import { withTranslation } from "react-i18next"; import styled from "styled-components"; +import { isMobile } from "react-device-detect"; + import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import RowContent from "@appserver/components/row-content"; import IconButton from "@appserver/components/icon-button"; import Badge from "@appserver/components/badge"; -import commonIconsStyles from "@appserver/components/utils/common-icons-style"; + +import withContentActions from "../hoc/withContentActions"; import { - convertFile, - getFileConversationProgress, -} from "@appserver/common/api/files"; -import { - AppServerConfig, - FileAction, - ShareAccessRights, -} from "@appserver/common/constants"; -import toastr from "studio/toastr"; -import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg"; -import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg"; -import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg"; -import CheckIcon from "../../../../../../../public/images/check.react.svg"; -import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg"; -import { TIMEOUT } from "../../../../../../helpers/constants"; -import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; -import { ConvertDialog } from "../../../../../dialogs"; -import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; -import { isMobile } from "react-device-detect"; -import { observer, inject } from "mobx-react"; -import config from "../../../../../../../package.json"; -import { combineUrl } from "@appserver/common/utils"; + StyledFavoriteIcon, + StyledFileActionsConvertEditDocIcon, + StyledFileActionsLockedIcon, +} from "../sub-components/icons"; const sideColor = "#A3A9AE"; -const StyledCheckIcon = styled(CheckIcon)` - ${commonIconsStyles} - path { - fill: #a3a9ae; - } - :hover { - fill: #657077; - } -`; -const StyledCrossIcon = styled(CrossIcon)` - ${commonIconsStyles} - path { - fill: #a3a9ae; - } - :hover { - fill: #657077; - } -`; - -const StyledFavoriteIcon = styled(FavoriteIcon)` - ${commonIconsStyles} -`; - -const StyledFileActionsConvertEditDocIcon = styled( - FileActionsConvertEditDocIcon -)` - ${commonIconsStyles} - path { - fill: #3b72a7; - } -`; - -const StyledFileActionsLockedIcon = styled(FileActionsLockedIcon)` - ${commonIconsStyles} - path { - fill: #3b72a7; - } -`; const SimpleFilesRowContent = styled(RowContent)` .badge-ext { margin-left: -8px; @@ -107,511 +54,82 @@ const SimpleFilesRowContent = styled(RowContent)` } `; -const okIcon = ; +const FilesRowContent = ({ + t, + item, + sectionWidth, + titleWithoutExt, + updatedDate, + fileOwner, + accessToEdit, + linkStyles, + newItems, + showNew, + canWebEdit, + /* canConvert,*/ + isTrashFolder, + onFilesClick, + onShowVersionHistory, + onBadgeClick, + onClickLock, + onClickFavorite, + /*setConvertDialogVisible*/ +}) => { + const { + contentLength, + fileExst, + filesCount, + foldersCount, + fileStatus, + id, + versionGroup, + locked, + providerKey, + } = item; -const cancelIcon = ( - -); - -class FilesRowContent extends React.PureComponent { - constructor(props) { - super(props); - let titleWithoutExt = getTitleWithoutExst(props.item); - - if (props.fileActionId === -1) { - titleWithoutExt = this.getDefaultName(props.fileActionExt); - } - - this.state = { - itemTitle: titleWithoutExt, - showConvertDialog: false, - //loading: false - }; - } - - completeAction = (id) => { - const isCancel = - (id.currentTarget && id.currentTarget.dataset.action === "cancel") || - id.keyCode === 27; - this.props.editCompleteAction(id, this.props.item, isCancel); + const onMobileRowClick = () => { + if (isTrashFolder || window.innerWidth > 1024) return; + onFilesClick(); }; - updateItem = () => { - const { - updateFile, - renameFolder, - item, - setIsLoading, - fileActionId, - editCompleteAction, - } = this.props; - - const { itemTitle } = this.state; - const originalTitle = getTitleWithoutExst(item); - - setIsLoading(true); - const isSameTitle = - originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === ""; - if (isSameTitle) { - this.setState({ - itemTitle: originalTitle, - }); - return editCompleteAction(fileActionId, item, isSameTitle); - } - - item.fileExst || item.contentLength - ? updateFile(fileActionId, itemTitle) - .then(() => this.completeAction(fileActionId)) - .finally(() => setIsLoading(false)) - : renameFolder(fileActionId, itemTitle) - .then(() => this.completeAction(fileActionId)) - .finally(() => setIsLoading(false)); - }; - - createItem = (e) => { - const { - createFile, - item, - setIsLoading, - openDocEditor, - isPrivacy, - isDesktop, - replaceFileStream, - t, - setEncryptionAccess, - createFolder, - } = this.props; - const { itemTitle } = this.state; - - setIsLoading(true); - - const itemId = e.currentTarget.dataset.itemid; - - if (itemTitle.trim() === "") { - toastr.warning(this.props.t("CreateWithEmptyTitle")); - return this.completeAction(itemId); - } - - let tab = - !isDesktop && item.fileExst - ? window.open( - combineUrl( - AppServerConfig.proxyURL, - config.homepage, - "/products/files/doceditor" - ), - "_blank" - ) - : null; - - !item.fileExst && !item.contentLength - ? createFolder(item.parentId, itemTitle) - .then(() => this.completeAction(itemId)) - .then(() => - toastr.success( - - New folder {{ itemTitle }} is created - - ) - ) - .catch((e) => toastr.error(e)) - .finally(() => { - return setIsLoading(false); - }) - : createFile(item.parentId, `${itemTitle}.${item.fileExst}`) - .then((file) => { - if (isPrivacy) { - return setEncryptionAccess(file).then((encryptedFile) => { - if (!encryptedFile) return Promise.resolve(); - toastr.info(t("EncryptedFileSaving")); - return replaceFileStream( - file.id, - encryptedFile, - true, - false - ).then(() => - openDocEditor(file.id, file.providerKey, tab, file.webUrl) - ); - }); - } - return openDocEditor(file.id, file.providerKey, tab, file.webUrl); - }) - .then(() => this.completeAction(itemId)) - .then(() => { - const exst = item.fileExst; - return toastr.success( - - New file {{ itemTitle }}.{{ exst }} is created - - ); - }) - .catch((e) => toastr.error(e)) - .finally(() => { - return setIsLoading(false); - }); - }; - - componentDidUpdate(prevProps) { - const { fileActionId, fileActionExt } = this.props; - if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) { - const itemTitle = this.getDefaultName(fileActionExt); - this.setState({ itemTitle }); - } - // if (fileAction) { - // if (fileActionId !== prevProps.fileActionId) { - // this.setState({ editingId: fileActionId }); - // } - // } - } - - renameTitle = (e) => { - let title = e.target.value; - //const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate - const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim"); - if (title.match(regexp)) { - toastr.warning(this.props.t("ContainsSpecCharacter")); - } - title = title.replace(regexp, "_"); - return this.setState({ itemTitle: title }); - }; - - cancelUpdateItem = (e) => { - const originalTitle = getTitleWithoutExst(this.props.item); - this.setState({ - itemTitle: originalTitle, - }); - - return this.completeAction(e); - }; - - onClickUpdateItem = (e) => { - this.props.fileActionType === FileAction.Create - ? this.createItem(e) - : this.updateItem(e); - }; - - onFilesClick = () => { - const { - filter, - parentFolder, - setIsLoading, - fetchFiles, - isImage, - isSound, - isVideo, - canWebEdit, - item, - isTrashFolder, - openDocEditor, - expandedKeys, - addExpandedKeys, - setMediaViewerData, - } = this.props; - const { id, fileExst, viewUrl, providerKey, contentLength } = item; - - if (isTrashFolder) return; - - if (!fileExst && !contentLength) { - setIsLoading(true); - - if (!expandedKeys.includes(parentFolder + "")) { - addExpandedKeys(parentFolder + ""); - } - - fetchFiles(id, filter) - .catch((err) => { - toastr.error(err); - setIsLoading(false); - }) - .finally(() => setIsLoading(false)); - } else { - if (canWebEdit) { - return openDocEditor(id, providerKey); - } - - if (isImage || isSound || isVideo) { - setMediaViewerData({ visible: true, id }); - return; - } - - return window.open(viewUrl, "_blank"); - } - }; - - onMobileRowClick = () => { - if (this.props.isTrashFolder || window.innerWidth > 1024) return; - this.onFilesClick(); - }; - - getStatusByDate = () => { - const { culture, t, item, sectionWidth } = this.props; - const { created, updated, version, fileExst } = item; - - const title = - version > 1 - ? t("TitleModified") - : fileExst - ? t("TitleUploaded") - : t("TitleCreated"); - - const date = fileExst ? updated : created; - const dateLabel = new Date(date).toLocaleString(culture); - const mobile = (sectionWidth && sectionWidth <= 375) || isMobile; - - return mobile ? dateLabel : `${title}: ${dateLabel}`; - }; - - getDefaultName = (format) => { - const { t } = this.props; - - switch (format) { - case "docx": - return t("NewDocument"); - case "xlsx": - return t("NewSpreadsheet"); - case "pptx": - return t("NewPresentation"); - default: - return t("NewFolder"); - } - }; - - onShowVersionHistory = () => { - const { - homepage, - isTabletView, - item, - setIsVerHistoryPanel, - fetchFileVersions, - history, - isTrashFolder, - } = this.props; - if (isTrashFolder) return; - - if (!isTabletView) { - fetchFileVersions(item.id + ""); - setIsVerHistoryPanel(true); - } else { - history.push( - combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`) - ); - } - }; - - onBadgeClick = () => { - const { - item, - selectedFolderPathParts, - markAsRead, - setNewFilesPanelVisible, - setNewFilesIds, - updateRootBadge, - updateFileBadge, - } = this.props; - if (item.fileExst) { - markAsRead([], [item.id]) - .then(() => { - updateRootBadge(selectedFolderPathParts[0], 1); - updateFileBadge(item.id); - }) - .catch((err) => toastr.error(err)); - } else { - setNewFilesPanelVisible(true); - const newFolderIds = this.props.selectedFolderPathParts; - newFolderIds.push(item.id); - setNewFilesIds(newFolderIds); - } - }; - - setConvertDialogVisible = () => - this.setState({ showConvertDialog: !this.state.showConvertDialog }); - - getConvertProgress = (fileId) => { - const { - selectedFolderId, - filter, - setIsLoading, - setSecondaryProgressBarData, - t, - clearSecondaryProgressData, - fetchFiles, - } = this.props; - getFileConversationProgress(fileId).then((res) => { - if (res && res[0] && res[0].progress !== 100) { - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: res[0].progress, - label: t("Convert"), - alert: false, - }); - setTimeout(() => this.getConvertProgress(fileId), 1000); - } else { - if (res[0].error) { - setSecondaryProgressBarData({ - visible: true, - alert: true, - }); - toastr.error(res[0].error); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - } else { - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: 100, - label: t("Convert"), - alert: false, - }); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - const newFilter = filter.clone(); - fetchFiles(selectedFolderId, newFilter) - .catch((err) => { - setSecondaryProgressBarData({ - visible: true, - alert: true, - }); - //toastr.error(err); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - }) - .finally(() => setIsLoading(false)); - } - } - }); - }; - - onConvert = () => { - const { item, t, setSecondaryProgressBarData } = this.props; - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: 0, - label: t("Convert"), - alert: false, - }); - this.setState({ showConvertDialog: false }, () => - convertFile(item.id).then((convertRes) => { - if (convertRes && convertRes[0] && convertRes[0].progress !== 100) { - this.getConvertProgress(item.id); - } - }) - ); - }; - - onClickLock = () => { - const { item } = this.props; - const { locked, id } = item; - this.props.lockFileAction(id, !locked).catch((err) => toastr.error(err)); - }; - - onClickFavorite = () => { - const { t, item } = this.props; - this.props - .setFavoriteAction("remove", item.id) - .then(() => toastr.success(t("RemovedFromFavorites"))) - .catch((err) => toastr.error(err)); - }; - render() { - const { - t, - item, - isTrashFolder, - isLoading, - isMobile, - canWebEdit, - /* canConvert,*/ - sectionWidth, - fileActionId, - fileActionExt, - } = this.props; - const { itemTitle, showConvertDialog } = this.state; - const { - contentLength, - updated, - createdBy, - fileExst, - filesCount, - foldersCount, - fileStatus, - id, - versionGroup, - locked, - providerKey, - } = item; - const titleWithoutExt = getTitleWithoutExst(item); - const fileOwner = - createdBy && - ((this.props.viewer.id === createdBy.id && t("AuthorMe")) || - createdBy.displayName); - const updatedDate = updated && this.getStatusByDate(); - - const accessToEdit = - item.access === ShareAccessRights.FullAccess || - item.access === ShareAccessRights.None; // TODO: fix access type for owner (now - None) - const isEdit = id === fileActionId && fileExst === fileActionExt; - - const linkStyles = isTrashFolder //|| window.innerWidth <= 1024 - ? { noHover: true } - : { onClick: this.onFilesClick }; - - const newItems = item.new || fileStatus === 2; - const showNew = !!newItems; - - return isEdit ? ( - - ) : ( - <> - {showConvertDialog && ( - - )} - + + - - {titleWithoutExt} - - <> - {fileExst ? ( -
- - {fileExst} - - {/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && ( + {titleWithoutExt} + + <> + {fileExst ? ( +
+ + {fileExst} + + {/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && ( )} */} - {canWebEdit && !isTrashFolder && accessToEdit && ( - - )} - {locked && ( - - )} - {fileStatus === 32 && !isTrashFolder && ( - - )} - {fileStatus === 1 && ( - - )} - {versionGroup > 1 && ( - - )} - {showNew && ( - - )} -
- ) : ( -
- {showNew && ( - - )} -
- )} - - - {fileOwner} - - - {(fileExst || contentLength || !providerKey) && - updatedDate && - updatedDate} - - - {fileExst || contentLength - ? contentLength - : !providerKey - ? `${t("TitleDocuments")}: ${filesCount} | ${t( - "TitleSubfolders" - )}: ${foldersCount}` - : ""} - - - - ); - } -} + {canWebEdit && !isTrashFolder && accessToEdit && ( + + )} + {locked && ( + + )} + {fileStatus === 32 && !isTrashFolder && ( + + )} + {fileStatus === 1 && ( + + )} + {versionGroup > 1 && ( + + )} + {showNew && ( + + )} +
+ ) : ( +
+ {showNew && ( + + )} +
+ )} + + + {fileOwner} + + + {(fileExst || contentLength || !providerKey) && + updatedDate && + updatedDate} + + + {fileExst || contentLength + ? contentLength + : !providerKey + ? `${t("TitleDocuments")}: ${filesCount} | ${t( + "TitleSubfolders" + )}: ${foldersCount}` + : ""} + +
+ + ); +}; -export default inject( - ( - { - auth, - filesStore, - formatsStore, - uploadDataStore, - treeFoldersStore, - selectedFolderStore, - filesActionsStore, - mediaViewerDataStore, - versionHistoryStore, - dialogsStore, - }, - { item } - ) => { - const { replaceFileStream, setEncryptionAccess } = auth; - const { culture, isDesktopClient, isTabletView } = auth.settingsStore; - const { secondaryProgressDataStore } = uploadDataStore; - const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; - const { - iconFormatsStore, - mediaViewersFormatsStore, - docserviceStore, - } = formatsStore; - - const { - fetchFiles, - filter, - createFile, - updateFile, - renameFolder, - createFolder, - openDocEditor, - setIsLoading, - isLoading, - updateFileBadge, - } = filesStore; - - const { - isRecycleBinFolder, - isPrivacyFolder, - expandedKeys, - addExpandedKeys, - updateRootBadge, - } = treeFoldersStore; - - const { - type: fileActionType, - extension: fileActionExt, - id: fileActionId, - } = filesStore.fileActionStore; - - const { - setSecondaryProgressBarData, - clearSecondaryProgressData, - } = secondaryProgressDataStore; - - const canWebEdit = docserviceStore.canWebEdit(item.fileExst); - const canConvert = docserviceStore.canConvert(item.fileExst); - const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); - const isImage = iconFormatsStore.isImage(item.fileExst); - const isSound = iconFormatsStore.isSound(item.fileExst); - - const { setMediaViewerData } = mediaViewerDataStore; - const { - editCompleteAction, - lockFileAction, - setFavoriteAction, - markAsRead, - } = filesActionsStore; - - const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore; - - return { - isDesktop: isDesktopClient, - isTabletView, - homepage: config.homepage, - viewer: auth.userStore.user, - culture, - fileActionId, - fileActionType, - fileActionExt, - selectedFolderId: selectedFolderStore.id, - selectedFolderPathParts: selectedFolderStore.pathParts, - parentFolder: selectedFolderStore.parentId, - isLoading, - isTrashFolder: isRecycleBinFolder, - isPrivacy: isPrivacyFolder, - filter, - canWebEdit, - canConvert, - isVideo, - isImage, - isSound, - expandedKeys, - - setIsLoading, - fetchFiles, - setSecondaryProgressBarData, - clearSecondaryProgressData, - createFile, - createFolder, - updateFile, - renameFolder, - replaceFileStream, - setEncryptionAccess, - addExpandedKeys, - openDocEditor, - editCompleteAction, - lockFileAction, - setFavoriteAction, - setMediaViewerData, - setIsVerHistoryPanel, - fetchFileVersions, - markAsRead, - setNewFilesPanelVisible, - setNewFilesIds, - updateRootBadge, - updateFileBadge, - }; - } -)(withRouter(withTranslation("Home")(observer(FilesRowContent)))); +export default withRouter( + withTranslation("Home")(withContentActions(FilesRowContent)) +); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js new file mode 100644 index 0000000000..4efc7e09da --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js @@ -0,0 +1,624 @@ +import React from "react"; +import { inject, observer } from "mobx-react"; +import { Trans } from "react-i18next"; +import { isMobile } from "react-device-detect"; + +import toastr from "studio/toastr"; +import { + AppServerConfig, + FileAction, + ShareAccessRights, +} from "@appserver/common/constants"; +import { combineUrl } from "@appserver/common/utils"; +import { + convertFile, + getFileConversationProgress, +} from "@appserver/common/api/files"; + +import config from "../../../../../../../package.json"; +import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; +import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; +import { cancelIcon, okIcon } from "../sub-components/icons"; +import { ConvertDialog } from "../../../../../dialogs"; + +export default function withContentActions(WrappedContent) { + class WithContentActions extends React.Component { + constructor(props) { + super(props); + let titleWithoutExt = getTitleWithoutExst(props.item); + + if (props.fileActionId === -1) { + titleWithoutExt = this.getDefaultName(props.fileActionExt); + } + + this.state = { + itemTitle: titleWithoutExt, + showConvertDialog: false, + //loading: false + }; + } + + componentDidUpdate(prevProps) { + const { fileActionId, fileActionExt } = this.props; + if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) { + const itemTitle = this.getDefaultName(fileActionExt); + this.setState({ itemTitle }); + } + // if (fileAction) { + // if (fileActionId !== prevProps.fileActionId) { + // this.setState({ editingId: fileActionId }); + // } + // } + } + + getDefaultName = (format) => { + const { t } = this.props; + + switch (format) { + case "docx": + return t("NewDocument"); + case "xlsx": + return t("NewSpreadsheet"); + case "pptx": + return t("NewPresentation"); + default: + return t("NewFolder"); + } + }; + + completeAction = (id) => { + const { editCompleteAction, item } = this.props; + + const isCancel = + (id.currentTarget && id.currentTarget.dataset.action === "cancel") || + id.keyCode === 27; + editCompleteAction(id, item, isCancel); + }; + + onFilesClick = () => { + const { + filter, + parentFolder, + setIsLoading, + fetchFiles, + isImage, + isSound, + isVideo, + canWebEdit, + item, + isTrashFolder, + openDocEditor, + expandedKeys, + addExpandedKeys, + setMediaViewerData, + } = this.props; + const { id, fileExst, viewUrl, providerKey, contentLength } = item; + + if (isTrashFolder) return; + + if (!fileExst && !contentLength) { + setIsLoading(true); + + if (!expandedKeys.includes(parentFolder + "")) { + addExpandedKeys(parentFolder + ""); + } + + fetchFiles(id, filter) + .catch((err) => { + toastr.error(err); + setIsLoading(false); + }) + .finally(() => setIsLoading(false)); + } else { + if (canWebEdit) { + return openDocEditor(id, providerKey); + } + + if (isImage || isSound || isVideo) { + setMediaViewerData({ visible: true, id }); + return; + } + + return window.open(viewUrl, "_blank"); + } + }; + + updateItem = () => { + const { + updateFile, + renameFolder, + item, + setIsLoading, + fileActionId, + editCompleteAction, + } = this.props; + + const { itemTitle } = this.state; + const originalTitle = getTitleWithoutExst(item); + + setIsLoading(true); + const isSameTitle = + originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === ""; + if (isSameTitle) { + this.setState({ + itemTitle: originalTitle, + }); + return editCompleteAction(fileActionId, item, isSameTitle); + } + + item.fileExst || item.contentLength + ? updateFile(fileActionId, itemTitle) + .then(() => this.completeAction(fileActionId)) + .finally(() => setIsLoading(false)) + : renameFolder(fileActionId, itemTitle) + .then(() => this.completeAction(fileActionId)) + .finally(() => setIsLoading(false)); + }; + + cancelUpdateItem = (e) => { + const { item } = this.props; + + const originalTitle = getTitleWithoutExst(item); + this.setState({ + itemTitle: originalTitle, + }); + + return this.completeAction(e); + }; + + onClickUpdateItem = (e) => { + const { fileActionType } = this.props; + + fileActionType === FileAction.Create + ? this.createItem(e) + : this.updateItem(e); + }; + + createItem = (e) => { + const { + createFile, + item, + setIsLoading, + openDocEditor, + isPrivacy, + isDesktop, + replaceFileStream, + t, + setEncryptionAccess, + createFolder, + } = this.props; + const { itemTitle } = this.state; + + setIsLoading(true); + + const itemId = e.currentTarget.dataset.itemid; + + if (itemTitle.trim() === "") { + toastr.warning(t("CreateWithEmptyTitle")); + return this.completeAction(itemId); + } + + let tab = + !isDesktop && item.fileExst + ? window.open( + combineUrl( + AppServerConfig.proxyURL, + config.homepage, + "/products/files/doceditor" + ), + "_blank" + ) + : null; + + !item.fileExst && !item.contentLength + ? createFolder(item.parentId, itemTitle) + .then(() => this.completeAction(itemId)) + .then(() => + toastr.success( + + New folder {{ itemTitle }} is created + + ) + ) + .catch((e) => toastr.error(e)) + .finally(() => { + return setIsLoading(false); + }) + : createFile(item.parentId, `${itemTitle}.${item.fileExst}`) + .then((file) => { + if (isPrivacy) { + return setEncryptionAccess(file).then((encryptedFile) => { + if (!encryptedFile) return Promise.resolve(); + toastr.info(t("EncryptedFileSaving")); + return replaceFileStream( + file.id, + encryptedFile, + true, + false + ).then(() => + openDocEditor(file.id, file.providerKey, tab, file.webUrl) + ); + }); + } + return openDocEditor(file.id, file.providerKey, tab, file.webUrl); + }) + .then(() => this.completeAction(itemId)) + .then(() => { + const exst = item.fileExst; + return toastr.success( + + New file {{ itemTitle }}.{{ exst }} is created + + ); + }) + .catch((e) => toastr.error(e)) + .finally(() => { + return setIsLoading(false); + }); + }; + + renameTitle = (e) => { + const { t } = this.props; + + let title = e.target.value; + //const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate + const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim"); + if (title.match(regexp)) { + toastr.warning(t("ContainsSpecCharacter")); + } + title = title.replace(regexp, "_"); + return this.setState({ itemTitle: title }); + }; + + getStatusByDate = () => { + const { culture, t, item, sectionWidth } = this.props; + const { created, updated, version, fileExst } = item; + + const title = + version > 1 + ? t("TitleModified") + : fileExst + ? t("TitleUploaded") + : t("TitleCreated"); + + const date = fileExst ? updated : created; + const dateLabel = new Date(date).toLocaleString(culture); + const mobile = (sectionWidth && sectionWidth <= 375) || isMobile; + + return mobile ? dateLabel : `${title}: ${dateLabel}`; + }; + + onShowVersionHistory = () => { + const { + homepage, + isTabletView, + item, + setIsVerHistoryPanel, + fetchFileVersions, + history, + isTrashFolder, + } = this.props; + if (isTrashFolder) return; + + if (!isTabletView) { + fetchFileVersions(item.id + ""); + setIsVerHistoryPanel(true); + } else { + history.push( + combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`) + ); + } + }; + + onBadgeClick = () => { + const { + item, + selectedFolderPathParts, + markAsRead, + setNewFilesPanelVisible, + setNewFilesIds, + updateRootBadge, + updateFileBadge, + } = this.props; + if (item.fileExst) { + markAsRead([], [item.id]) + .then(() => { + updateRootBadge(selectedFolderPathParts[0], 1); + updateFileBadge(item.id); + }) + .catch((err) => toastr.error(err)); + } else { + setNewFilesPanelVisible(true); + const newFolderIds = selectedFolderPathParts; + newFolderIds.push(item.id); + setNewFilesIds(newFolderIds); + } + }; + + setConvertDialogVisible = () => + this.setState({ showConvertDialog: !this.state.showConvertDialog }); + + onConvert = () => { + const { item, t, setSecondaryProgressBarData } = this.props; + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: 0, + label: t("Convert"), + alert: false, + }); + this.setState({ showConvertDialog: false }, () => + convertFile(item.id).then((convertRes) => { + if (convertRes && convertRes[0] && convertRes[0].progress !== 100) { + this.getConvertProgress(item.id); + } + }) + ); + }; + + getConvertProgress = (fileId) => { + const { + selectedFolderId, + filter, + setIsLoading, + setSecondaryProgressBarData, + t, + clearSecondaryProgressData, + fetchFiles, + } = this.props; + getFileConversationProgress(fileId).then((res) => { + if (res && res[0] && res[0].progress !== 100) { + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: res[0].progress, + label: t("Convert"), + alert: false, + }); + setTimeout(() => this.getConvertProgress(fileId), 1000); + } else { + if (res[0].error) { + setSecondaryProgressBarData({ + visible: true, + alert: true, + }); + toastr.error(res[0].error); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + } else { + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: 100, + label: t("Convert"), + alert: false, + }); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + const newFilter = filter.clone(); + fetchFiles(selectedFolderId, newFilter) + .catch((err) => { + setSecondaryProgressBarData({ + visible: true, + alert: true, + }); + //toastr.error(err); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + }) + .finally(() => setIsLoading(false)); + } + } + }); + }; + + onClickLock = () => { + const { item, lockFileAction } = this.props; + const { locked, id } = item; + + lockFileAction(id, !locked).catch((err) => toastr.error(err)); + }; + + onClickFavorite = () => { + const { t, item, setFavoriteAction } = this.props; + + setFavoriteAction("remove", item.id) + .then(() => toastr.success(t("RemovedFromFavorites"))) + .catch((err) => toastr.error(err)); + }; + + render() { + const { itemTitle, showConvertDialog } = this.state; + const { + item, + fileActionId, + fileActionExt, + isLoading, + viewer, + t, + isTrashFolder, + canWebEdit, + canConvert, + } = this.props; + const { id, fileExst, updated, createdBy, access, fileStatus } = item; + + const titleWithoutExt = getTitleWithoutExst(item); + + const isEdit = id === fileActionId && fileExst === fileActionExt; + + const updatedDate = updated && this.getStatusByDate(); + + const fileOwner = + createdBy && + ((viewer.id === createdBy.id && t("AuthorMe")) || + createdBy.displayName); + + const accessToEdit = + access === ShareAccessRights.FullAccess || + access === ShareAccessRights.None; // TODO: fix access type for owner (now - None) + + const linkStyles = isTrashFolder //|| window.innerWidth <= 1024 + ? { noHover: true } + : { onClick: this.onFilesClick }; + + const newItems = item.new || fileStatus === 2; + const showNew = !!newItems; + + return isEdit ? ( + + ) : ( + <> + {showConvertDialog && ( + + )} + + + ); + } + } + + return inject( + ( + { + filesActionsStore, + filesStore, + selectedFolderStore, + formatsStore, + treeFoldersStore, + mediaViewerDataStore, + auth, + versionHistoryStore, + dialogsStore, + uploadDataStore, + }, + { item, t, history } + ) => { + const { + editCompleteAction, + markAsRead, + lockFileAction, + setFavoriteAction, + } = filesActionsStore; + const { + filter, + setIsLoading, + fetchFiles, + openDocEditor, + updateFile, + renameFolder, + createFile, + createFolder, + isLoading, + updateFileBadge, + } = filesStore; + const { + iconFormatsStore, + mediaViewersFormatsStore, + docserviceStore, + } = formatsStore; + const { + isRecycleBinFolder, + expandedKeys, + addExpandedKeys, + isPrivacyFolder, + updateRootBadge, + } = treeFoldersStore; + const { setMediaViewerData } = mediaViewerDataStore; + const { + type: fileActionType, + extension: fileActionExt, + id: fileActionId, + } = filesStore.fileActionStore; + const { replaceFileStream, setEncryptionAccess } = auth; + const { culture, isDesktopClient, isTabletView } = auth.settingsStore; + const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; + const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore; + const { secondaryProgressDataStore } = uploadDataStore; + + const { + setSecondaryProgressBarData, + clearSecondaryProgressData, + } = secondaryProgressDataStore; + const isImage = iconFormatsStore.isImage(item.fileExst); + const isSound = iconFormatsStore.isSound(item.fileExst); + const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); + const canWebEdit = docserviceStore.canWebEdit(item.fileExst); + return { + t, + editCompleteAction, + filter, + parentFolder: selectedFolderStore.parentId, + setIsLoading, + fetchFiles, + isImage, + isSound, + isVideo, + canWebEdit, + isTrashFolder: isRecycleBinFolder, + openDocEditor, + expandedKeys, + addExpandedKeys, + setMediaViewerData, + updateFile, + renameFolder, + fileActionId, + editCompleteAction, + fileActionType, + createFile, + isPrivacy: isPrivacyFolder, + isDesktop: isDesktopClient, + replaceFileStream, + setEncryptionAccess, + createFolder, + fileActionExt, + isLoading, + culture, + homepage: config.homepage, + isTabletView, + setIsVerHistoryPanel, + fetchFileVersions, + history, + selectedFolderPathParts: selectedFolderStore.pathParts, + markAsRead, + setNewFilesPanelVisible, + setNewFilesIds, + updateRootBadge, + updateFileBadge, + setSecondaryProgressBarData, + clearSecondaryProgressData, + selectedFolderId: selectedFolderStore.id, + lockFileAction, + setFavoriteAction, + viewer: auth.userStore.user, + }; + } + )(observer(WithContentActions)); +} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js index 269b65c366..4fe4453111 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js @@ -1,5 +1,14 @@ +import React from "react"; import styled from "styled-components"; +import commonIconsStyles from "@appserver/components/utils/common-icons-style"; + +import CheckIcon from "../../../../../../../public/images/check.react.svg"; +import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg"; +import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg"; +import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg"; +import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg"; + export const EncryptedFileIcon = styled.div` background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent; height: 16px; @@ -8,3 +17,47 @@ export const EncryptedFileIcon = styled.div` margin-top: 14px; margin-left: ${(props) => (props.isEdit ? "40px" : "12px")}; `; + +const StyledCheckIcon = styled(CheckIcon)` + ${commonIconsStyles} + path { + fill: #a3a9ae; + } + :hover { + fill: #657077; + } +`; +export const okIcon = ; + +const StyledCrossIcon = styled(CrossIcon)` + ${commonIconsStyles} + path { + fill: #a3a9ae; + } + :hover { + fill: #657077; + } +`; +export const cancelIcon = ( + +); + +export const StyledFavoriteIcon = styled(FavoriteIcon)` + ${commonIconsStyles} +`; + +export const StyledFileActionsConvertEditDocIcon = styled( + FileActionsConvertEditDocIcon +)` + ${commonIconsStyles} + path { + fill: #3b72a7; + } +`; + +export const StyledFileActionsLockedIcon = styled(FileActionsLockedIcon)` + ${commonIconsStyles} + path { + fill: #3b72a7; + } +`; From 0bf59a8c98b948fcefe1190ee29eac8061f047b5 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 16:48:32 +0300 Subject: [PATCH 04/19] Web: Files: refactoring FilesTileContent --- .../Body/FilesTile/FilesTileContent.js | 543 ++++-------------- 1 file changed, 100 insertions(+), 443 deletions(-) diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js index 0c5e427622..31ec475521 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js @@ -1,23 +1,14 @@ import React from "react"; import { withRouter } from "react-router"; -import { Trans, withTranslation } from "react-i18next"; +import { withTranslation } from "react-i18next"; import styled from "styled-components"; + import Badge from "@appserver/components/badge"; import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; -import { markAsRead } from "@appserver/common/api/files"; -import { FileAction, AppServerConfig } from "@appserver/common/constants"; -import toastr from "studio/toastr"; -import { getTitleWithoutExst } from "../../../../../helpers/files-helpers"; -import { NewFilesPanel } from "../../../../panels"; -import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; + import TileContent from "./TileContent"; -import { isMobile } from "react-device-detect"; -import { inject, observer } from "mobx-react"; -import CheckIcon from "../../../../../../public/images/check.react.svg"; -import CrossIcon from "../../../../../../../../../public/images/cross.react.svg"; -import config from "../../../../../../package.json"; -import { combineUrl } from "@appserver/common/utils"; +import withContentActions from "../hoc/withContentActions"; const SimpleFilesTileContent = styled(TileContent)` .rowMainContainer { @@ -63,438 +54,104 @@ const SimpleFilesTileContent = styled(TileContent)` } `; -const okIcon = ( - -); +const FilesTileContent = ({ + t, + item, + sectionWidth, + titleWithoutExt, + updatedDate, + fileOwner, + accessToEdit, + linkStyles, + newItems, + showNew, + canWebEdit, + /* canConvert,*/ + isTrashFolder, + onFilesClick, + onShowVersionHistory, + onBadgeClick, + onClickLock, + onClickFavorite, + /*setConvertDialogVisible*/ +}) => { + const { + contentLength, + fileExst, + filesCount, + foldersCount, + fileStatus, + id, + versionGroup, + locked, + providerKey, + } = item; -const cancelIcon = ( - -); - -class FilesTileContent extends React.PureComponent { - constructor(props) { - super(props); - let titleWithoutExt = getTitleWithoutExst(props.item); - - if (props.fileAction.id === -1) { - titleWithoutExt = this.getDefaultName(props.fileAction.extension); - } - - this.state = { - itemTitle: titleWithoutExt, - editingId: props.fileAction.id, - showNewFilesPanel: false, - newFolderId: [], - newItems: props.item.new, - //loading: false - }; - } - - completeAction = (e) => { - //this.setState({ loading: false }, () =>) - this.props.onEditComplete(e); + const onMobileRowClick = () => { + if (isTrashFolder || window.innerWidth > 1024) return; + onFilesClick(); }; - updateItem = (e) => { - const { - fileAction, - updateFile, - renameFolder, - item, - setIsLoading, - } = this.props; - - const { itemTitle } = this.state; - const originalTitle = getTitleWithoutExst(item); - - setIsLoading(true); - if (originalTitle === itemTitle) return this.completeAction(e); - - item.fileExst - ? updateFile(fileAction.id, itemTitle) - .then(() => this.completeAction(e)) - .finally(() => setIsLoading(false)) - : renameFolder(fileAction.id, itemTitle) - .then(() => this.completeAction(e)) - .finally(() => setIsLoading(false)); - }; - - createItem = (e) => { - const { createFile, item, setIsLoading, createFolder, t } = this.props; - const { itemTitle } = this.state; - - setIsLoading(true); - - if (itemTitle.trim() === "") return this.completeAction(); - - !item.fileExst - ? createFolder(item.parentId, itemTitle) - .then(() => this.completeAction(e)) - .finally(() => { - toastr.success( - - New folder {{ itemTitle }} is created - - ); - return setIsLoading(false); - }) - : createFile(item.parentId, `${itemTitle}.${item.fileExst}`) - .then(() => this.completeAction(e)) - .finally(() => { - const exst = item.fileExst; - toastr.success( - - New file {{ itemTitle }}.{{ exst }} is created - - ); - return setIsLoading(false); - }); - }; - - componentDidUpdate(prevProps) { - const { fileAction } = this.props; - if (fileAction) { - if (fileAction.id !== prevProps.fileAction.id) { - this.setState({ editingId: fileAction.id }); - } - } - } - - renameTitle = (e) => { - this.setState({ itemTitle: e.target.value }); - }; - - cancelUpdateItem = (e) => { - //this.setState({ loading: false }); - this.completeAction(e); - }; - - onClickUpdateItem = () => { - this.props.fileAction.type === FileAction.Create - ? this.createItem() - : this.updateItem(); - }; - - onKeyUpUpdateItem = (e) => { - if (e.keyCode === 13) { - this.props.fileAction.type === FileAction.Create - ? this.createItem() - : this.updateItem(); - } - - if (e.keyCode === 27) return this.cancelUpdateItem(); - }; - - onFilesClick = () => { - const { id, fileExst, viewUrl, providerKey } = this.props.item; - const { - filter, - parentFolder, - setIsLoading, - onMediaFileClick, - fetchFiles, - canWebEdit, - openDocEditor, - isVideo, - isImage, - isSound, - expandedKeys, - addExpandedKeys, - } = this.props; - if (!fileExst) { - setIsLoading(true); - - if (!expandedKeys.includes(parentFolder + "")) { - addExpandedKeys(parentFolder + ""); - } - - fetchFiles(id, filter) - .catch((err) => { - toastr.error(err); - setIsLoading(false); - }) - .finally(() => setIsLoading(false)); - } else { - if (canWebEdit) { - return openDocEditor(id, providerKey); - } - - const isOpenMedia = isImage || isSound || isVideo; - - if (isOpenMedia) { - onMediaFileClick(id); - return; - } - - return window.open(viewUrl, "_blank"); - } - }; - - onMobileRowClick = (e) => { - if (!isMobile) return; - - this.onFilesClick(); - }; - - getStatusByDate = () => { - const { culture, t, item, sectionWidth } = this.props; - const { created, updated, version, fileExst } = item; - - const title = - version > 1 - ? t("TitleModified") - : fileExst - ? t("TitleUploaded") - : t("TitleCreated"); - - const date = fileExst ? updated : created; - const dateLabel = new Date(date).toLocaleString(culture); - const mobile = (sectionWidth && sectionWidth <= 375) || isMobile; - - return mobile ? dateLabel : `${title}: ${dateLabel}`; - }; - - getDefaultName = (format) => { - const { t } = this.props; - - switch (format) { - case "docx": - return t("NewDocument"); - case "xlsx": - return t("NewSpreadsheet"); - case "pptx": - return t("NewPresentation"); - default: - return t("NewFolder"); - } - }; - - onShowVersionHistory = (e) => { - const { homepage, history } = this.props; - const fileId = e.currentTarget.dataset.id; - - history.push( - combineUrl(AppServerConfig.proxyURL, homepage, `/${fileId}/history`) - ); - }; - - onBadgeClick = () => { - const { showNewFilesPanel } = this.state; - const { - item, - treeFolders, - setTreeFolders, - rootFolderId, - newItems, - filter, - fetchFiles, - } = this.props; - if (item.fileExst) { - markAsRead([], [item.id]) - .then(() => { - const data = treeFolders; - const dataItem = data.find((x) => x.id === rootFolderId); - dataItem.newItems = newItems ? dataItem.newItems - 1 : 0; //////newItems - setTreeFolders(data); - fetchFiles(this.props.selectedFolderId, filter.clone()); - }) - .catch((err) => toastr.error(err)); - } else { - const newFolderId = this.props.selectedFolderPathParts; - newFolderId.push(item.id); - this.setState({ - showNewFilesPanel: !showNewFilesPanel, - newFolderId, - }); - } - }; - - onShowNewFilesPanel = () => { - const { showNewFilesPanel } = this.state; - this.setState({ showNewFilesPanel: !showNewFilesPanel }); - }; - - render() { - const { item, fileAction, isTrashFolder, folders } = this.props; - const { - itemTitle, - editingId, - showNewFilesPanel, - newItems, - newFolderId, - } = this.state; - const { fileExst, id } = item; - - const titleWithoutExt = getTitleWithoutExst(item); - - const isEdit = id === editingId && fileExst === fileAction.extension; - const linkStyles = isTrashFolder - ? { noHover: true } - : { onClick: this.onFilesClick }; - const showNew = item.new && item.new > 0; - - return isEdit ? ( - - ) : ( - <> - {showNewFilesPanel && ( - - )} - + + - - {titleWithoutExt} - - <> - {fileExst ? ( -
- - {fileExst} - -
- ) : ( -
- {!!showNew && ( - - )} -
- )} - -
- - ); - } -} + {titleWithoutExt} + + <> + {fileExst ? ( +
+ + {fileExst} + +
+ ) : ( +
+ {!!showNew && ( + + )} +
+ )} + +
+ + ); +}; -export default inject( - ( - { auth, filesStore, formatsStore, treeFoldersStore, selectedFolderStore }, - { item } - ) => { - const { culture } = auth.settingsStore; - const { - iconFormatsStore, - mediaViewersFormatsStore, - docserviceStore, - } = formatsStore; - const { - folders, - fetchFiles, - filter, - newRowItems, - createFile, - updateFile, - renameFolder, - createFolder, - setIsLoading, - isLoading, - dragging, - } = filesStore; - - const { - treeFolders, - setTreeFolders, - isRecycleBinFolder, - expandedKeys, - addExpandedKeys, - } = treeFoldersStore; - - const { type, extension, id } = filesStore.fileActionStore; - - const fileAction = { type, extension, id }; - - const canWebEdit = docserviceStore.canWebEdit(item.fileExst); - const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); - const isImage = iconFormatsStore.isImage(item.fileExst); - const isSound = iconFormatsStore.isSound(item.fileExst); - - return { - culture, - homepage: config.homepage, - fileAction, - folders, - rootFolderId: selectedFolderStore.pathParts, - selectedFolderId: selectedFolderStore.id, - selectedFolderPathParts: selectedFolderStore.pathParts, - newItems: selectedFolderStore.new, - parentFolder: selectedFolderStore.parentId, - isLoading, - treeFolders, - isTrashFolder: isRecycleBinFolder, - filter, - dragging, - canWebEdit, - isVideo, - isImage, - isSound, - newRowItems, - expandedKeys, - - setIsLoading, - fetchFiles, - setTreeFolders, - createFile, - createFolder, - updateFile, - renameFolder, - addExpandedKeys, - }; - } -)(withRouter(withTranslation("Home")(observer(FilesTileContent)))); +export default withRouter( + withTranslation("Home")(withContentActions(FilesTileContent)) +); From 22b15ac51a8da3ead90cad526ccff98e01544f0b Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 17:28:49 +0300 Subject: [PATCH 05/19] Web: Files: refactoring: created Badges component, refactoring EditingWrapperComponent, FilesTileContent, FilesRowContent --- .../Section/Body/FilesRow/FilesRowContent.js | 155 ++++-------------- .../Body/FilesTile/FilesTileContent.js | 72 ++++---- .../Section/Body/hoc/withContentActions.js | 3 - .../Home/Section/Body/hoc/withFileActions.js | 2 +- .../Section/Body/sub-components/Badges.js | 123 ++++++++++++++ .../sub-components/EditingWrapperComponent.js | 31 +++- .../Home/Section/Body/sub-components/icons.js | 27 --- 7 files changed, 220 insertions(+), 193 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index d3da858337..e899f713df 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -7,15 +7,9 @@ import { isMobile } from "react-device-detect"; import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import RowContent from "@appserver/components/row-content"; -import IconButton from "@appserver/components/icon-button"; -import Badge from "@appserver/components/badge"; import withContentActions from "../hoc/withContentActions"; -import { - StyledFavoriteIcon, - StyledFileActionsConvertEditDocIcon, - StyledFileActionsLockedIcon, -} from "../sub-components/icons"; +import Badges from "../sub-components/Badges"; const sideColor = "#A3A9AE"; @@ -66,14 +60,14 @@ const FilesRowContent = ({ newItems, showNew, canWebEdit, - /* canConvert,*/ + canConvert, isTrashFolder, onFilesClick, onShowVersionHistory, onBadgeClick, onClickLock, onClickFavorite, - /*setConvertDialogVisible*/ + setConvertDialogVisible, }) => { const { contentLength, @@ -113,120 +107,37 @@ const FilesRowContent = ({ > {titleWithoutExt} - <> + +
{fileExst ? ( -
- - {fileExst} - - {/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && ( - - )} */} - {canWebEdit && !isTrashFolder && accessToEdit && ( - - )} - {locked && ( - - )} - {fileStatus === 32 && !isTrashFolder && ( - - )} - {fileStatus === 1 && ( - - )} - {versionGroup > 1 && ( - - )} - {showNew && ( - - )} -
- ) : ( -
- {showNew && ( - - )} -
- )} - + + {fileExst} + + ) : null} + +
{ const { contentLength, @@ -111,42 +111,38 @@ const FilesTileContent = ({ isTextOverflow > {titleWithoutExt} - - <> {fileExst ? ( -
- - {fileExst} - -
- ) : ( -
- {!!showNew && ( - - )} -
- )} - + + {fileExst} + + ) : null} + + +
+ +
); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js index 4efc7e09da..4be7ddaf31 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js @@ -18,7 +18,6 @@ import { import config from "../../../../../../../package.json"; import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; -import { cancelIcon, okIcon } from "../sub-components/icons"; import { ConvertDialog } from "../../../../../dialogs"; export default function withContentActions(WrappedContent) { @@ -464,8 +463,6 @@ export default function withContentActions(WrappedContent) { return isEdit ? (
; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js new file mode 100644 index 0000000000..6e18e4ea52 --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js @@ -0,0 +1,123 @@ +import React from "react"; +import Badge from "@appserver/components/badge"; +import IconButton from "@appserver/components/icon-button"; +import { + StyledFavoriteIcon, + StyledFileActionsConvertEditDocIcon, + StyledFileActionsLockedIcon, +} from "./Icons"; + +const Badges = ({ + newItems, + item, + canWebEdit, + isTrashFolder, + /* canConvert, */ + accessToEdit, + showNew, + onFilesClick, + onClickLock, + onClickFavorite, + onShowVersionHistory, + onBadgeClick, + /*setConvertDialogVisible*/ +}) => { + const { id, locked, fileStatus, versionGroup, title, fileExst } = item; + + return fileExst ? ( +
+ {/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && ( + + )} */} + {canWebEdit && !isTrashFolder && accessToEdit && ( + + )} + {locked && ( + + )} + {fileStatus === 32 && !isTrashFolder && ( + + )} + {fileStatus === 1 && ( + + )} + {versionGroup > 1 && ( + + )} + {showNew && ( + + )} +
+ ) : ( + showNew && ( + + ) + ); +}; + +export default Badges; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js index 20542112db..f9e5334d29 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js @@ -2,6 +2,35 @@ import React, { useState } from "react"; import styled from "styled-components"; import Button from "@appserver/components/button"; import TextInput from "@appserver/components/text-input"; +import commonIconsStyles from "@appserver/components/utils/common-icons-style"; + +import CheckIcon from "../../../../../../../public/images/check.react.svg"; +import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg"; + +const StyledCheckIcon = styled(CheckIcon)` + ${commonIconsStyles} + path { + fill: #a3a9ae; + } + :hover { + fill: #657077; + } +`; + +const StyledCrossIcon = styled(CrossIcon)` + ${commonIconsStyles} + path { + fill: #a3a9ae; + } + :hover { + fill: #657077; + } +`; + +export const okIcon = ; +export const cancelIcon = ( + +); const EditingWrapper = styled.div` width: 100%; @@ -49,8 +78,6 @@ const EditingWrapperComponent = (props) => { const { itemTitle, itemId, - okIcon, - cancelIcon, renameTitle, onClickUpdateItem, cancelUpdateItem, diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js index 4fe4453111..d573902375 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js @@ -1,10 +1,7 @@ -import React from "react"; import styled from "styled-components"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; -import CheckIcon from "../../../../../../../public/images/check.react.svg"; -import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg"; import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg"; import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg"; import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg"; @@ -18,30 +15,6 @@ export const EncryptedFileIcon = styled.div` margin-left: ${(props) => (props.isEdit ? "40px" : "12px")}; `; -const StyledCheckIcon = styled(CheckIcon)` - ${commonIconsStyles} - path { - fill: #a3a9ae; - } - :hover { - fill: #657077; - } -`; -export const okIcon = ; - -const StyledCrossIcon = styled(CrossIcon)` - ${commonIconsStyles} - path { - fill: #a3a9ae; - } - :hover { - fill: #657077; - } -`; -export const cancelIcon = ( - -); - export const StyledFavoriteIcon = styled(FavoriteIcon)` ${commonIconsStyles} `; From e22c641c9cdf83d67352d9cff1ea12b0dcb09d22 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Thu, 22 Apr 2021 23:56:18 +0300 Subject: [PATCH 06/19] Web: Files: refactoring: created withLoadingCheck HOC --- .../Body/FilesRow/FilesRowContainer.js | 45 +++------------- .../Home/Section/Body/hoc/withLoadingCheck.js | 51 +++++++++++++++++++ .../pages/Home/Section/Body/index.js | 50 ++++-------------- 3 files changed, 67 insertions(+), 79 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js index c63c072e9e..98897be0e9 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js @@ -1,42 +1,13 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; import { inject, observer } from "mobx-react"; import RowContainer from "@appserver/components/row-container"; import { Consumer } from "@appserver/components/utils/context"; import SimpleFilesRow from "./SimpleFilesRow"; -import Loaders from "@appserver/common/components/Loaders"; -import { isMobile } from "react-device-detect"; -let loadTimeout = null; +import withLoadingCheck from "../hoc/withLoadingCheck"; -const FilesRowContainer = ({ isLoaded, isLoading, filesList, tReady }) => { - const [inLoad, setInLoad] = useState(false); - - const cleanTimer = () => { - loadTimeout && clearTimeout(loadTimeout); - loadTimeout = null; - }; - - useEffect(() => { - if (isLoading) { - cleanTimer(); - loadTimeout = setTimeout(() => { - console.log("inLoad", true); - setInLoad(true); - }, 500); - } else { - cleanTimer(); - console.log("inLoad", false); - setInLoad(false); - } - - return () => { - cleanTimer(); - }; - }, [isLoading]); - - return !isLoaded || (isMobile && inLoad) || !tReady ? ( - - ) : ( +const FilesRowContainer = ({ filesList }) => { + return ( {(context) => ( { ); }; -export default inject(({ auth, filesStore }) => { - const { filesList, isLoading } = filesStore; +export default inject(({ filesStore }) => { + const { filesList } = filesStore; return { filesList, - isLoading, - isLoaded: auth.isLoaded, }; -})(observer(FilesRowContainer)); +})(withLoadingCheck(observer(FilesRowContainer))); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js new file mode 100644 index 0000000000..f5b785a503 --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js @@ -0,0 +1,51 @@ +import React, { useEffect, useState } from "react"; +import { observer, inject } from "mobx-react"; +import { isMobile } from "react-device-detect"; + +import Loaders from "@appserver/common/components/Loaders"; + +let loadTimeout = null; +export default function withLoadingCheck(WrappedComponent, type) { + const WithLoadingCheck = (props) => { + const { tReady, firstLoad, isLoaded, isLoading } = props; + const [inLoad, setInLoad] = useState(false); + + const cleanTimer = () => { + loadTimeout && clearTimeout(loadTimeout); + loadTimeout = null; + }; + + useEffect(() => { + if (isLoading) { + cleanTimer(); + loadTimeout = setTimeout(() => { + console.log("inLoad", true); + setInLoad(true); + }, 500); + } else { + cleanTimer(); + console.log("inLoad", false); + setInLoad(false); + } + + return () => { + cleanTimer(); + }; + }, [isLoading]); + + return firstLoad || !isLoaded || (isMobile && inLoad) || !tReady ? ( + + ) : ( + + ); + }; + + return inject(({ auth, filesStore }) => { + const { firstLoad, isLoading } = filesStore; + return { + firstLoad, + isLoaded: auth.isLoaded, + isLoading, + }; + })(observer(WithLoadingCheck)); +} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js index 640d9d3f4a..bfbff219c2 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js @@ -1,16 +1,15 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect } from "react"; import { withRouter } from "react-router"; import { withTranslation } from "react-i18next"; -import Loaders from "@appserver/common/components/Loaders"; import { isMobile } from "react-device-detect"; import { observer, inject } from "mobx-react"; import FilesRowContainer from "./FilesRow/FilesRowContainer"; import FilesTileContainer from "./FilesTile/FilesTileContainer"; import EmptyContainer from "./EmptyContainer"; -let currentDroppable = null; +import withLoadingCheck from "./hoc/withLoadingCheck"; -let loadTimeout = null; +let currentDroppable = null; const SectionBodyContent = (props) => { const { @@ -18,8 +17,6 @@ const SectionBodyContent = (props) => { tReady, fileActionId, viewAs, - firstLoad, - isLoading, isEmptyFilesList, folderId, dragging, @@ -31,31 +28,6 @@ const SectionBodyContent = (props) => { moveDragItems, } = props; - const [inLoad, setInLoad] = useState(false); - - const cleanTimer = () => { - loadTimeout && clearTimeout(loadTimeout); - loadTimeout = null; - }; - - useEffect(() => { - if (isLoading) { - cleanTimer(); - loadTimeout = setTimeout(() => { - console.log("inLoad", true); - setInLoad(true); - }, 500); - } else { - cleanTimer(); - console.log("inLoad", false); - setInLoad(false); - } - - return () => { - cleanTimer(); - }; - }, [isLoading]); - useEffect(() => { const customScrollElm = document.querySelector( "#customScrollBar > .scroll-body" @@ -174,11 +146,7 @@ const SectionBodyContent = (props) => { //console.log("Files Home SectionBodyContent render", props); return (!fileActionId && isEmptyFilesList) || null ? ( - firstLoad || (isMobile && inLoad) ? ( - - ) : ( - - ) + ) : viewAs === "tile" ? ( ) : ( @@ -194,14 +162,12 @@ export default inject( filesActionsStore, }) => { const { - firstLoad, fileActionStore, filesList, dragging, setDragging, startDrag, setStartDrag, - isLoading, viewAs, setTooltipPosition, } = filesStore; @@ -209,9 +175,7 @@ export default inject( return { dragging, fileActionId: fileActionStore.id, - firstLoad, viewAs, - isLoading, isEmptyFilesList: filesList.length <= 0, setDragging, startDrag, @@ -222,4 +186,8 @@ export default inject( moveDragItems: filesActionsStore.moveDragItems, }; } -)(withRouter(withTranslation("Home")(observer(SectionBodyContent)))); +)( + withRouter( + withTranslation("Home")(withLoadingCheck(observer(SectionBodyContent))) + ) +); From e90a9201bba5eaf306a15594b9cecc8e0f61cfe6 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Fri, 23 Apr 2021 14:10:42 +0300 Subject: [PATCH 07/19] Web: Files: refactoring: created withBadges HOC, rename withLoader, applied changes --- .../Body/FilesRow/FilesRowContainer.js | 4 +- .../Section/Body/FilesRow/FilesRowContent.js | 34 +-- .../pages/Home/Section/Body/hoc/withBadges.js | 271 ++++++++++++++++++ .../Section/Body/hoc/withContentActions.js | 224 ++------------- .../{withLoadingCheck.js => withLoader.js} | 0 .../pages/Home/Section/Body/index.js | 6 +- 6 files changed, 295 insertions(+), 244 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/{withLoadingCheck.js => withLoader.js} (100%) diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js index 98897be0e9..96518e92ef 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js @@ -4,8 +4,6 @@ import RowContainer from "@appserver/components/row-container"; import { Consumer } from "@appserver/components/utils/context"; import SimpleFilesRow from "./SimpleFilesRow"; -import withLoadingCheck from "../hoc/withLoadingCheck"; - const FilesRowContainer = ({ filesList }) => { return ( @@ -34,4 +32,4 @@ export default inject(({ filesStore }) => { return { filesList, }; -})(withLoadingCheck(observer(FilesRowContainer))); +})(observer(FilesRowContainer)); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index e899f713df..67c40e3859 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -10,6 +10,7 @@ import RowContent from "@appserver/components/row-content"; import withContentActions from "../hoc/withContentActions"; import Badges from "../sub-components/Badges"; +import withBadges from "../hoc/withBadges"; const sideColor = "#A3A9AE"; @@ -55,29 +56,16 @@ const FilesRowContent = ({ titleWithoutExt, updatedDate, fileOwner, - accessToEdit, linkStyles, - newItems, - showNew, - canWebEdit, - canConvert, isTrashFolder, onFilesClick, - onShowVersionHistory, - onBadgeClick, - onClickLock, - onClickFavorite, - setConvertDialogVisible, + badgesComponent, }) => { const { contentLength, fileExst, filesCount, foldersCount, - fileStatus, - id, - versionGroup, - locked, providerKey, } = item; @@ -122,21 +110,7 @@ const FilesRowContent = ({ {fileExst}
) : null} - + {badgesComponent}
{ + const { item, lockFileAction } = this.props; + const { locked, id } = item; + + lockFileAction(id, !locked).catch((err) => toastr.error(err)); + }; + + onClickFavorite = () => { + const { t, item, setFavoriteAction } = this.props; + + setFavoriteAction("remove", item.id) + .then(() => toastr.success(t("RemovedFromFavorites"))) + .catch((err) => toastr.error(err)); + }; + + onShowVersionHistory = () => { + const { + homepage, + isTabletView, + item, + setIsVerHistoryPanel, + fetchFileVersions, + history, + isTrashFolder, + } = this.props; + if (isTrashFolder) return; + + if (!isTabletView) { + fetchFileVersions(item.id + ""); + setIsVerHistoryPanel(true); + } else { + history.push( + combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`) + ); + } + }; + onBadgeClick = () => { + const { + item, + selectedFolderPathParts, + markAsRead, + setNewFilesPanelVisible, + setNewFilesIds, + updateRootBadge, + updateFileBadge, + } = this.props; + if (item.fileExst) { + markAsRead([], [item.id]) + .then(() => { + updateRootBadge(selectedFolderPathParts[0], 1); + updateFileBadge(item.id); + }) + .catch((err) => toastr.error(err)); + } else { + setNewFilesPanelVisible(true); + const newFolderIds = selectedFolderPathParts; + newFolderIds.push(item.id); + setNewFilesIds(newFolderIds); + } + }; + + setConvertDialogVisible = () => + this.setState({ showConvertDialog: !this.state.showConvertDialog }); + + onConvert = () => { + const { item, t, setSecondaryProgressBarData } = this.props; + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: 0, + label: t("Convert"), + alert: false, + }); + this.setState({ showConvertDialog: false }, () => + convertFile(item.id).then((convertRes) => { + if (convertRes && convertRes[0] && convertRes[0].progress !== 100) { + this.getConvertProgress(item.id); + } + }) + ); + }; + + getConvertProgress = (fileId) => { + const { + selectedFolderId, + filter, + setIsLoading, + setSecondaryProgressBarData, + t, + clearSecondaryProgressData, + fetchFiles, + } = this.props; + getFileConversationProgress(fileId).then((res) => { + if (res && res[0] && res[0].progress !== 100) { + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: res[0].progress, + label: t("Convert"), + alert: false, + }); + setTimeout(() => this.getConvertProgress(fileId), 1000); + } else { + if (res[0].error) { + setSecondaryProgressBarData({ + visible: true, + alert: true, + }); + toastr.error(res[0].error); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + } else { + setSecondaryProgressBarData({ + icon: "file", + visible: true, + percent: 100, + label: t("Convert"), + alert: false, + }); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + const newFilter = filter.clone(); + fetchFiles(selectedFolderId, newFilter) + .catch((err) => { + setSecondaryProgressBarData({ + visible: true, + alert: true, + }); + //toastr.error(err); + setTimeout(() => clearSecondaryProgressData(), TIMEOUT); + }) + .finally(() => setIsLoading(false)); + } + } + }); + }; + render() { + const { showConvertDialog } = this.state; + const { + item, + canWebEdit, + isTrashFolder, + canConvert, + onFilesClick, // from withContentAction HOC + } = this.props; + const { fileStatus, access } = item; + + const newItems = item.new || fileStatus === 2; + const showNew = !!newItems; + + const accessToEdit = + access === ShareAccessRights.FullAccess || + access === ShareAccessRights.None; // TODO: fix access type for owner (now - None) + + const badgesComponent = ( + + ); + + return ( + <> + {showConvertDialog && ( + + )} + + + ); + } + } + + return inject( + ( + { + auth, + formatsStore, + treeFoldersStore, + filesActionsStore, + versionHistoryStore, + selectedFolderStore, + dialogsStore, + filesStore, + uploadDataStore, + }, + { item, history, t } + ) => { + const { docserviceStore } = formatsStore; + const { isRecycleBinFolder, updateRootBadge } = treeFoldersStore; + const { + lockFileAction, + setFavoriteAction, + markAsRead, + } = filesActionsStore; + const { isTabletView } = auth.settingsStore; + const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; + const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore; + const { updateFileBadge, filter, setIsLoading, fetchFiles } = filesStore; + const { secondaryProgressDataStore } = uploadDataStore; + const { + setSecondaryProgressBarData, + clearSecondaryProgressData, + } = secondaryProgressDataStore; + + const canWebEdit = docserviceStore.canWebEdit(item.fileExst); + const canConvert = docserviceStore.canConvert(item.fileExst); + + return { + history, + t, + canWebEdit, + canConvert, + isTrashFolder: isRecycleBinFolder, + lockFileAction, + setFavoriteAction, + homepage: config.homepage, + isTabletView, + setIsVerHistoryPanel, + fetchFileVersions, + selectedFolderPathParts: selectedFolderStore.pathParts, + markAsRead, + setNewFilesPanelVisible, + setNewFilesIds, + updateRootBadge, + updateFileBadge, + setSecondaryProgressBarData, + selectedFolderId: selectedFolderStore.id, + filter, + setIsLoading, + clearSecondaryProgressData, + fetchFiles, + }; + } + )(observer(WithBadges)); +} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js index 4be7ddaf31..6748f1eb58 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js @@ -10,15 +10,10 @@ import { ShareAccessRights, } from "@appserver/common/constants"; import { combineUrl } from "@appserver/common/utils"; -import { - convertFile, - getFileConversationProgress, -} from "@appserver/common/api/files"; import config from "../../../../../../../package.json"; import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; -import { ConvertDialog } from "../../../../../dialogs"; export default function withContentActions(WrappedContent) { class WithContentActions extends React.Component { @@ -32,7 +27,7 @@ export default function withContentActions(WrappedContent) { this.state = { itemTitle: titleWithoutExt, - showConvertDialog: false, + //loading: false }; } @@ -287,144 +282,8 @@ export default function withContentActions(WrappedContent) { return mobile ? dateLabel : `${title}: ${dateLabel}`; }; - onShowVersionHistory = () => { - const { - homepage, - isTabletView, - item, - setIsVerHistoryPanel, - fetchFileVersions, - history, - isTrashFolder, - } = this.props; - if (isTrashFolder) return; - - if (!isTabletView) { - fetchFileVersions(item.id + ""); - setIsVerHistoryPanel(true); - } else { - history.push( - combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`) - ); - } - }; - - onBadgeClick = () => { - const { - item, - selectedFolderPathParts, - markAsRead, - setNewFilesPanelVisible, - setNewFilesIds, - updateRootBadge, - updateFileBadge, - } = this.props; - if (item.fileExst) { - markAsRead([], [item.id]) - .then(() => { - updateRootBadge(selectedFolderPathParts[0], 1); - updateFileBadge(item.id); - }) - .catch((err) => toastr.error(err)); - } else { - setNewFilesPanelVisible(true); - const newFolderIds = selectedFolderPathParts; - newFolderIds.push(item.id); - setNewFilesIds(newFolderIds); - } - }; - - setConvertDialogVisible = () => - this.setState({ showConvertDialog: !this.state.showConvertDialog }); - - onConvert = () => { - const { item, t, setSecondaryProgressBarData } = this.props; - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: 0, - label: t("Convert"), - alert: false, - }); - this.setState({ showConvertDialog: false }, () => - convertFile(item.id).then((convertRes) => { - if (convertRes && convertRes[0] && convertRes[0].progress !== 100) { - this.getConvertProgress(item.id); - } - }) - ); - }; - - getConvertProgress = (fileId) => { - const { - selectedFolderId, - filter, - setIsLoading, - setSecondaryProgressBarData, - t, - clearSecondaryProgressData, - fetchFiles, - } = this.props; - getFileConversationProgress(fileId).then((res) => { - if (res && res[0] && res[0].progress !== 100) { - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: res[0].progress, - label: t("Convert"), - alert: false, - }); - setTimeout(() => this.getConvertProgress(fileId), 1000); - } else { - if (res[0].error) { - setSecondaryProgressBarData({ - visible: true, - alert: true, - }); - toastr.error(res[0].error); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - } else { - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: 100, - label: t("Convert"), - alert: false, - }); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - const newFilter = filter.clone(); - fetchFiles(selectedFolderId, newFilter) - .catch((err) => { - setSecondaryProgressBarData({ - visible: true, - alert: true, - }); - //toastr.error(err); - setTimeout(() => clearSecondaryProgressData(), TIMEOUT); - }) - .finally(() => setIsLoading(false)); - } - } - }); - }; - - onClickLock = () => { - const { item, lockFileAction } = this.props; - const { locked, id } = item; - - lockFileAction(id, !locked).catch((err) => toastr.error(err)); - }; - - onClickFavorite = () => { - const { t, item, setFavoriteAction } = this.props; - - setFavoriteAction("remove", item.id) - .then(() => toastr.success(t("RemovedFromFavorites"))) - .catch((err) => toastr.error(err)); - }; - render() { - const { itemTitle, showConvertDialog } = this.state; + const { itemTitle } = this.state; const { item, fileActionId, @@ -433,8 +292,6 @@ export default function withContentActions(WrappedContent) { viewer, t, isTrashFolder, - canWebEdit, - canConvert, } = this.props; const { id, fileExst, updated, createdBy, access, fileStatus } = item; @@ -450,7 +307,7 @@ export default function withContentActions(WrappedContent) { createdBy.displayName); const accessToEdit = - access === ShareAccessRights.FullAccess || + access === ShareAccessRights.FullAccess || // only badges? access === ShareAccessRights.None; // TODO: fix access type for owner (now - None) const linkStyles = isTrashFolder //|| window.innerWidth <= 1024 @@ -470,34 +327,18 @@ export default function withContentActions(WrappedContent) { cancelUpdateItem={this.cancelUpdateItem} /> ) : ( - <> - {showConvertDialog && ( - - )} - - + ); } } @@ -512,18 +353,10 @@ export default function withContentActions(WrappedContent) { treeFoldersStore, mediaViewerDataStore, auth, - versionHistoryStore, - dialogsStore, - uploadDataStore, }, { item, t, history } ) => { - const { - editCompleteAction, - markAsRead, - lockFileAction, - setFavoriteAction, - } = filesActionsStore; + const { editCompleteAction } = filesActionsStore; const { filter, setIsLoading, @@ -534,7 +367,6 @@ export default function withContentActions(WrappedContent) { createFile, createFolder, isLoading, - updateFileBadge, } = filesStore; const { iconFormatsStore, @@ -546,7 +378,6 @@ export default function withContentActions(WrappedContent) { expandedKeys, addExpandedKeys, isPrivacyFolder, - updateRootBadge, } = treeFoldersStore; const { setMediaViewerData } = mediaViewerDataStore; const { @@ -555,15 +386,8 @@ export default function withContentActions(WrappedContent) { id: fileActionId, } = filesStore.fileActionStore; const { replaceFileStream, setEncryptionAccess } = auth; - const { culture, isDesktopClient, isTabletView } = auth.settingsStore; - const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; - const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore; - const { secondaryProgressDataStore } = uploadDataStore; + const { culture, isDesktopClient } = auth.settingsStore; - const { - setSecondaryProgressBarData, - clearSecondaryProgressData, - } = secondaryProgressDataStore; const isImage = iconFormatsStore.isImage(item.fileExst); const isSound = iconFormatsStore.isSound(item.fileExst); const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); @@ -599,21 +423,7 @@ export default function withContentActions(WrappedContent) { isLoading, culture, homepage: config.homepage, - isTabletView, - setIsVerHistoryPanel, - fetchFileVersions, history, - selectedFolderPathParts: selectedFolderStore.pathParts, - markAsRead, - setNewFilesPanelVisible, - setNewFilesIds, - updateRootBadge, - updateFileBadge, - setSecondaryProgressBarData, - clearSecondaryProgressData, - selectedFolderId: selectedFolderStore.id, - lockFileAction, - setFavoriteAction, viewer: auth.userStore.user, }; } diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoader.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoadingCheck.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoader.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js index bfbff219c2..d114d5ba90 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js @@ -7,7 +7,7 @@ import FilesRowContainer from "./FilesRow/FilesRowContainer"; import FilesTileContainer from "./FilesTile/FilesTileContainer"; import EmptyContainer from "./EmptyContainer"; -import withLoadingCheck from "./hoc/withLoadingCheck"; +import withLoader from "./hoc/withLoader"; let currentDroppable = null; @@ -187,7 +187,5 @@ export default inject( }; } )( - withRouter( - withTranslation("Home")(withLoadingCheck(observer(SectionBodyContent))) - ) + withRouter(withTranslation("Home")(withLoader(observer(SectionBodyContent)))) ); From 9f7bc2d3f2c10cfec61734f18c6f4fd6fdb4cd5a Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Fri, 23 Apr 2021 15:57:49 +0300 Subject: [PATCH 08/19] Web: Files: refactoring: created withContextOptions HOC, refactoring withFileActions --- .../Section/Body/FilesRow/SimpleFilesRow.js | 3 +- .../Section/Body/hoc/withContextOptions.js | 498 ++++++++++++++++++ .../Home/Section/Body/hoc/withFileActions.js | 468 +--------------- 3 files changed, 506 insertions(+), 463 deletions(-) create mode 100644 products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js index 638c02eb94..073eae46d2 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js @@ -8,6 +8,7 @@ import { withRouter } from "react-router-dom"; import { createSelectable } from "react-selectable-fast"; import withFileActions from "../hoc/withFileActions"; +import withContextOptions from "../hoc/withContextOptions"; const StyledSimpleFilesRow = styled(Row)` margin-top: -2px; @@ -97,5 +98,5 @@ const SimpleFilesRow = createSelectable((props) => { }); export default withTranslation("Home")( - withFileActions(withRouter(SimpleFilesRow)) + withFileActions(withContextOptions(withRouter(SimpleFilesRow))) ); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js new file mode 100644 index 0000000000..8efed90211 --- /dev/null +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js @@ -0,0 +1,498 @@ +import React from "react"; +import { inject, observer } from "mobx-react"; +import copy from "copy-to-clipboard"; + +import { combineUrl } from "@appserver/common/utils"; +import { FileAction, AppServerConfig } from "@appserver/common/constants"; +import toastr from "studio/toastr"; + +import config from "../../../../../../../package.json"; + +export default function withContextOptions(WrappedComponent) { + class WithContextOptions extends React.Component { + onOpenLocation = () => { + const { item, openLocationAction } = this.props; + const { id, folderId, fileExst } = item; + + const locationId = !fileExst ? id : folderId; + openLocationAction(locationId, !fileExst); + }; + + onOwnerChange = () => { + const { setChangeOwnerPanelVisible } = this.props; + setChangeOwnerPanelVisible(true); + }; + onMoveAction = () => { + const { setMoveToPanelVisible } = this.props; + setMoveToPanelVisible(true); + }; + onCopyAction = () => { + const { setCopyPanelVisible } = this.props; + setCopyPanelVisible(true); + }; + + showVersionHistory = () => { + const { + item, + isTabletView, + fetchFileVersions, + setIsVerHistoryPanel, + history, + homepage, + } = this.props; + const { id } = item; + + if (!isTabletView) { + fetchFileVersions(id + ""); + setIsVerHistoryPanel(true); + } else { + history.push( + combineUrl(AppServerConfig.proxyURL, homepage, `/${id}/history`) + ); + } + }; + + finalizeVersion = () => { + const { item, finalizeVersionAction } = this.props; + const { id } = item; + finalizeVersionAction(id).catch((err) => toastr.error(err)); + }; + + onClickFavorite = (e) => { + const { item, setFavoriteAction, t } = this.props; + const { id } = item; + const data = (e.currentTarget && e.currentTarget.dataset) || e; + const { action } = data; + + setFavoriteAction(action, id) + .then(() => + action === "mark" + ? toastr.success(t("MarkedAsFavorite")) + : toastr.success(t("RemovedFromFavorites")) + ) + .catch((err) => toastr.error(err)); + }; + + lockFile = () => { + const { item, lockFileAction } = this.props; + const { id, locked } = item; + lockFileAction(id, !locked).catch((err) => toastr.error(err)); + }; + + onClickLinkForPortal = () => { + const { item, homepage, t } = this.props; + const { fileExst, canOpenPlayer, webUrl } = item; + + const isFile = !!fileExst; + copy( + isFile + ? canOpenPlayer + ? `${window.location.href}&preview=${id}` + : webUrl + : `${window.location.origin + homepage}/filter?folder=${id}` + ); + + toastr.success(t("LinkCopySuccess")); + }; + + onClickLinkEdit = () => { + const { item, openDocEditor } = this.props; + const { id, providerKey } = item; + openDocEditor(id, providerKey); + }; + + onClickDownload = () => { + const { item, downloadAction, t } = this.props; + const { fileExst, contentLength, viewUrl } = item; + const isFile = !!fileExst && contentLength; + isFile + ? window.open(viewUrl, "_blank") + : downloadAction(t("ArchivingData")).catch((err) => toastr.error(err)); + }; + + onClickDownloadAs = () => { + const { setDownloadDialogVisible } = this.props; + setDownloadDialogVisible(true); + }; + + onDuplicate = () => { + const { duplicateAction, t, item } = this.props; + duplicateAction(item, t("CopyOperation")).catch((err) => + toastr.error(err) + ); + }; + + onClickRename = () => { + const { item, setAction } = this.props; + const { id, fileExst } = item; + setAction({ + type: FileAction.Rename, + extension: fileExst, + id, + }); + }; + + onChangeThirdPartyInfo = () => { + const { item, setThirdpartyInfo } = this.props; + const { providerKey } = item; + setThirdpartyInfo(providerKey); + }; + + onMediaFileClick = (fileId) => { + const { item, setMediaViewerData } = this.props; + const itemId = typeof fileId !== "object" ? fileId : item.id; + setMediaViewerData({ visible: true, id: itemId }); + }; + + onClickDelete = () => { + const { + item, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + confirmDelete, + setDeleteDialogVisible, + t, + deleteFileAction, + deleteFolderAction, + isThirdPartyFolder, + } = this.props; + const { id, title, fileExst, contentLength, folderId, parentId } = item; + + if (isThirdPartyFolder) { + const splitItem = id.split("-"); + setRemoveItem({ id: splitItem[splitItem.length - 1], title }); + setDeleteThirdPartyDialogVisible(true); + return; + } + + if (confirmDelete) { + setDeleteDialogVisible(true); + } else { + const translations = { + deleteOperation: t("DeleteOperation"), + }; + + fileExst || contentLength + ? deleteFileAction(id, folderId, translations) + .then(() => toastr.success(t("FileRemoved"))) + .catch((err) => toastr.error(err)) + : deleteFolderAction(id, parentId, translations) + .then(() => toastr.success(t("FolderRemoved"))) + .catch((err) => toastr.error(err)); + } + }; + + onClickShare = () => { + const { onSelectItem, setSharingPanelVisible, item } = this.props; + onSelectItem(item); + setSharingPanelVisible(true); + }; + + getFilesContextOptions = () => { + const { item, t, isThirdPartyFolder } = this.props; + const { access, contextOptions } = item; + const isSharable = access !== 1 && access !== 0; + return contextOptions.map((option) => { + switch (option) { + case "open": + return { + key: option, + label: t("Open"), + icon: "images/catalog.folder.react.svg", + onClick: this.onOpenLocation, + disabled: false, + }; + case "show-version-history": + return { + key: option, + label: t("ShowVersionHistory"), + icon: "images/history.react.svg", + onClick: this.showVersionHistory, + disabled: false, + }; + case "finalize-version": + return { + key: option, + label: t("FinalizeVersion"), + icon: "images/history-finalized.react.svg", + onClick: this.finalizeVersion, + disabled: false, + }; + case "separator0": + case "separator1": + case "separator2": + case "separator3": + return { key: option, isSeparator: true }; + case "open-location": + return { + key: option, + label: t("OpenLocation"), + icon: "images/download-as.react.svg", + onClick: this.onOpenLocation, + disabled: false, + }; + case "mark-as-favorite": + return { + key: option, + label: t("MarkAsFavorite"), + icon: "images/favorites.react.svg", + onClick: this.onClickFavorite, + disabled: false, + "data-action": "mark", + action: "mark", + }; + case "block-unblock-version": + return { + key: option, + label: t("UnblockVersion"), + icon: "images/lock.react.svg", + onClick: this.lockFile, + disabled: false, + }; + case "sharing-settings": + return { + key: option, + label: t("SharingSettings"), + icon: "images/catalog.shared.react.svg", + onClick: this.onClickShare, + disabled: isSharable, + }; + case "send-by-email": + return { + key: option, + label: t("SendByEmail"), + icon: "/static/images/mail.react.svg", + disabled: true, + }; + case "owner-change": + return { + key: option, + label: t("ChangeOwner"), + icon: "images/catalog.user.react.svg", + onClick: this.onOwnerChange, + disabled: false, + }; + case "link-for-portal-users": + return { + key: option, + label: t("LinkForPortalUsers"), + icon: "/static/images/invitation.link.react.svg", + onClick: this.onClickLinkForPortal, + disabled: false, + }; + case "edit": + return { + key: option, + label: t("Edit"), + icon: "/static/images/access.edit.react.svg", + onClick: this.onClickLinkEdit, + disabled: false, + }; + case "preview": + return { + key: option, + label: t("Preview"), + icon: "EyeIcon", + onClick: this.onClickLinkEdit, + disabled: true, + }; + case "view": + return { + key: option, + label: t("View"), + icon: "/static/images/eye.react.svg", + onClick: this.onMediaFileClick, + disabled: false, + }; + case "download": + return { + key: option, + label: t("Download"), + icon: "images/download.react.svg", + onClick: this.onClickDownload, + disabled: false, + }; + case "download-as": + return { + key: option, + label: t("DownloadAs"), + icon: "images/download-as.react.svg", + onClick: this.onClickDownloadAs, + disabled: false, + }; + case "move-to": + return { + key: option, + label: t("MoveTo"), + icon: "images/move.react.svg", + onClick: this.onMoveAction, + disabled: false, + }; + case "restore": + return { + key: option, + label: t("Restore"), + icon: "images/move.react.svg", + onClick: this.onMoveAction, + disabled: false, + }; + case "copy-to": + return { + key: option, + label: t("Copy"), + icon: "/static/images/copy.react.svg", + onClick: this.onCopyAction, + disabled: false, + }; + case "copy": + return { + key: option, + label: t("Duplicate"), + icon: "/static/images/copy.react.svg", + onClick: this.onDuplicate, + disabled: false, + }; + case "rename": + return { + key: option, + label: t("Rename"), + icon: "images/rename.react.svg", + onClick: this.onClickRename, + disabled: false, + }; + case "change-thirdparty-info": + return { + key: option, + label: t("ThirdPartyInfo"), + icon: "/static/images/access.edit.react.svg", + onClick: this.onChangeThirdPartyInfo, + disabled: false, + }; + case "delete": + return { + key: option, + label: isThirdPartyFolder ? t("DeleteThirdParty") : t("Delete"), + icon: "/static/images/catalog.trash.react.svg", + onClick: this.onClickDelete, + disabled: false, + }; + case "remove-from-favorites": + return { + key: option, + label: t("RemoveFromFavorites"), + icon: "images/favorites.react.svg", + onClick: this.onClickFavorite, + disabled: false, + "data-action": "remove", + action: "remove", + }; + default: + break; + } + + return undefined; + }); + }; + render() { + const { actionType, actionId, actionExtension, item } = this.props; + const { id, fileExst, contextOptions } = item; + + const isEdit = + !!actionType && actionId === id && fileExst === actionExtension; + + const contextOptionsProps = + !isEdit && contextOptions && contextOptions.length > 0 + ? { + contextOptions: this.getFilesContextOptions(), + } + : {}; + + return ( + + ); + } + } + + return inject( + ( + { + filesStore, + filesActionsStore, + auth, + versionHistoryStore, + mediaViewerDataStore, + settingsStore, + selectedFolderStore, + dialogsStore, + }, + { item } + ) => { + const { openDocEditor, fileActionStore } = filesStore; + const { + openLocationAction, + finalizeVersionAction, + setFavoriteAction, + lockFileAction, + downloadAction, + duplicateAction, + setThirdpartyInfo, + deleteFileAction, + deleteFolderAction, + onSelectItem, + } = filesActionsStore; + const { + setChangeOwnerPanelVisible, + setMoveToPanelVisible, + setCopyPanelVisible, + setDownloadDialogVisible, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + setDeleteDialogVisible, + setSharingPanelVisible, + } = dialogsStore; + const { isTabletView } = auth.settingsStore; + const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; + const { setAction, type, extension, id } = fileActionStore; + const { setMediaViewerData } = mediaViewerDataStore; + const { isRootFolder } = selectedFolderStore; + + const isThirdPartyFolder = item.providerKey && isRootFolder; + + return { + openLocationAction, + setChangeOwnerPanelVisible, + setMoveToPanelVisible, + setCopyPanelVisible, + isTabletView, + setIsVerHistoryPanel, + fetchFileVersions, + homepage: config.homepage, + finalizeVersionAction, + setFavoriteAction, + lockFileAction, + openDocEditor, + downloadAction, + setDownloadDialogVisible, + duplicateAction, + setAction, + setThirdpartyInfo, + setMediaViewerData, + setRemoveItem, + setDeleteThirdPartyDialogVisible, + confirmDelete: settingsStore.confirmDelete, + setDeleteDialogVisible, + deleteFileAction, + deleteFolderAction, + isThirdPartyFolder, + onSelectItem, + setSharingPanelVisible, + actionType: type, + actionId: id, + actionExtension: extension, + }; + } + )(observer(WithContextOptions)); +} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js index d29d766b06..134742175a 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js @@ -1,16 +1,11 @@ import React from "react"; import { inject, observer } from "mobx-react"; import { ReactSVG } from "react-svg"; -import copy from "copy-to-clipboard"; import IconButton from "@appserver/components/icon-button"; import Text from "@appserver/components/text"; -import { combineUrl } from "@appserver/common/utils"; -import { FileAction, AppServerConfig } from "@appserver/common/constants"; -import toastr from "studio/toastr"; import { EncryptedFileIcon } from "../sub-components/Icons"; -import config from "../../../../../../../package.json"; const svgLoader = () =>
; export default function withFileActions(WrappedFileItem) { @@ -124,385 +119,6 @@ export default function withFileActions(WrappedFileItem) { setStartDrag(true); }; - onOpenLocation = () => { - const { isFolder, item, openLocationAction } = this.props; - const { id, folderId, fileExst } = item; - - const locationId = !fileExst ? id : folderId; - console.log(locationId, id, folderId, isFolder); - openLocationAction(locationId, !fileExst); - }; - - onOwnerChange = () => { - const { setChangeOwnerPanelVisible } = this.props; - setChangeOwnerPanelVisible(true); - }; - onMoveAction = () => { - const { setMoveToPanelVisible } = this.props; - setMoveToPanelVisible(true); - }; - onCopyAction = () => { - const { setCopyPanelVisible } = this.props; - setCopyPanelVisible(true); - }; - - showVersionHistory = () => { - const { - item, - isTabletView, - fetchFileVersions, - setIsVerHistoryPanel, - history, - homepage, - } = this.props; - const { id } = item; - - if (!isTabletView) { - fetchFileVersions(id + ""); - setIsVerHistoryPanel(true); - } else { - history.push( - combineUrl(AppServerConfig.proxyURL, homepage, `/${id}/history`) - ); - } - }; - - finalizeVersion = () => { - const { item, finalizeVersionAction } = this.props; - const { id } = item; - finalizeVersionAction(id).catch((err) => toastr.error(err)); - }; - - onClickFavorite = (e) => { - const { item, setFavoriteAction, t } = this.props; - const { id } = item; - const data = (e.currentTarget && e.currentTarget.dataset) || e; - const { action } = data; - - setFavoriteAction(action, id) - .then(() => - action === "mark" - ? toastr.success(t("MarkedAsFavorite")) - : toastr.success(t("RemovedFromFavorites")) - ) - .catch((err) => toastr.error(err)); - }; - - lockFile = () => { - const { item, lockFileAction } = this.props; - const { id, locked } = item; - lockFileAction(id, !locked).catch((err) => toastr.error(err)); - }; - - onClickLinkForPortal = () => { - const { item, homepage, t } = this.props; - const { fileExst, canOpenPlayer, webUrl } = item; - - const isFile = !!fileExst; - copy( - isFile - ? canOpenPlayer - ? `${window.location.href}&preview=${id}` - : webUrl - : `${window.location.origin + homepage}/filter?folder=${id}` - ); - - toastr.success(t("LinkCopySuccess")); - }; - - onClickLinkEdit = () => { - const { item, openDocEditor } = this.props; - const { id, providerKey } = item; - openDocEditor(id, providerKey); - }; - - onClickDownload = () => { - const { item, downloadAction, t } = this.props; - const { fileExst, contentLength, viewUrl } = item; - const isFile = !!fileExst && contentLength; - isFile - ? window.open(viewUrl, "_blank") - : downloadAction(t("ArchivingData")).catch((err) => toastr.error(err)); - }; - - onClickDownloadAs = () => { - const { setDownloadDialogVisible } = this.props; - setDownloadDialogVisible(true); - }; - - onDuplicate = () => { - const { duplicateAction, t, item } = this.props; - duplicateAction(item, t("CopyOperation")).catch((err) => - toastr.error(err) - ); - }; - - onClickRename = () => { - const { item, setAction } = this.props; - const { id, fileExst } = item; - setAction({ - type: FileAction.Rename, - extension: fileExst, - id, - }); - }; - - onChangeThirdPartyInfo = () => { - const { item, setThirdpartyInfo } = this.props; - const { providerKey } = item; - setThirdpartyInfo(providerKey); - }; - - onMediaFileClick = (fileId) => { - const { item, setMediaViewerData } = this.props; - const itemId = typeof fileId !== "object" ? fileId : item.id; - setMediaViewerData({ visible: true, id: itemId }); - }; - - onClickDelete = () => { - const { - item, - setRemoveItem, - setDeleteThirdPartyDialogVisible, - confirmDelete, - setDeleteDialogVisible, - t, - deleteFileAction, - deleteFolderAction, - isThirdPartyFolder, - } = this.props; - const { id, title, fileExst, contentLength, folderId, parentId } = item; - - if (isThirdPartyFolder) { - const splitItem = id.split("-"); - setRemoveItem({ id: splitItem[splitItem.length - 1], title }); - setDeleteThirdPartyDialogVisible(true); - return; - } - - if (confirmDelete) { - setDeleteDialogVisible(true); - } else { - const translations = { - deleteOperation: t("DeleteOperation"), - }; - - fileExst || contentLength - ? deleteFileAction(id, folderId, translations) - .then(() => toastr.success(t("FileRemoved"))) - .catch((err) => toastr.error(err)) - : deleteFolderAction(id, parentId, translations) - .then(() => toastr.success(t("FolderRemoved"))) - .catch((err) => toastr.error(err)); - } - }; - - getFilesContextOptions = () => { - const { item, t, isThirdPartyFolder } = this.props; - const { access, contextOptions } = item; - const isSharable = access !== 1 && access !== 0; - return contextOptions.map((option) => { - switch (option) { - case "open": - return { - key: option, - label: t("Open"), - icon: "images/catalog.folder.react.svg", - onClick: this.onOpenLocation, - disabled: false, - }; - case "show-version-history": - return { - key: option, - label: t("ShowVersionHistory"), - icon: "images/history.react.svg", - onClick: this.showVersionHistory, - disabled: false, - }; - case "finalize-version": - return { - key: option, - label: t("FinalizeVersion"), - icon: "images/history-finalized.react.svg", - onClick: this.finalizeVersion, - disabled: false, - }; - case "separator0": - case "separator1": - case "separator2": - case "separator3": - return { key: option, isSeparator: true }; - case "open-location": - return { - key: option, - label: t("OpenLocation"), - icon: "images/download-as.react.svg", - onClick: this.onOpenLocation, - disabled: false, - }; - case "mark-as-favorite": - return { - key: option, - label: t("MarkAsFavorite"), - icon: "images/favorites.react.svg", - onClick: this.onClickFavorite, - disabled: false, - "data-action": "mark", - action: "mark", - }; - case "block-unblock-version": - return { - key: option, - label: t("UnblockVersion"), - icon: "images/lock.react.svg", - onClick: this.lockFile, - disabled: false, - }; - case "sharing-settings": - return { - key: option, - label: t("SharingSettings"), - icon: "images/catalog.shared.react.svg", - onClick: this.onClickShare, - disabled: isSharable, - }; - case "send-by-email": - return { - key: option, - label: t("SendByEmail"), - icon: "/static/images/mail.react.svg", - disabled: true, - }; - case "owner-change": - return { - key: option, - label: t("ChangeOwner"), - icon: "images/catalog.user.react.svg", - onClick: this.onOwnerChange, - disabled: false, - }; - case "link-for-portal-users": - return { - key: option, - label: t("LinkForPortalUsers"), - icon: "/static/images/invitation.link.react.svg", - onClick: this.onClickLinkForPortal, - disabled: false, - }; - case "edit": - return { - key: option, - label: t("Edit"), - icon: "/static/images/access.edit.react.svg", - onClick: this.onClickLinkEdit, - disabled: false, - }; - case "preview": - return { - key: option, - label: t("Preview"), - icon: "EyeIcon", - onClick: this.onClickLinkEdit, - disabled: true, - }; - case "view": - return { - key: option, - label: t("View"), - icon: "/static/images/eye.react.svg", - onClick: this.onMediaFileClick, - disabled: false, - }; - case "download": - return { - key: option, - label: t("Download"), - icon: "images/download.react.svg", - onClick: this.onClickDownload, - disabled: false, - }; - case "download-as": - return { - key: option, - label: t("DownloadAs"), - icon: "images/download-as.react.svg", - onClick: this.onClickDownloadAs, - disabled: false, - }; - case "move-to": - return { - key: option, - label: t("MoveTo"), - icon: "images/move.react.svg", - onClick: this.onMoveAction, - disabled: false, - }; - case "restore": - return { - key: option, - label: t("Restore"), - icon: "images/move.react.svg", - onClick: this.onMoveAction, - disabled: false, - }; - case "copy-to": - return { - key: option, - label: t("Copy"), - icon: "/static/images/copy.react.svg", - onClick: this.onCopyAction, - disabled: false, - }; - case "copy": - return { - key: option, - label: t("Duplicate"), - icon: "/static/images/copy.react.svg", - onClick: this.onDuplicate, - disabled: false, - }; - case "rename": - return { - key: option, - label: t("Rename"), - icon: "images/rename.react.svg", - onClick: this.onClickRename, - disabled: false, - }; - case "change-thirdparty-info": - return { - key: option, - label: t("ThirdPartyInfo"), - icon: "/static/images/access.edit.react.svg", - onClick: this.onChangeThirdPartyInfo, - disabled: false, - }; - case "delete": - return { - key: option, - label: isThirdPartyFolder ? t("DeleteThirdParty") : t("Delete"), - icon: "/static/images/catalog.trash.react.svg", - onClick: this.onClickDelete, - disabled: false, - }; - case "remove-from-favorites": - return { - key: option, - label: t("RemoveFromFavorites"), - icon: "images/favorites.react.svg", - onClick: this.onClickFavorite, - disabled: false, - "data-action": "remove", - action: "remove", - }; - default: - break; - } - - return undefined; - }); - }; - render() { const { item, @@ -518,14 +134,7 @@ export default function withFileActions(WrappedFileItem) { dragging, isFolder, } = this.props; - const { - fileExst, - access, - contentLength, - id, - shared, - contextOptions, - } = item; + const { fileExst, access, contentLength, id, shared } = item; const isEdit = !!actionType && actionId === id && fileExst === actionExtension; @@ -550,13 +159,6 @@ export default function withFileActions(WrappedFileItem) { ? null : this.getSharedButton(shared); - const contextOptionsProps = - !isEdit && contextOptions && contextOptions.length > 0 - ? { - contextOptions: this.getFilesContextOptions(), - } - : {}; - const checkedProps = isEdit || id <= 0 ? {} : { checked }; const element = this.getItemIcon(isEdit || id <= 0); @@ -574,7 +176,6 @@ export default function withFileActions(WrappedFileItem) { displayShareButton={displayShareButton} isPrivacy={isPrivacy} sharedButton={sharedButton} - contextOptionsProps={contextOptionsProps} checkedProps={checkedProps} element={element} dragging={dragging} @@ -593,36 +194,11 @@ export default function withFileActions(WrappedFileItem) { selectedFolderStore, filesStore, uploadDataStore, - auth, - mediaViewerDataStore, - settingsStore, - versionHistoryStore, }, { item, t, history } ) => { - const { - selectRowAction, - onSelectItem, - openLocationAction, - finalizeVersionAction, - setFavoriteAction, - lockFileAction, - downloadAction, - duplicateAction, - setThirdpartyInfo, - deleteFileAction, - deleteFolderAction, - } = filesActionsStore; - const { - setSharingPanelVisible, - setChangeOwnerPanelVisible, - setMoveToPanelVisible, - setCopyPanelVisible, - setDownloadDialogVisible, - setRemoveItem, - setDeleteThirdPartyDialogVisible, - setDeleteDialogVisible, - } = dialogsStore; + const { selectRowAction, onSelectItem } = filesActionsStore; + const { setSharingPanelVisible } = dialogsStore; const { isPrivacyFolder, isRecycleBinFolder } = treeFoldersStore; const { id: selectedFolderId, isRootFolder } = selectedFolderStore; const { @@ -631,17 +207,12 @@ export default function withFileActions(WrappedFileItem) { selection, setTooltipPosition, setStartDrag, - openDocEditor, fileActionStore, canShare, isFileSelected, } = filesStore; - const { setAction } = fileActionStore; const { startUpload } = uploadDataStore; - const { type, extension, id } = filesStore.fileActionStore; - const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore; - const { isTabletView } = auth.settingsStore; - const { setMediaViewerData } = mediaViewerDataStore; + const { type, extension, id } = fileActionStore; const selectedItem = selection.find( (x) => x.id === item.id && x.fileExst === item.fileExst @@ -656,8 +227,6 @@ export default function withFileActions(WrappedFileItem) { ? false : true; - const isThirdPartyFolder = item.providerKey && isRootFolder; - return { t, item, @@ -674,36 +243,11 @@ export default function withFileActions(WrappedFileItem) { setStartDrag, history, isFolder, - openLocationAction, - setChangeOwnerPanelVisible, - setMoveToPanelVisible, - setCopyPanelVisible, - isTabletView, - fetchFileVersions, - setIsVerHistoryPanel, - homepage: config.homepage, - finalizeVersionAction, - setFavoriteAction, - lockFileAction, - openDocEditor, - setDownloadDialogVisible, - downloadAction, - duplicateAction, - setAction, - setThirdpartyInfo, - setMediaViewerData, - isRootFolder, - setRemoveItem, - setDeleteThirdPartyDialogVisible, - confirmDelete: settingsStore.confirmDelete, - setDeleteDialogVisible, - deleteFileAction, - deleteFolderAction, - isThirdPartyFolder, + isRootFolder, //?? canShare, actionType: type, actionExtension: extension, - actionId: fileActionStore.id, + actionId: id, checked: isFileSelected(item.id, item.parentId), }; } From 02f16eb2e14e31e30e24ac1b305c6518710ec5a7 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Fri, 23 Apr 2021 16:21:09 +0300 Subject: [PATCH 09/19] Web: Files: refactoring: moved onFilesClick to withFileActions HOC --- .../Section/Body/FilesRow/FilesRowContent.js | 5 +- .../Section/Body/FilesRow/SimpleFilesRow.js | 7 +- .../pages/Home/Section/Body/hoc/withBadges.js | 2 +- .../{withContentActions.js => withContent.js} | 89 ++----------------- .../Home/Section/Body/hoc/withFileActions.js | 88 +++++++++++++++++- 5 files changed, 101 insertions(+), 90 deletions(-) rename products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/{withContentActions.js => withContent.js} (82%) diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index 67c40e3859..a4a53e9216 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -8,8 +8,7 @@ import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import RowContent from "@appserver/components/row-content"; -import withContentActions from "../hoc/withContentActions"; -import Badges from "../sub-components/Badges"; +import withContent from "../hoc/withContent"; import withBadges from "../hoc/withBadges"; const sideColor = "#A3A9AE"; @@ -161,5 +160,5 @@ const FilesRowContent = ({ }; export default withRouter( - withTranslation("Home")(withContentActions(withBadges(FilesRowContent))) + withTranslation("Home")(withContent(withBadges(FilesRowContent))) ); diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js index 073eae46d2..b79c9edbcf 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js @@ -64,6 +64,7 @@ const SimpleFilesRow = createSelectable((props) => { contextOptionsProps, checkedProps, element, + onFilesClick, } = props; return ( @@ -90,7 +91,11 @@ const SimpleFilesRow = createSelectable((props) => { {...contextOptionsProps} contextButtonSpacerWidth={displayShareButton} > - + diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js index e36f80a474..d296132d81 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js @@ -162,7 +162,7 @@ export default function withBadges(WrappedComponent) { canWebEdit, isTrashFolder, canConvert, - onFilesClick, // from withContentAction HOC + onFilesClick, // from withFileAction HOC } = this.props; const { fileStatus, access } = item; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js similarity index 82% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js rename to products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js index 6748f1eb58..20108d844d 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContentActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js @@ -69,54 +69,6 @@ export default function withContentActions(WrappedContent) { editCompleteAction(id, item, isCancel); }; - onFilesClick = () => { - const { - filter, - parentFolder, - setIsLoading, - fetchFiles, - isImage, - isSound, - isVideo, - canWebEdit, - item, - isTrashFolder, - openDocEditor, - expandedKeys, - addExpandedKeys, - setMediaViewerData, - } = this.props; - const { id, fileExst, viewUrl, providerKey, contentLength } = item; - - if (isTrashFolder) return; - - if (!fileExst && !contentLength) { - setIsLoading(true); - - if (!expandedKeys.includes(parentFolder + "")) { - addExpandedKeys(parentFolder + ""); - } - - fetchFiles(id, filter) - .catch((err) => { - toastr.error(err); - setIsLoading(false); - }) - .finally(() => setIsLoading(false)); - } else { - if (canWebEdit) { - return openDocEditor(id, providerKey); - } - - if (isImage || isSound || isVideo) { - setMediaViewerData({ visible: true, id }); - return; - } - - return window.open(viewUrl, "_blank"); - } - }; - updateItem = () => { const { updateFile, @@ -292,6 +244,7 @@ export default function withContentActions(WrappedContent) { viewer, t, isTrashFolder, + onFilesClick, } = this.props; const { id, fileExst, updated, createdBy, access, fileStatus } = item; @@ -312,7 +265,7 @@ export default function withContentActions(WrappedContent) { const linkStyles = isTrashFolder //|| window.innerWidth <= 1024 ? { noHover: true } - : { onClick: this.onFilesClick }; + : { onClick: onFilesClick }; const newItems = item.new || fileStatus === 2; const showNew = !!newItems; @@ -345,22 +298,12 @@ export default function withContentActions(WrappedContent) { return inject( ( - { - filesActionsStore, - filesStore, - selectedFolderStore, - formatsStore, - treeFoldersStore, - mediaViewerDataStore, - auth, - }, - { item, t, history } + { filesActionsStore, filesStore, treeFoldersStore, auth }, + { t, history } ) => { const { editCompleteAction } = filesActionsStore; const { - filter, setIsLoading, - fetchFiles, openDocEditor, updateFile, renameFolder, @@ -368,18 +311,12 @@ export default function withContentActions(WrappedContent) { createFolder, isLoading, } = filesStore; - const { - iconFormatsStore, - mediaViewersFormatsStore, - docserviceStore, - } = formatsStore; const { isRecycleBinFolder, - expandedKeys, - addExpandedKeys, + isPrivacyFolder, } = treeFoldersStore; - const { setMediaViewerData } = mediaViewerDataStore; + const { type: fileActionType, extension: fileActionExt, @@ -388,26 +325,12 @@ export default function withContentActions(WrappedContent) { const { replaceFileStream, setEncryptionAccess } = auth; const { culture, isDesktopClient } = auth.settingsStore; - const isImage = iconFormatsStore.isImage(item.fileExst); - const isSound = iconFormatsStore.isSound(item.fileExst); - const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); - const canWebEdit = docserviceStore.canWebEdit(item.fileExst); return { t, editCompleteAction, - filter, - parentFolder: selectedFolderStore.parentId, setIsLoading, - fetchFiles, - isImage, - isSound, - isVideo, - canWebEdit, isTrashFolder: isRecycleBinFolder, openDocEditor, - expandedKeys, - addExpandedKeys, - setMediaViewerData, updateFile, renameFolder, fileActionId, diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js index 134742175a..c2a1240a08 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js @@ -119,6 +119,54 @@ export default function withFileActions(WrappedFileItem) { setStartDrag(true); }; + onFilesClick = () => { + const { + filter, + parentFolder, + setIsLoading, + fetchFiles, + isImage, + isSound, + isVideo, + canWebEdit, + item, + isTrashFolder, + openDocEditor, + expandedKeys, + addExpandedKeys, + setMediaViewerData, + } = this.props; + const { id, fileExst, viewUrl, providerKey, contentLength } = item; + + if (isTrashFolder) return; + + if (!fileExst && !contentLength) { + setIsLoading(true); + + if (!expandedKeys.includes(parentFolder + "")) { + addExpandedKeys(parentFolder + ""); + } + + fetchFiles(id, filter) + .catch((err) => { + toastr.error(err); + setIsLoading(false); + }) + .finally(() => setIsLoading(false)); + } else { + if (canWebEdit) { + return openDocEditor(id, providerKey); + } + + if (isImage || isSound || isVideo) { + setMediaViewerData({ visible: true, id }); + return; + } + + return window.open(viewUrl, "_blank"); + } + }; + render() { const { item, @@ -169,6 +217,7 @@ export default function withFileActions(WrappedFileItem) { rowContextClick={this.rowContextClick} onDrop={this.onDrop} onMouseDown={this.onMouseDown} + onFilesClick={this.onFilesClick} getClassName={this.getClassName} className={className} isDragging={isDragging} @@ -194,12 +243,19 @@ export default function withFileActions(WrappedFileItem) { selectedFolderStore, filesStore, uploadDataStore, + formatsStore, + mediaViewerDataStore, }, { item, t, history } ) => { const { selectRowAction, onSelectItem } = filesActionsStore; const { setSharingPanelVisible } = dialogsStore; - const { isPrivacyFolder, isRecycleBinFolder } = treeFoldersStore; + const { + isPrivacyFolder, + isRecycleBinFolder, + expandedKeys, + addExpandedKeys, + } = treeFoldersStore; const { id: selectedFolderId, isRootFolder } = selectedFolderStore; const { dragging, @@ -210,9 +266,19 @@ export default function withFileActions(WrappedFileItem) { fileActionStore, canShare, isFileSelected, + filter, + setIsLoading, + fetchFiles, + openDocEditor, } = filesStore; const { startUpload } = uploadDataStore; const { type, extension, id } = fileActionStore; + const { + iconFormatsStore, + mediaViewersFormatsStore, + docserviceStore, + } = formatsStore; + const { setMediaViewerData } = mediaViewerDataStore; const selectedItem = selection.find( (x) => x.id === item.id && x.fileExst === item.fileExst @@ -227,6 +293,11 @@ export default function withFileActions(WrappedFileItem) { ? false : true; + const isImage = iconFormatsStore.isImage(item.fileExst); + const isSound = iconFormatsStore.isSound(item.fileExst); + const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst); + const canWebEdit = docserviceStore.canWebEdit(item.fileExst); + return { t, item, @@ -243,12 +314,25 @@ export default function withFileActions(WrappedFileItem) { setStartDrag, history, isFolder, - isRootFolder, //?? + isRootFolder, canShare, actionType: type, actionExtension: extension, actionId: id, checked: isFileSelected(item.id, item.parentId), + filter, + parentFolder: selectedFolderStore.parentId, + setIsLoading, + fetchFiles, + isImage, + isSound, + isVideo, + canWebEdit, + isTrashFolder: isRecycleBinFolder, + openDocEditor, + expandedKeys, + addExpandedKeys, + setMediaViewerData, }; } )(observer(WithFileActions)); From d61f4a6984131bd7ccb798e52906ccf629f607d3 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Fri, 23 Apr 2021 16:47:37 +0300 Subject: [PATCH 10/19] Web: Files: refactoring: moved hocs to HOCs folder, Badges, Icons, EditingWrapperComponents, EmptyContainer to components folder --- .../Home/Section/Body/hoc => HOCs}/withBadges.js | 8 +++----- .../Home/Section/Body/hoc => HOCs}/withContent.js | 13 ++++--------- .../Section/Body/hoc => HOCs}/withContextOptions.js | 2 +- .../Section/Body/hoc => HOCs}/withFileActions.js | 2 +- .../Home/Section/Body/hoc => HOCs}/withLoader.js | 0 .../Home/Section/Body/sub-components => }/Badges.js | 0 .../sub-components => }/EditingWrapperComponent.js | 4 ++-- .../Body => }/EmptyContainer/EmptyContainer.js | 0 .../EmptyContainer/EmptyFilterContainer.js | 0 .../EmptyContainer/EmptyFolderContainer.js | 0 .../Body => }/EmptyContainer/RootFolderContainer.js | 0 .../Home/Section/Body => }/EmptyContainer/index.js | 0 .../Body/sub-components/icons.js => Icons.js} | 6 +++--- .../Home/Section/Body/FilesRow/FilesRowContent.js | 4 ++-- .../Home/Section/Body/FilesRow/SimpleFilesRow.js | 4 ++-- .../src/components/pages/Home/Section/Body/index.js | 4 ++-- .../pages/Settings/Section/Body/ConnectedClouds.js | 2 +- 17 files changed, 21 insertions(+), 28 deletions(-) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/hoc => HOCs}/withBadges.js (97%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/hoc => HOCs}/withContent.js (96%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/hoc => HOCs}/withContextOptions.js (99%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/hoc => HOCs}/withFileActions.js (99%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/hoc => HOCs}/withLoader.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body/sub-components => }/Badges.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body/sub-components => }/EditingWrapperComponent.js (95%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body => }/EmptyContainer/EmptyContainer.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body => }/EmptyContainer/EmptyFilterContainer.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body => }/EmptyContainer/EmptyFolderContainer.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body => }/EmptyContainer/RootFolderContainer.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body => }/EmptyContainer/index.js (100%) rename products/ASC.Files/Client/src/components/{pages/Home/Section/Body/sub-components/icons.js => Icons.js} (71%) diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js b/products/ASC.Files/Client/src/HOCs/withBadges.js similarity index 97% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js rename to products/ASC.Files/Client/src/HOCs/withBadges.js index d296132d81..badba784b3 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withBadges.js +++ b/products/ASC.Files/Client/src/HOCs/withBadges.js @@ -12,8 +12,8 @@ import { getFileConversationProgress, } from "@appserver/common/api/files"; -import Badges from "../sub-components/Badges"; -import config from "../../../../../../../package.json"; +import Badges from "../components/Badges"; +import config from "../../package.json"; export default function withBadges(WrappedComponent) { class WithBadges extends React.Component { @@ -219,7 +219,7 @@ export default function withBadges(WrappedComponent) { filesStore, uploadDataStore, }, - { item, history, t } + { item } ) => { const { docserviceStore } = formatsStore; const { isRecycleBinFolder, updateRootBadge } = treeFoldersStore; @@ -242,8 +242,6 @@ export default function withBadges(WrappedComponent) { const canConvert = docserviceStore.canConvert(item.fileExst); return { - history, - t, canWebEdit, canConvert, isTrashFolder: isRecycleBinFolder, diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js b/products/ASC.Files/Client/src/HOCs/withContent.js similarity index 96% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js rename to products/ASC.Files/Client/src/HOCs/withContent.js index 20108d844d..9c5effc052 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContent.js +++ b/products/ASC.Files/Client/src/HOCs/withContent.js @@ -11,9 +11,9 @@ import { } from "@appserver/common/constants"; import { combineUrl } from "@appserver/common/utils"; -import config from "../../../../../../../package.json"; -import EditingWrapperComponent from "../sub-components/EditingWrapperComponent"; -import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers"; +import config from "../../package.json"; +import EditingWrapperComponent from "../components/EditingWrapperComponent"; +import { getTitleWithoutExst } from "../helpers/files-helpers"; export default function withContentActions(WrappedContent) { class WithContentActions extends React.Component { @@ -297,10 +297,7 @@ export default function withContentActions(WrappedContent) { } return inject( - ( - { filesActionsStore, filesStore, treeFoldersStore, auth }, - { t, history } - ) => { + ({ filesActionsStore, filesStore, treeFoldersStore, auth }, {}) => { const { editCompleteAction } = filesActionsStore; const { setIsLoading, @@ -326,7 +323,6 @@ export default function withContentActions(WrappedContent) { const { culture, isDesktopClient } = auth.settingsStore; return { - t, editCompleteAction, setIsLoading, isTrashFolder: isRecycleBinFolder, @@ -346,7 +342,6 @@ export default function withContentActions(WrappedContent) { isLoading, culture, homepage: config.homepage, - history, viewer: auth.userStore.user, }; } diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js b/products/ASC.Files/Client/src/HOCs/withContextOptions.js similarity index 99% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js rename to products/ASC.Files/Client/src/HOCs/withContextOptions.js index 8efed90211..49b80ceb4b 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withContextOptions.js +++ b/products/ASC.Files/Client/src/HOCs/withContextOptions.js @@ -6,7 +6,7 @@ import { combineUrl } from "@appserver/common/utils"; import { FileAction, AppServerConfig } from "@appserver/common/constants"; import toastr from "studio/toastr"; -import config from "../../../../../../../package.json"; +import config from "../../package.json"; export default function withContextOptions(WrappedComponent) { class WithContextOptions extends React.Component { diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js b/products/ASC.Files/Client/src/HOCs/withFileActions.js similarity index 99% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js rename to products/ASC.Files/Client/src/HOCs/withFileActions.js index c2a1240a08..08f5d8f870 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withFileActions.js +++ b/products/ASC.Files/Client/src/HOCs/withFileActions.js @@ -5,7 +5,7 @@ import { ReactSVG } from "react-svg"; import IconButton from "@appserver/components/icon-button"; import Text from "@appserver/components/text"; -import { EncryptedFileIcon } from "../sub-components/Icons"; +import { EncryptedFileIcon } from "../components/Icons"; const svgLoader = () =>
; export default function withFileActions(WrappedFileItem) { diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoader.js b/products/ASC.Files/Client/src/HOCs/withLoader.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/hoc/withLoader.js rename to products/ASC.Files/Client/src/HOCs/withLoader.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js b/products/ASC.Files/Client/src/components/Badges.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/Badges.js rename to products/ASC.Files/Client/src/components/Badges.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js b/products/ASC.Files/Client/src/components/EditingWrapperComponent.js similarity index 95% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js rename to products/ASC.Files/Client/src/components/EditingWrapperComponent.js index f9e5334d29..6ac5d79df7 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/EditingWrapperComponent.js +++ b/products/ASC.Files/Client/src/components/EditingWrapperComponent.js @@ -4,8 +4,8 @@ import Button from "@appserver/components/button"; import TextInput from "@appserver/components/text-input"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; -import CheckIcon from "../../../../../../../public/images/check.react.svg"; -import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg"; +import CheckIcon from "../../public/images/check.react.svg"; +import CrossIcon from "../../../../../public/images/cross.react.svg"; const StyledCheckIcon = styled(CheckIcon)` ${commonIconsStyles} diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyContainer.js b/products/ASC.Files/Client/src/components/EmptyContainer/EmptyContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyContainer.js rename to products/ASC.Files/Client/src/components/EmptyContainer/EmptyContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyFilterContainer.js b/products/ASC.Files/Client/src/components/EmptyContainer/EmptyFilterContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyFilterContainer.js rename to products/ASC.Files/Client/src/components/EmptyContainer/EmptyFilterContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyFolderContainer.js b/products/ASC.Files/Client/src/components/EmptyContainer/EmptyFolderContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/EmptyFolderContainer.js rename to products/ASC.Files/Client/src/components/EmptyContainer/EmptyFolderContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/RootFolderContainer.js b/products/ASC.Files/Client/src/components/EmptyContainer/RootFolderContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/RootFolderContainer.js rename to products/ASC.Files/Client/src/components/EmptyContainer/RootFolderContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/index.js b/products/ASC.Files/Client/src/components/EmptyContainer/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/EmptyContainer/index.js rename to products/ASC.Files/Client/src/components/EmptyContainer/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js b/products/ASC.Files/Client/src/components/Icons.js similarity index 71% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js rename to products/ASC.Files/Client/src/components/Icons.js index d573902375..3e9538e4bf 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/sub-components/icons.js +++ b/products/ASC.Files/Client/src/components/Icons.js @@ -2,9 +2,9 @@ import styled from "styled-components"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; -import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg"; -import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg"; -import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg"; +import FavoriteIcon from "../../public/images/favorite.react.svg"; +import FileActionsConvertEditDocIcon from "../../public/images/file.actions.convert.edit.doc.react.svg"; +import FileActionsLockedIcon from "../../public/images/file.actions.locked.react.svg"; export const EncryptedFileIcon = styled.div` background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js index a4a53e9216..021ff1e2e4 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js @@ -8,8 +8,8 @@ import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import RowContent from "@appserver/components/row-content"; -import withContent from "../hoc/withContent"; -import withBadges from "../hoc/withBadges"; +import withContent from "../../../../../../HOCs/withContent"; +import withBadges from "../../../../../../HOCs/withBadges"; const sideColor = "#A3A9AE"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js index b79c9edbcf..a2b0364122 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js @@ -7,8 +7,8 @@ import FilesRowContent from "./FilesRowContent"; import { withRouter } from "react-router-dom"; import { createSelectable } from "react-selectable-fast"; -import withFileActions from "../hoc/withFileActions"; -import withContextOptions from "../hoc/withContextOptions"; +import withFileActions from "../../../../../../HOCs/withFileActions"; +import withContextOptions from "../../../../../../HOCs/withContextOptions"; const StyledSimpleFilesRow = styled(Row)` margin-top: -2px; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js index d114d5ba90..0e2a5cd302 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js +++ b/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js @@ -5,9 +5,9 @@ import { isMobile } from "react-device-detect"; import { observer, inject } from "mobx-react"; import FilesRowContainer from "./FilesRow/FilesRowContainer"; import FilesTileContainer from "./FilesTile/FilesTileContainer"; -import EmptyContainer from "./EmptyContainer"; +import EmptyContainer from "../../../../EmptyContainer"; -import withLoader from "./hoc/withLoader"; +import withLoader from "../../../../../HOCs/withLoader"; let currentDroppable = null; diff --git a/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js b/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js index 11697c2967..7d8bcb5ee8 100644 --- a/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js +++ b/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js @@ -7,7 +7,7 @@ import Box from "@appserver/components/box"; import Row from "@appserver/components/row"; import RowContainer from "@appserver/components/row-container"; import { withTranslation } from "react-i18next"; -import EmptyFolderContainer from "../../../Home/Section/Body/EmptyContainer/EmptyContainer"; +import EmptyFolderContainer from "../../../../EmptyContainer/EmptyContainer"; import BoxIcon from "../../../../../../public/images/icon_box.react.svg"; import DropBoxIcon from "../../../../../../public/images/icon_dropbox.react.svg"; import GoogleDriveIcon from "../../../../../../public/images/icon_google_drive.react.svg"; From a3408860c3759230beb21f1a9ed476f02115d5a6 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Fri, 23 Apr 2021 17:17:11 +0300 Subject: [PATCH 11/19] Web: Files: refactoring: FilesRow, FilesTile renamed to RowsView, TilesView, pages moved to /src/ --- products/ASC.Files/Client/src/Files.jsx | 6 ++--- .../panels/VersionHistoryPanel/index.js | 2 +- .../pages/Home/MediaViewer/index.js | 0 .../Body/RowsView}/FilesRowContainer.js | 0 .../Section/Body/RowsView}/FilesRowContent.js | 4 ++-- .../Section/Body/RowsView}/SimpleFilesRow.js | 4 ++-- .../Section/Body/TilesView}/BadgesFileTile.js | 0 .../Home/Section/Body/TilesView}/FileTile.js | 0 .../Body/TilesView}/FilesTileContainer.js | 0 .../Body/TilesView}/FilesTileContent.js | 0 .../Body/TilesView}/sub-components/Tile.js | 0 .../sub-components/TileContainer.js | 0 .../TilesView}/sub-components/TileContent.js | 0 .../pages/Home/Section/Body/index.js | 8 +++---- .../pages/Home/Section/Filter/index.js | 0 .../pages/Home/Section/Header/index.js | 0 .../pages/Home/Section/Paging/index.js | 0 .../pages/Home/Section/index.js | 0 .../src/{components => }/pages/Home/index.js | 8 +++---- .../Settings/Section/Body/ConnectedClouds.js | 22 +++++++++---------- .../pages/Settings/Section/Body/index.js | 0 .../pages/Settings/Section/Header/index.js | 0 .../pages/Settings/Section/index.js | 0 .../{components => }/pages/Settings/index.js | 4 ++-- .../Section/Body/StyledVersionRow.js | 0 .../Section/Body/VersionBadge.js | 0 .../VersionHistory/Section/Body/VersionRow.js | 2 +- .../VersionHistory/Section/Body/index.js | 0 .../VersionHistory/Section/Header/index.js | 0 .../pages/VersionHistory/Section/index.js | 0 .../pages/VersionHistory/index.js | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) rename products/ASC.Files/Client/src/{components => }/pages/Home/MediaViewer/index.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesRow => pages/Home/Section/Body/RowsView}/FilesRowContainer.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesRow => pages/Home/Section/Body/RowsView}/FilesRowContent.js (96%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesRow => pages/Home/Section/Body/RowsView}/SimpleFilesRow.js (94%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/BadgesFileTile.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/FileTile.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/FilesTileContainer.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/FilesTileContent.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/sub-components/Tile.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/sub-components/TileContainer.js (100%) rename products/ASC.Files/Client/src/{components/pages/Home/Section/Body/FilesTile => pages/Home/Section/Body/TilesView}/sub-components/TileContent.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Home/Section/Body/index.js (95%) rename products/ASC.Files/Client/src/{components => }/pages/Home/Section/Filter/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Home/Section/Header/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Home/Section/Paging/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Home/Section/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Home/index.js (98%) rename products/ASC.Files/Client/src/{components => }/pages/Settings/Section/Body/ConnectedClouds.js (90%) rename products/ASC.Files/Client/src/{components => }/pages/Settings/Section/Body/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Settings/Section/Header/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Settings/Section/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/Settings/index.js (96%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/Body/StyledVersionRow.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/Body/VersionBadge.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/Body/VersionRow.js (98%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/Body/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/Header/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/Section/index.js (100%) rename products/ASC.Files/Client/src/{components => }/pages/VersionHistory/index.js (98%) diff --git a/products/ASC.Files/Client/src/Files.jsx b/products/ASC.Files/Client/src/Files.jsx index 06376c70a6..82b3c9db14 100644 --- a/products/ASC.Files/Client/src/Files.jsx +++ b/products/ASC.Files/Client/src/Files.jsx @@ -12,9 +12,9 @@ import "./custom.scss"; import i18n from "./i18n"; import { I18nextProvider } from "react-i18next"; import { regDesktop } from "@appserver/common/desktop"; -import Home from "./components/pages/Home"; -import Settings from "./components/pages/Settings"; -import VersionHistory from "./components/pages/VersionHistory"; +import Home from "./pages/Home"; +import Settings from "./pages/Settings"; +import VersionHistory from "./pages/VersionHistory"; import ErrorBoundary from "@appserver/common/components/ErrorBoundary"; import Panels from "./components/FilesPanels"; import { AppServerConfig } from "@appserver/common/constants"; diff --git a/products/ASC.Files/Client/src/components/panels/VersionHistoryPanel/index.js b/products/ASC.Files/Client/src/components/panels/VersionHistoryPanel/index.js index 01355c8f2a..250dd4d13f 100644 --- a/products/ASC.Files/Client/src/components/panels/VersionHistoryPanel/index.js +++ b/products/ASC.Files/Client/src/components/panels/VersionHistoryPanel/index.js @@ -12,7 +12,7 @@ import { StyledHeaderContent, StyledBody, } from "../StyledPanels"; -import { SectionBodyContent } from "../../pages/VersionHistory/Section/"; +import { SectionBodyContent } from "../../../pages/VersionHistory/Section/"; import { inject, observer } from "mobx-react"; import config from "../../../../package.json"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/MediaViewer/index.js b/products/ASC.Files/Client/src/pages/Home/MediaViewer/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/MediaViewer/index.js rename to products/ASC.Files/Client/src/pages/Home/MediaViewer/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/FilesRowContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContainer.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/FilesRowContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/FilesRowContent.js similarity index 96% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/FilesRowContent.js index 021ff1e2e4..84e2782144 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/FilesRowContent.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/FilesRowContent.js @@ -8,8 +8,8 @@ import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import RowContent from "@appserver/components/row-content"; -import withContent from "../../../../../../HOCs/withContent"; -import withBadges from "../../../../../../HOCs/withBadges"; +import withContent from "../../../../../HOCs/withContent"; +import withBadges from "../../../../../HOCs/withBadges"; const sideColor = "#A3A9AE"; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/SimpleFilesRow.js similarity index 94% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/SimpleFilesRow.js index a2b0364122..7c9fbcbb3d 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Body/RowsView/SimpleFilesRow.js @@ -7,8 +7,8 @@ import FilesRowContent from "./FilesRowContent"; import { withRouter } from "react-router-dom"; import { createSelectable } from "react-selectable-fast"; -import withFileActions from "../../../../../../HOCs/withFileActions"; -import withContextOptions from "../../../../../../HOCs/withContextOptions"; +import withFileActions from "../../../../../HOCs/withFileActions"; +import withContextOptions from "../../../../../HOCs/withContextOptions"; const StyledSimpleFilesRow = styled(Row)` margin-top: -2px; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/BadgesFileTile.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/BadgesFileTile.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/BadgesFileTile.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/BadgesFileTile.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FileTile.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FileTile.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FileTile.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContainer.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContainer.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/FilesTileContent.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/Tile.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/Tile.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/Tile.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/Tile.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContainer.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/TileContainer.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContainer.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/TileContainer.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContent.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/TileContent.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTile/sub-components/TileContent.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/sub-components/TileContent.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js similarity index 95% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js rename to products/ASC.Files/Client/src/pages/Home/Section/Body/index.js index 0e2a5cd302..282eeafba5 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/Section/Body/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Body/index.js @@ -3,11 +3,11 @@ import { withRouter } from "react-router"; import { withTranslation } from "react-i18next"; import { isMobile } from "react-device-detect"; import { observer, inject } from "mobx-react"; -import FilesRowContainer from "./FilesRow/FilesRowContainer"; -import FilesTileContainer from "./FilesTile/FilesTileContainer"; -import EmptyContainer from "../../../../EmptyContainer"; +import FilesRowContainer from "./RowsView/FilesRowContainer"; +import FilesTileContainer from "./TilesView/FilesTileContainer"; +import EmptyContainer from "../../../../components/EmptyContainer"; -import withLoader from "../../../../../HOCs/withLoader"; +import withLoader from "../../../../HOCs/withLoader"; let currentDroppable = null; diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Filter/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Filter/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Filter/index.js rename to products/ASC.Files/Client/src/pages/Home/Section/Filter/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Header/index.js rename to products/ASC.Files/Client/src/pages/Home/Section/Header/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/Paging/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Paging/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/Paging/index.js rename to products/ASC.Files/Client/src/pages/Home/Section/Paging/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/Section/index.js b/products/ASC.Files/Client/src/pages/Home/Section/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Home/Section/index.js rename to products/ASC.Files/Client/src/pages/Home/Section/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Home/index.js b/products/ASC.Files/Client/src/pages/Home/index.js similarity index 98% rename from products/ASC.Files/Client/src/components/pages/Home/index.js rename to products/ASC.Files/Client/src/pages/Home/index.js index e5fb22e8d3..4683c599c0 100644 --- a/products/ASC.Files/Client/src/components/pages/Home/index.js +++ b/products/ASC.Files/Client/src/pages/Home/index.js @@ -14,7 +14,7 @@ import { ArticleBodyContent, ArticleHeaderContent, ArticleMainButtonContent, -} from "../../Article"; +} from "../../components/Article"; import { SectionBodyContent, SectionFilterContent, @@ -22,11 +22,11 @@ import { SectionPagingContent, } from "./Section"; -import { ConvertDialog } from "../../dialogs"; +import { ConvertDialog } from "../../components/dialogs"; import MediaViewer from "./MediaViewer"; -import DragTooltip from "../../DragTooltip"; +import DragTooltip from "../../components/DragTooltip"; import { observer, inject } from "mobx-react"; -import config from "../../../../package.json"; +import config from "../../../package.json"; class PureHome extends React.Component { componentDidMount() { diff --git a/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js b/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js similarity index 90% rename from products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js rename to products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js index 7d8bcb5ee8..f2c4bb698f 100644 --- a/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/ConnectedClouds.js +++ b/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js @@ -7,17 +7,17 @@ import Box from "@appserver/components/box"; import Row from "@appserver/components/row"; import RowContainer from "@appserver/components/row-container"; import { withTranslation } from "react-i18next"; -import EmptyFolderContainer from "../../../../EmptyContainer/EmptyContainer"; -import BoxIcon from "../../../../../../public/images/icon_box.react.svg"; -import DropBoxIcon from "../../../../../../public/images/icon_dropbox.react.svg"; -import GoogleDriveIcon from "../../../../../../public/images/icon_google_drive.react.svg"; -import KDriveIcon from "../../../../../../public/images/icon_kdrive.react.svg"; -import NextCloudIcon from "../../../../../../public/images/icon_nextcloud.react.svg"; -import OneDriveIcon from "../../../../../../public/images/icon_onedrive.react.svg"; -import OwnCloudIcon from "../../../../../../public/images/icon_owncloud.react.svg"; -import SharePointIcon from "../../../../../../public/images/icon_sharepoint.react.svg"; -import WebDavIcon from "../../../../../../public/images/icon_webdav.react.svg"; -import YandexDiskIcon from "../../../../../../public/images/icon_yandex_disk.react.svg"; +import EmptyFolderContainer from "../../../../components/EmptyContainer/EmptyContainer"; +import BoxIcon from "../../../../../public/images/icon_box.react.svg"; +import DropBoxIcon from "../../../../../public/images/icon_dropbox.react.svg"; +import GoogleDriveIcon from "../../../../../public/images/icon_google_drive.react.svg"; +import KDriveIcon from "../../../../../public/images/icon_kdrive.react.svg"; +import NextCloudIcon from "../../../../../public/images/icon_nextcloud.react.svg"; +import OneDriveIcon from "../../../../../public/images/icon_onedrive.react.svg"; +import OwnCloudIcon from "../../../../../public/images/icon_owncloud.react.svg"; +import SharePointIcon from "../../../../../public/images/icon_sharepoint.react.svg"; +import WebDavIcon from "../../../../../public/images/icon_webdav.react.svg"; +import YandexDiskIcon from "../../../../../public/images/icon_yandex_disk.react.svg"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; import { inject, observer } from "mobx-react"; diff --git a/products/ASC.Files/Client/src/components/pages/Settings/Section/Body/index.js b/products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Settings/Section/Body/index.js rename to products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Settings/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Settings/Section/Header/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Settings/Section/Header/index.js rename to products/ASC.Files/Client/src/pages/Settings/Section/Header/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Settings/Section/index.js b/products/ASC.Files/Client/src/pages/Settings/Section/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/Settings/Section/index.js rename to products/ASC.Files/Client/src/pages/Settings/Section/index.js diff --git a/products/ASC.Files/Client/src/components/pages/Settings/index.js b/products/ASC.Files/Client/src/pages/Settings/index.js similarity index 96% rename from products/ASC.Files/Client/src/components/pages/Settings/index.js rename to products/ASC.Files/Client/src/pages/Settings/index.js index b96270289c..21a3f1667f 100644 --- a/products/ASC.Files/Client/src/components/pages/Settings/index.js +++ b/products/ASC.Files/Client/src/pages/Settings/index.js @@ -7,10 +7,10 @@ import { ArticleHeaderContent, ArticleBodyContent, ArticleMainButtonContent, -} from "../../Article"; +} from "../../components/Article"; import { SectionHeaderContent, SectionBodyContent } from "./Section"; import { withTranslation } from "react-i18next"; -import { setDocumentTitle } from "../../../helpers/utils"; +import { setDocumentTitle } from "../../helpers/utils"; import { inject, observer } from "mobx-react"; const PureSettings = ({ diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/StyledVersionRow.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/StyledVersionRow.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/StyledVersionRow.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/StyledVersionRow.js diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/VersionBadge.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/VersionBadge.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/VersionBadge.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/VersionBadge.js diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/VersionRow.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/VersionRow.js similarity index 98% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/VersionRow.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/VersionRow.js index dc967ef89d..d7af931dae 100644 --- a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/VersionRow.js +++ b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/VersionRow.js @@ -10,7 +10,7 @@ import { withTranslation } from "react-i18next"; import { withRouter } from "react-router"; import VersionBadge from "./VersionBadge"; import StyledVersionRow from "./StyledVersionRow"; -import ExternalLinkIcon from "../../../../../../public/images/external.link.react.svg"; +import ExternalLinkIcon from "../../../../../public/images/external.link.react.svg"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; import { inject, observer } from "mobx-react"; diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/index.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Body/index.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/Body/index.js diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Header/index.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/Header/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/Header/index.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/Header/index.js diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/Section/index.js b/products/ASC.Files/Client/src/pages/VersionHistory/Section/index.js similarity index 100% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/Section/index.js rename to products/ASC.Files/Client/src/pages/VersionHistory/Section/index.js diff --git a/products/ASC.Files/Client/src/components/pages/VersionHistory/index.js b/products/ASC.Files/Client/src/pages/VersionHistory/index.js similarity index 98% rename from products/ASC.Files/Client/src/components/pages/VersionHistory/index.js rename to products/ASC.Files/Client/src/pages/VersionHistory/index.js index c7b55ce021..760d71fda8 100644 --- a/products/ASC.Files/Client/src/components/pages/VersionHistory/index.js +++ b/products/ASC.Files/Client/src/pages/VersionHistory/index.js @@ -8,7 +8,7 @@ import { ArticleHeaderContent, ArticleBodyContent, ArticleMainButtonContent, -} from "../../Article"; +} from "../../components/Article"; import { SectionHeaderContent, SectionBodyContent } from "./Section"; //import { setDocumentTitle } from "../../../helpers/utils"; import { inject, observer } from "mobx-react"; From e89c8a6f76df61240dd6fa133b16916468db1cf3 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Sun, 25 Apr 2021 12:58:26 +0300 Subject: [PATCH 12/19] Files: fixed getfolderID --- products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs index 5df944c3d1..c9201245e1 100644 --- a/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs +++ b/products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs @@ -976,10 +976,12 @@ namespace ASC.Files.Core.Data }; FilesDbContext.AddOrUpdate(r => r.BunchObjects, toInsert); + FilesDbContext.SaveChanges(); + tx.Commit(); //Commit changes } - FilesDbContext.SaveChanges(); + return newFolderId; } From a66a454462425fa17074eaa78fe84332cd043ed6 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Sun, 25 Apr 2021 18:06:56 +0300 Subject: [PATCH 13/19] Settings: added tfaapp method --- .../Controllers/SettingsController.cs | 39 +++++++++++++++++-- web/ASC.Web.Api/Models/TfaSettings.cs | 10 +++++ .../PublicResources/Resource.Designer.cs | 18 +++++++++ .../PublicResources/Resource.de.resx | 10 ++++- .../PublicResources/Resource.es.resx | 10 ++++- .../PublicResources/Resource.fr.resx | 10 ++++- .../PublicResources/Resource.it.resx | 10 ++++- .../PublicResources/Resource.resx | 10 ++++- .../PublicResources/Resource.ru.resx | 10 ++++- 9 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 web/ASC.Web.Api/Models/TfaSettings.cs diff --git a/web/ASC.Web.Api/Controllers/SettingsController.cs b/web/ASC.Web.Api/Controllers/SettingsController.cs index 1bef71f74e..b6588383af 100644 --- a/web/ASC.Web.Api/Controllers/SettingsController.cs +++ b/web/ASC.Web.Api/Controllers/SettingsController.cs @@ -1427,21 +1427,54 @@ namespace ASC.Api.Settings return FirstTimeTenantSettings.SaveData(wizardModel); } + [Read("tfaapp")] + public IEnumerable GetTfaSettings() + { + var result = new List(); + + var SmsVisible = StudioSmsNotificationSettingsHelper.IsVisibleSettings(); + var SmsEnable = SmsVisible && SmsProviderManager.Enabled(); + var TfaVisible = TfaAppAuthSettings.IsVisibleSettings; + + if (SmsVisible) + { + result.Add(new TfaSettings + { + Enabled = StudioSmsNotificationSettingsHelper.Enable, + Id = "sms", + Title = Resource.ButtonSmsEnable, + Avaliable = SmsEnable + }); + } + + if (TfaVisible) + { + result.Add(new TfaSettings + { + Enabled = SettingsManager.Load().EnableSetting, + Id = "app", + Title = Resource.ButtonTfaAppEnable, + Avaliable = true + }); + } + + return result; + } [Update("tfaapp")] public bool TfaSettingsFromBody([FromBody]TfaModel model) { - return TfaSettings(model); + return TfaSettingsUpdate(model); } [Update("tfaapp")] [Consumes("application/x-www-form-urlencoded")] public bool TfaSettingsFromForm([FromForm] TfaModel model) { - return TfaSettings(model); + return TfaSettingsUpdate(model); } - private bool TfaSettings(TfaModel model) + private bool TfaSettingsUpdate(TfaModel model) { PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings); diff --git a/web/ASC.Web.Api/Models/TfaSettings.cs b/web/ASC.Web.Api/Models/TfaSettings.cs new file mode 100644 index 0000000000..a5738aea0d --- /dev/null +++ b/web/ASC.Web.Api/Models/TfaSettings.cs @@ -0,0 +1,10 @@ +namespace ASC.Web.Api.Models +{ + public class TfaSettings + { + public string Id { get; set; } + public string Title { get; set; } + public bool Enabled { get; set; } + public bool Avaliable { get; set; } + } +} diff --git a/web/ASC.Web.Core/PublicResources/Resource.Designer.cs b/web/ASC.Web.Core/PublicResources/Resource.Designer.cs index a50bb4c61d..c3cb8c1481 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.Designer.cs +++ b/web/ASC.Web.Core/PublicResources/Resource.Designer.cs @@ -105,6 +105,24 @@ namespace ASC.Web.Core.PublicResources { } } + /// + /// Looks up a localized string similar to By SMS. + /// + public static string ButtonSmsEnable { + get { + return ResourceManager.GetString("ButtonSmsEnable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to By authenticator app. + /// + public static string ButtonTfaAppEnable { + get { + return ResourceManager.GetString("ButtonTfaAppEnable", resourceCulture); + } + } + /// /// Looks up a localized string similar to A link to confirm the operation has been sent to :email (the email address of the portal owner).. /// diff --git a/web/ASC.Web.Core/PublicResources/Resource.de.resx b/web/ASC.Web.Core/PublicResources/Resource.de.resx index a7ce5ef24d..5b51f25a42 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.de.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.de.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Das Feld mit dem Prüfcode darf nicht leer sein @@ -73,6 +73,12 @@ Ihre Nachricht wurde erfolgreich gesendet. Der Portaladministrator wird Sie kontaktieren. + + Per SMS + + + Über die Authentifizierungs-App + Der Link zum Bestätigen der Operation wurde an :email verschickt (die E-Mail-Adresse des Portalbesitzers). diff --git a/web/ASC.Web.Core/PublicResources/Resource.es.resx b/web/ASC.Web.Core/PublicResources/Resource.es.resx index 0af7e35468..6733c1d541 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.es.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.es.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Campo de código de validación no puede estar vacío @@ -73,6 +73,12 @@ Su mensaje fue enviado con éxito. El administrador del portal se pondrá en contacto con usted. + + Por SMS + + + Con ayuda de la aplicación para autenticación + Un enlace para confirmar la operación ha sido enviada al :correo electrónico (la dirección del correo electrónico del propietario del portal). diff --git a/web/ASC.Web.Core/PublicResources/Resource.fr.resx b/web/ASC.Web.Core/PublicResources/Resource.fr.resx index f7b244108b..da2e892699 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.fr.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.fr.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Le champ du code de validation ne peut pas être vide @@ -73,6 +73,12 @@ Votre message a été envoyé avec succès. Vous serez contacté par l'administrateur du portail. + + par SMS + + + Par l'application authentificateur + Un lien pour confirmer l'opération a été envoyé à :e-mail (l'adresse e-mail du propriétaire du portail). diff --git a/web/ASC.Web.Core/PublicResources/Resource.it.resx b/web/ASC.Web.Core/PublicResources/Resource.it.resx index 649248d0d3..c051cfded0 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.it.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.it.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Il campo Valida codice non può essere vuoto @@ -73,6 +73,12 @@ Il tuo messaggio è stato inviato con successo. Sarai contattato dall'amministratore del portale. + + Tramite SMS + + + Con authenticator app + Un collegamento per confermare l'operazione è stato inviato all'indirizzo :email (l'indirizzo email del proprietario del portale). diff --git a/web/ASC.Web.Core/PublicResources/Resource.resx b/web/ASC.Web.Core/PublicResources/Resource.resx index d6a6f2aa69..bf9175aa54 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Validation code field cannot be empty @@ -73,6 +73,12 @@ Your message was successfully sent. You will be contacted by the portal administrator. + + By SMS + + + By authenticator app + A link to confirm the operation has been sent to :email (the email address of the portal owner). diff --git a/web/ASC.Web.Core/PublicResources/Resource.ru.resx b/web/ASC.Web.Core/PublicResources/Resource.ru.resx index 1ddb41e5c2..c7722cb4ee 100644 --- a/web/ASC.Web.Core/PublicResources/Resource.ru.resx +++ b/web/ASC.Web.Core/PublicResources/Resource.ru.resx @@ -53,10 +53,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.4.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Поле кода подтверждения не может быть пустым @@ -73,6 +73,12 @@ Ваше сообщение успешно отправлено. Администратор портала с Вами свяжется. + + С помощью SMS + + + С помощью приложения для аутентификации + Ссылка для подтверждения операции была отправлена на :email (адрес электронной почты владельца портала). From 4b2f1160443f274ef9a4fb8e042bf4fd54283fda Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Sun, 25 Apr 2021 20:41:57 +0300 Subject: [PATCH 14/19] Web: Files: refactoring: fix after merge --- .../ASC.Files/Client/src/HOCs/withContent.js | 25 +++++++++++++++---- .../Client/src/HOCs/withContextOptions.js | 5 ++++ .../Settings/Section/Body/ConnectedClouds.js | 2 +- .../src/pages/Settings/Section/Body/index.js | 2 +- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/products/ASC.Files/Client/src/HOCs/withContent.js b/products/ASC.Files/Client/src/HOCs/withContent.js index 9c5effc052..bc280048f4 100644 --- a/products/ASC.Files/Client/src/HOCs/withContent.js +++ b/products/ASC.Files/Client/src/HOCs/withContent.js @@ -71,6 +71,7 @@ export default function withContentActions(WrappedContent) { updateItem = () => { const { + t, updateFile, renameFolder, item, @@ -95,9 +96,27 @@ export default function withContentActions(WrappedContent) { item.fileExst || item.contentLength ? updateFile(fileActionId, itemTitle) .then(() => this.completeAction(fileActionId)) + .then(() => + toastr.success( + t("FileRenamed", { + oldTitle: item.title, + newTitle: itemTitle + item.fileExst, + }) + ) + ) + .catch((err) => toastr.error(err)) .finally(() => setIsLoading(false)) : renameFolder(fileActionId, itemTitle) .then(() => this.completeAction(fileActionId)) + .then(() => + toastr.success( + t("FolderRenamed", { + folderTitle: item.title, + newFoldedTitle: itemTitle, + }) + ) + ) + .catch((err) => toastr.error(err)) .finally(() => setIsLoading(false)); }; @@ -308,11 +327,7 @@ export default function withContentActions(WrappedContent) { createFolder, isLoading, } = filesStore; - const { - isRecycleBinFolder, - - isPrivacyFolder, - } = treeFoldersStore; + const { isRecycleBinFolder, isPrivacyFolder } = treeFoldersStore; const { type: fileActionType, diff --git a/products/ASC.Files/Client/src/HOCs/withContextOptions.js b/products/ASC.Files/Client/src/HOCs/withContextOptions.js index 49b80ceb4b..8ec66f6c33 100644 --- a/products/ASC.Files/Client/src/HOCs/withContextOptions.js +++ b/products/ASC.Files/Client/src/HOCs/withContextOptions.js @@ -39,8 +39,10 @@ export default function withContextOptions(WrappedComponent) { setIsVerHistoryPanel, history, homepage, + isTrashFolder, } = this.props; const { id } = item; + if (isTrashFolder) return; if (!isTabletView) { fetchFileVersions(id + ""); @@ -427,6 +429,7 @@ export default function withContextOptions(WrappedComponent) { settingsStore, selectedFolderStore, dialogsStore, + treeFoldersStore, }, { item } ) => { @@ -458,6 +461,7 @@ export default function withContextOptions(WrappedComponent) { const { setAction, type, extension, id } = fileActionStore; const { setMediaViewerData } = mediaViewerDataStore; const { isRootFolder } = selectedFolderStore; + const { isRecycleBinFolder } = treeFoldersStore; const isThirdPartyFolder = item.providerKey && isRootFolder; @@ -492,6 +496,7 @@ export default function withContextOptions(WrappedComponent) { actionType: type, actionId: id, actionExtension: extension, + isTrashFolder: isRecycleBinFolder, }; } )(observer(WithContextOptions)); diff --git a/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js b/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js index 21d0d89ea3..f2d61d9a14 100644 --- a/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js +++ b/products/ASC.Files/Client/src/pages/Settings/Section/Body/ConnectedClouds.js @@ -22,7 +22,7 @@ import commonIconsStyles from "@appserver/components/utils/common-icons-style"; import { inject, observer } from "mobx-react"; import combineUrl from "@appserver/common/utils/combineUrl"; import AppServerConfig from "@appserver/common/constants/AppServerConfig"; -import config from "../../../../../../package.json"; +import config from "../../../../../package.json"; import { withRouter } from "react-router"; const StyledBoxIcon = styled(BoxIcon)` diff --git a/products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js b/products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js index 6ee1b38286..9e31b08160 100644 --- a/products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js +++ b/products/ASC.Files/Client/src/pages/Settings/Section/Body/index.js @@ -6,7 +6,7 @@ import Error403 from "studio/Error403"; import Error520 from "studio/Error520"; import ConnectClouds from "./ConnectedClouds"; import { inject, observer } from "mobx-react"; -import { loopTreeFolders } from "../../../../../helpers/files-helpers"; +import { loopTreeFolders } from "../../../../helpers/files-helpers"; const StyledSettings = styled.div` display: grid; From 7c9e35d004cfc0d07804c285cb6a6f63e6f9bc1e Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Mon, 26 Apr 2021 09:45:57 +0300 Subject: [PATCH 15/19] Web: Components: ContextMenuButton: Fixed out of event call for new menu item --- .../context-menu-button/index.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/asc-web-components/context-menu-button/index.js b/packages/asc-web-components/context-menu-button/index.js index ed23be4ffc..5c4c585b89 100644 --- a/packages/asc-web-components/context-menu-button/index.js +++ b/packages/asc-web-components/context-menu-button/index.js @@ -80,8 +80,8 @@ class ContextMenuButton extends React.Component { } } - onIconButtonClick = () => { - if (this.props.isDisabled) { + onIconButtonClick = (e) => { + if (this.props.isDisabled || this.props.isNew) { this.stopAction; return; } @@ -95,7 +95,7 @@ class ContextMenuButton extends React.Component { !this.props.isDisabled && this.state.isOpen && this.props.onClick && - this.props.onClick() + this.props.onClick(e) ); // eslint-disable-line react/prop-types }; @@ -125,12 +125,17 @@ class ContextMenuButton extends React.Component { } callNewMenu = (e) => { - if (this.props.isDisabled) { + if (this.props.isDisabled || !this.props.isNew) { this.stopAction; return; } - this.props.isNew && this.props.onClick(e); + this.setState( + { + data: this.props.getData(), + }, + () => this.props.onClick(e) + ); }; render() { From cad6ee216c0380a52f01f1597f81dd54f702f853 Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Mon, 26 Apr 2021 10:25:45 +0300 Subject: [PATCH 16/19] Web: Components: Badge: Fixed event propagation for Badge component --- packages/asc-web-components/badge/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/asc-web-components/badge/index.js b/packages/asc-web-components/badge/index.js index e5bc04118b..4c9d0162fe 100644 --- a/packages/asc-web-components/badge/index.js +++ b/packages/asc-web-components/badge/index.js @@ -11,7 +11,6 @@ const Badge = (props) => { if (!props.onClick) return; e.preventDefault(); - e.stopPropagation(); props.onClick(e); }; From 8c939c77bb2afdda391c9b3aafb4663461138af7 Mon Sep 17 00:00:00 2001 From: Artem Tarasov Date: Mon, 26 Apr 2021 15:46:26 +0300 Subject: [PATCH 17/19] Web: Files: refactoring: renamed HOCs --- products/ASC.Files/Client/src/HOCs/withContent.js | 6 +++--- products/ASC.Files/Client/src/HOCs/withLoader.js | 6 +++--- .../pages/Home/Section/Body/TilesView/FilesTileContent.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/products/ASC.Files/Client/src/HOCs/withContent.js b/products/ASC.Files/Client/src/HOCs/withContent.js index bc280048f4..f453b200a0 100644 --- a/products/ASC.Files/Client/src/HOCs/withContent.js +++ b/products/ASC.Files/Client/src/HOCs/withContent.js @@ -15,8 +15,8 @@ import config from "../../package.json"; import EditingWrapperComponent from "../components/EditingWrapperComponent"; import { getTitleWithoutExst } from "../helpers/files-helpers"; -export default function withContentActions(WrappedContent) { - class WithContentActions extends React.Component { +export default function withContent(WrappedContent) { + class WithContent extends React.Component { constructor(props) { super(props); let titleWithoutExt = getTitleWithoutExst(props.item); @@ -360,5 +360,5 @@ export default function withContentActions(WrappedContent) { viewer: auth.userStore.user, }; } - )(observer(WithContentActions)); + )(observer(WithContent)); } diff --git a/products/ASC.Files/Client/src/HOCs/withLoader.js b/products/ASC.Files/Client/src/HOCs/withLoader.js index f5b785a503..669617e745 100644 --- a/products/ASC.Files/Client/src/HOCs/withLoader.js +++ b/products/ASC.Files/Client/src/HOCs/withLoader.js @@ -5,8 +5,8 @@ import { isMobile } from "react-device-detect"; import Loaders from "@appserver/common/components/Loaders"; let loadTimeout = null; -export default function withLoadingCheck(WrappedComponent, type) { - const WithLoadingCheck = (props) => { +export default function withLoader(WrappedComponent, type) { + const withLoader = (props) => { const { tReady, firstLoad, isLoaded, isLoading } = props; const [inLoad, setInLoad] = useState(false); @@ -47,5 +47,5 @@ export default function withLoadingCheck(WrappedComponent, type) { isLoaded: auth.isLoaded, isLoading, }; - })(observer(WithLoadingCheck)); + })(observer(withLoader)); } diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js index d8b71ec030..0fc01424cc 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Body/TilesView/FilesTileContent.js @@ -7,7 +7,7 @@ import Link from "@appserver/components/link"; import Text from "@appserver/components/text"; import TileContent from "./TileContent"; -import withContentActions from "../hoc/withContentActions"; +import withContent from "../hoc/withContent"; import Badges from "../sub-components/Badges"; const SimpleFilesTileContent = styled(TileContent)` @@ -149,5 +149,5 @@ const FilesTileContent = ({ }; export default withRouter( - withTranslation("Home")(withContentActions(FilesTileContent)) + withTranslation("Home")(withContent(FilesTileContent)) ); From a96ae77570407a2e76187018c0942b25dc730aa1 Mon Sep 17 00:00:00 2001 From: Alexey Kostenko Date: Mon, 26 Apr 2021 16:41:57 +0300 Subject: [PATCH 18/19] OAuth: Fixed crash on login page --- .../src/pages/Profile/Section/Body/index.js | 27 +++++++++++-------- .../Confirm/sub-components/createUser.js | 18 +++++++++++-- web/ASC.Web.Login/src/Login.jsx | 17 ++++++++++-- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js b/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js index deeb6b2674..9287dd6acb 100644 --- a/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js +++ b/products/ASC.People/Client/src/pages/Profile/Section/Body/index.js @@ -193,6 +193,7 @@ class SectionBodyContent extends React.PureComponent { const providerButtons = providers && providers.map((item) => { + if (!providersData[item.provider]) return; const { icon, label, iconOptions } = providersData[item.provider]; if (!icon || !label) return ; @@ -247,17 +248,21 @@ class SectionBodyContent extends React.PureComponent { return providerButtons; }; + oauthDataExists = () => { + const { providers } = this.props; + + let existProviders = 0; + providers && providers.length > 0; + providers.map((item) => { + if (!providersData[item.provider]) return; + existProviders++; + }); + + return !!existProviders; + }; + render() { - const { - profile, - cultures, - culture, - isAdmin, - viewer, - t, - isSelf, - providers, - } = this.props; + const { profile, cultures, culture, isAdmin, t, isSelf } = this.props; const contacts = profile.contacts && getUserContacts(profile.contacts); const role = getUserRole(profile); @@ -300,7 +305,7 @@ class SectionBodyContent extends React.PureComponent { culture={culture} /> - {isSelf && providers && providers.length > 0 && ( + {isSelf && this.oauthDataExists() && ( diff --git a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/createUser.js b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/createUser.js index 53b92daaa0..b4c8755c1e 100644 --- a/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/createUser.js +++ b/web/ASC.Web.Client/src/components/pages/Confirm/sub-components/createUser.js @@ -195,10 +195,11 @@ class Confirm extends React.PureComponent { const providerButtons = providers && providers.map((item, index) => { + if (!providersData[item.provider]) return; const { icon, label, iconOptions, className } = providersData[ item.provider ]; - if (!icon) return; + if (item.provider === "Facebook") { facebookIndex = index; return; @@ -223,6 +224,19 @@ class Confirm extends React.PureComponent { return providerButtons; }; + oauthDataExists = () => { + const { providers } = this.props; + + let existProviders = 0; + providers && providers.length > 0; + providers.map((item) => { + if (!providersData[item.provider]) return; + existProviders++; + }); + + return !!existProviders; + }; + authCallback = (profile) => { const { t, defaultPage } = this.props; const { FirstName, LastName, EMail, Serialized } = profile; @@ -493,7 +507,7 @@ class Confirm extends React.PureComponent { onClick={this.onSubmit} /> - {providers && providers.length > 0 && ( + {this.oauthDataExists && ( {this.providerButtons()} diff --git a/web/ASC.Web.Login/src/Login.jsx b/web/ASC.Web.Login/src/Login.jsx index e80f2562b6..ae3dfa97e8 100644 --- a/web/ASC.Web.Login/src/Login.jsx +++ b/web/ASC.Web.Login/src/Login.jsx @@ -362,10 +362,12 @@ const Form = (props) => { const providerButtons = providers && providers.map((item, index) => { + if (!providersData[item.provider]) return; + const { icon, label, iconOptions, className } = providersData[ item.provider ]; - if (!icon) return; + if (item.provider === "Facebook") { facebookIndex = index; return; @@ -390,6 +392,17 @@ const Form = (props) => { return providerButtons; }; + const oauthDataExists = () => { + let existProviders = 0; + providers && providers.length > 0; + providers.map((item) => { + if (!providersData[item.provider]) return; + existProviders++; + }); + + return !!existProviders; + }; + //console.log("Login render"); return ( @@ -507,7 +520,7 @@ const Form = (props) => {
)} - {providers && providers.length > 0 && ( + {oauthDataExists() && ( <>
From baafc5f175c656f68c7605c1836636244200ed6e Mon Sep 17 00:00:00 2001 From: Sergey Kirichenko Date: Mon, 26 Apr 2021 19:08:48 +0300 Subject: [PATCH 19/19] Add calendar and mail service in docker (#234) * Add 2 services building feature * Add 2 services for runnig * Del in .env status latest * Add to notify.yml 2 volumes Co-authored-by: Alexey Golubev --- build/install/common/publish-backend.sh | 2 ++ build/install/docker/.env | 4 +++ build/install/docker/Dockerfile-app | 27 ++++++++++++++++--- build/install/docker/appserver.yml | 19 +++++++++++++ build/install/docker/build.yml | 14 ++++++++++ .../nginx/templates/upstream.conf.template | 10 +++++++ build/install/docker/notify.yml | 4 +++ 7 files changed, 76 insertions(+), 4 deletions(-) diff --git a/build/install/common/publish-backend.sh b/build/install/common/publish-backend.sh index 3a0c3b87c4..93a54547d1 100644 --- a/build/install/common/publish-backend.sh +++ b/build/install/common/publish-backend.sh @@ -60,6 +60,8 @@ servers_products_name_backend=(ASC.CRM) servers_products_name_backend+=(ASC.Files) servers_products_name_backend+=(ASC.People) servers_products_name_backend+=(ASC.Projects) +servers_products_name_backend+=(ASC.Calendar) +servers_products_name_backend+=(ASC.Mail) # Publish server backend products for i in ${!servers_products_name_backend[@]}; do diff --git a/build/install/docker/.env b/build/install/docker/.env index 823635a2ee..ddf27d85e8 100644 --- a/build/install/docker/.env +++ b/build/install/docker/.env @@ -47,10 +47,12 @@ # service host # API_SYSTEM_HOST=${CONTAINER_PREFIX}api-system BACKUP_HOST=${CONTAINER_PREFIX}backup + CALENDAR_HOST=${CONTAINER_PREFIX}calendar CRM_HOST=${CONTAINER_PREFIX}crm STORAGE_ENCRYPTION_HOST=${CONTAINER_PREFIX}storage-encryption FILES_HOST=${CONTAINER_PREFIX}files FILES_SERVICES_HOST=${CONTAINER_PREFIX}files-services + MAIL_HOST=${CONTAINER_PREFIX}mail STORAGE_MIGRATION_HOST=${CONTAINER_PREFIX}storage-migration NOTIFY_HOST=${CONTAINER_PREFIX}notify PEOPLE_SERVER_HOST=${CONTAINER_PREFIX}people-server @@ -68,9 +70,11 @@ SERVICE_API_SYSTEM=${API_SYSTEM_HOST}:${SERVICE_PORT} SERVICE_BACKUP=${BACKUP_HOST}:${SERVICE_PORT} SERVICE_CRM=${CRM_HOST}:${SERVICE_PORT} + SERVICE_CALENDAR=${CALENDAR_HOST}:${SERVICE_PORT} SERVICE_STORAGE_ENCRYPTION=${STORAGE_ENCRYPTION_HOST}:${SERVICE_PORT} SERVICE_FILES=${FILES_HOST}:${SERVICE_PORT} SERVICE_FILES_SERVICES=${FILES_SERVICES_HOST}:${SERVICE_PORT} + SERVICE_MAIL=${MAIL_HOST}:${SERVICE_PORT} SERVICE_STORAGE_MIGRATION=${STORAGE_MIGRATION_HOST}:${SERVICE_PORT} SERVICE_NOTIFY=${NOTIFY_HOST}:${SERVICE_PORT} SERVICE_PEOPLE_SERVER=${PEOPLE_SERVER_HOST}:${SERVICE_PORT} diff --git a/build/install/docker/Dockerfile-app b/build/install/docker/Dockerfile-app index dd3d677de8..2ab5d1bdd3 100644 --- a/build/install/docker/Dockerfile-app +++ b/build/install/docker/Dockerfile-app @@ -45,11 +45,8 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \ bash build-frontend.sh -sp ${SRC_PATH} && \ bash build-backend.sh -sp ${SRC_PATH} -ar "--disable-parallel" && \ bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel" - -COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf -COPY config/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf -RUN sed -i 's/Server=.*;Port=/Server=127.0.0.1;Port=/' /app/onlyoffice/config/appsettings.test.json +COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf RUN rm -rf /var/lib/apt/lists/* @@ -107,6 +104,8 @@ COPY --from=base ${SRC_PATH}/web/ASC.Web.Login/dist ${BUILD_PATH}/studio/login COPY --from=base ${SRC_PATH}/products/ASC.People/Client/dist ${BUILD_PATH}/products/ASC.People/client COPY --from=base ${SRC_PATH}/products/ASC.Projects/Client/dist ${BUILD_PATH}/products/ASC.Projects/client COPY --from=base ${SRC_PATH}/web/ASC.Web.Client/dist ${BUILD_PATH}/studio/client +COPY --from=base ${SRC_PATH}/products/ASC.Calendar/Client/dist ${BUILD_PATH}/products/ASC.Calendar/client +COPY --from=base ${SRC_PATH}/products/ASC.Mail/Client/dist ${BUILD_PATH}/products/ASC.Mail/client COPY /config/nginx/templates/upstream.conf.template /etc/nginx/templates/upstream.conf.template @@ -122,6 +121,8 @@ RUN chown nginx:nginx /etc/nginx/* -R && \ sed -i 's/localhost:5020/$service_projects_server/' /etc/nginx/conf.d/onlyoffice.conf && \ sed -i 's/localhost:5000/$service_api/' /etc/nginx/conf.d/onlyoffice.conf && \ sed -i 's/localhost:5003/$service_studio/' /etc/nginx/conf.d/onlyoffice.conf && \ + sed -i 's/localhost:5023/$service_calendar/' /etc/nginx/conf.d/onlyoffice.conf && \ + sed -i 's/localhost:5022/$service_mail/' /etc/nginx/conf.d/onlyoffice.conf && \ sed -i 's/localhost:9999/$service_urlshortener/' /etc/nginx/conf.d/onlyoffice.conf && \ sed -i 's/172.*/$document_server;/' /etc/nginx/conf.d/onlyoffice.conf && \ # configute the image nginx whith less privileged https://hub.docker.com/_/nginx @@ -146,6 +147,15 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.B CMD ["ASC.Data.Backup.dll", "ASC.Data.Backup", "core:products:folder=/var/www/products/", "core:products:subfolder=server"] +## ASC.Calendar ## +FROM builder AS calendar +WORKDIR ${BUILD_PATH}/products/ASC.Calendar/server/ + +COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh . +COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Calendar/server/ . + +CMD ["ASC.Calendar.dll", "ASC.Calendar"] + ## ASC.CRM ## FROM builder AS crm WORKDIR ${BUILD_PATH}/products/ASC.CRM/server/ @@ -182,6 +192,15 @@ COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Files. CMD ["ASC.Files.Service.dll", "ASC.Files.Service", "core:products:folder=/var/www/products/", "core:products:subfolder=server"] +## ASC.Mail ## +FROM builder AS mail +WORKDIR ${BUILD_PATH}/products/ASC.Mail/server/ + +COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh . +COPY --from=base --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Mail/server/ . + +CMD ["ASC.Mail.dll", "ASC.Mail"] + ## ASC.Data.Storage.Migration ## FROM builder AS data_storage_migration WORKDIR ${BUILD_PATH}/services/storage.migration/service/ diff --git a/build/install/docker/appserver.yml b/build/install/docker/appserver.yml index 3eef1db072..4912140010 100644 --- a/build/install/docker/appserver.yml +++ b/build/install/docker/appserver.yml @@ -29,6 +29,9 @@ x-service: - people_data:/var/www/products/ASC.People/server/ - crm_data:/var/www/products/ASC.CRM/server/ - project_data:/var/www/products/ASC.Projects/server/ + - calendar_data:/var/www/products/ASC.Calendar/server/ + - mail_data:/var/www/products/ASC.Mail/server/ + services: onlyoffice-elasticsearch: @@ -95,6 +98,11 @@ services: image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}" container_name: ${BACKUP_HOST} + onlyoffice-calendar: + <<: *x-service-base + image: "${REPO}/${STATUS}appserver-calendar:${SRV_VERSION}" + container_name: ${CALENDAR_HOST} + onlyoffice-crm: <<: *x-service-base image: "${REPO}/${STATUS}appserver-crm:${SRV_VERSION}" @@ -115,6 +123,11 @@ services: image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}" container_name: ${FILES_SERVICES_HOST} + onlyoffice-mail: + <<: *x-service-base + image: "${REPO}/${STATUS}appserver-mail:${SRV_VERSION}" + container_name: ${MAIL_HOST} + onlyoffice-storage-migration: <<: *x-service-base image: "${REPO}/${STATUS}appserver-storage-migration:${SRV_VERSION}" @@ -187,10 +200,12 @@ services: depends_on: - onlyoffice-api-system - onlyoffice-backup + - onlyoffice-calendar - onlyoffice-crm - onlyoffice-storage-encryption - onlyoffice-files - onlyoffice-files-services + - onlyoffice-mail - onlyoffice-storage-migration - onlyoffice-people-server - onlyoffice-projects-server @@ -204,10 +219,12 @@ services: environment: - SERVICE_API_SYSTEM=${SERVICE_API_SYSTEM} - SERVICE_BACKUP=${SERVICE_BACKUP} + - SERVICE_CALENDAR=${SERVICE_CALENDAR} - SERVICE_CRM=${SERVICE_CRM} - SERVICE_STORAGE_ENCRYPTION=${SERVICE_STORAGE_ENCRYPTION} - SERVICE_FILES=${SERVICE_FILES} - SERVICE_FILES_SERVICES=${SERVICE_FILES_SERVICES} + - SERVICE_MAIL=${SERVICE_MAIL} - SERVICE_STORAGE_MIGRATION=${SERVICE_STORAGE_MIGRATION} - SERVICE_NOTIFY=${SERVICE_NOTIFY} - SERVICE_PEOPLE_SERVER=${SERVICE_PEOPLE_SERVER} @@ -240,3 +257,5 @@ volumes: people_data: crm_data: project_data: + calendar_data: + mail_data: diff --git a/build/install/docker/build.yml b/build/install/docker/build.yml index 1e6209d635..9a43b41e51 100644 --- a/build/install/docker/build.yml +++ b/build/install/docker/build.yml @@ -15,6 +15,13 @@ services: target: backup image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}" + onlyoffice-calendar: + build: + context: ./ + dockerfile: "${DOCKERFILE}" + target: calendar + image: "${REPO}/${STATUS}appserver-calendar:${SRV_VERSION}" + onlyoffice-crm: build: context: ./ @@ -43,6 +50,13 @@ services: target: files_services image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}" + onlyoffice-mail: + build: + context: ./ + dockerfile: "${DOCKERFILE}" + target: mail + image: "${REPO}/${STATUS}appserver-mail:${SRV_VERSION}" + onlyoffice-storage-migration: build: context: ./ diff --git a/build/install/docker/config/nginx/templates/upstream.conf.template b/build/install/docker/config/nginx/templates/upstream.conf.template index 675432e66c..a14517cd5a 100644 --- a/build/install/docker/config/nginx/templates/upstream.conf.template +++ b/build/install/docker/config/nginx/templates/upstream.conf.template @@ -10,6 +10,11 @@ map $SERVICE_BACKUP $service_backup { $SERVICE_BACKUP $SERVICE_BACKUP; } +map $SERVICE_CALENDAR $service_calendar { + volatile; + $SERVICE_CALENDAR $SERVICE_CALENDAR; +} + map $SERVICE_CRM $service_crm { volatile; $SERVICE_CRM $SERVICE_CRM; @@ -30,6 +35,11 @@ map $SERVICE_FILES_SERVICES $service_files_services { $SERVICE_FILES_SERVICES $SERVICE_FILES_SERVICES; } +map $SERVICE_MAIL $service_mail { + volatile; + $SERVICE_MAIL $SERVICE_MAIL; +} + map $SERVICE_STORAGE_MIGRATION $service_storage_migration { volatile; $SERVICE_STORAGE_MIGRATION $SERVICE_STORAGE_MIGRATION; diff --git a/build/install/docker/notify.yml b/build/install/docker/notify.yml index 0d813e085a..7a437cf4d3 100644 --- a/build/install/docker/notify.yml +++ b/build/install/docker/notify.yml @@ -29,6 +29,8 @@ x-service: - people_data:/var/www/products/ASC.People/server/ - crm_data:/var/www/products/ASC.CRM/server/ - project_data:/var/www/products/ASC.Projects/server/ + - calendar_data:/var/www/products/ASC.Calendar/server/ + - mail_data:/var/www/products/ASC.Mail/server/ services: onlyoffice-notify: @@ -47,3 +49,5 @@ volumes: people_data: crm_data: project_data: + calendar_data: + mail_data: