From e144a27c077f07875f1cc4d9c826a4fc6df17e52 Mon Sep 17 00:00:00 2001 From: TimofeyBoyko Date: Fri, 15 Oct 2021 15:07:15 +0800 Subject: [PATCH] Web:Common: added navigation components --- .../components/Navigation/Navigation.js | 155 ++++ .../components/Navigation/StyledNavigation.js | 83 ++ .../components/Navigation/index.js | 1 + .../Navigation/sub-components/arrow-btn.js | 21 + .../Navigation/sub-components/control-btn.js | 63 ++ .../Navigation/sub-components/drop-box.js | 236 ++++++ .../Navigation/sub-components/item.js | 86 +++ .../Navigation/sub-components/text.js | 84 ++ .../Navigation/svg/default.react.svg | 4 + .../Navigation/svg/default.tablet.react.svg | 4 + .../components/Navigation/svg/root.react.svg | 4 + .../Navigation/svg/root.tablet.react.svg | 4 + .../sub-components/section-header.js | 37 +- .../PageLayout/sub-components/section.js | 28 +- .../src/pages/Home/Section/Header/index.js | 580 +++++++------- .../ASC.Files/Client/src/pages/Home/index.js | 129 ++-- .../ASC.Files/Client/src/store/FilesStore.js | 720 +++++++----------- .../Client/src/store/SelectedFolderStore.js | 4 +- 18 files changed, 1415 insertions(+), 828 deletions(-) create mode 100644 packages/asc-web-common/components/Navigation/Navigation.js create mode 100644 packages/asc-web-common/components/Navigation/StyledNavigation.js create mode 100644 packages/asc-web-common/components/Navigation/index.js create mode 100644 packages/asc-web-common/components/Navigation/sub-components/arrow-btn.js create mode 100644 packages/asc-web-common/components/Navigation/sub-components/control-btn.js create mode 100644 packages/asc-web-common/components/Navigation/sub-components/drop-box.js create mode 100644 packages/asc-web-common/components/Navigation/sub-components/item.js create mode 100644 packages/asc-web-common/components/Navigation/sub-components/text.js create mode 100644 packages/asc-web-common/components/Navigation/svg/default.react.svg create mode 100644 packages/asc-web-common/components/Navigation/svg/default.tablet.react.svg create mode 100644 packages/asc-web-common/components/Navigation/svg/root.react.svg create mode 100644 packages/asc-web-common/components/Navigation/svg/root.tablet.react.svg diff --git a/packages/asc-web-common/components/Navigation/Navigation.js b/packages/asc-web-common/components/Navigation/Navigation.js new file mode 100644 index 0000000000..c79e8e4ee0 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/Navigation.js @@ -0,0 +1,155 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import Loaders from '@appserver/common/components/Loaders'; + +import StyledContainer from './StyledNavigation'; +import ArrowButton from './sub-components/arrow-btn'; +import Text from './sub-components/text'; +import ControlButtons from './sub-components/control-btn'; +import DropBox from './sub-components/drop-box'; + +import { Consumer } from '@appserver/components/utils/context'; + +import DomHelpers from '@appserver/components/utils/domHelpers'; + +const Navigation = ({ + tReady, + isRootFolder, + title, + canCreate, + isDesktop, + isTabletView, + personal, + onClickFolder, + navigationItems, + getContextOptionsPlus, + getContextOptionsFolder, + onBackToParentFolder, + ...rest +}) => { + const [isOpen, setIsOpen] = React.useState(false); + const [firstClick, setFirstClick] = React.useState(true); + const [changeWidth, setChangeWidth] = React.useState(false); + const dropBoxRef = React.useRef(null); + + const onMissClick = (e) => { + e.preventDefault; + const path = e.path || (e.composedPath && e.composedPath()); + if (!firstClick) { + !path.includes(dropBoxRef.current) ? toggleDropBox() : null; + } else { + setFirstClick((prev) => !prev); + } + }; + + const onClickAvailable = React.useCallback( + (id) => { + onClickFolder && onClickFolder(id); + toggleDropBox(); + }, + [onClickFolder, toggleDropBox], + ); + + const toggleDropBox = React.useCallback(() => { + if (isRootFolder) return; + setIsOpen((prev) => !prev); + setFirstClick(true); + + setTimeout(() => { + setChangeWidth( + DomHelpers.getOuterWidth(dropBoxRef.current) + 24 === + DomHelpers.getOuterWidth(document.getElementById('section')), + ); + }, 0); + }, [setIsOpen, setFirstClick, setChangeWidth, isRootFolder]); + + React.useEffect(() => { + if (isOpen) { + window.addEventListener('click', onMissClick); + } else { + window.removeEventListener('click', onMissClick); + setFirstClick(true); + } + + return () => window.removeEventListener('click', onMissClick); + }, [isOpen, onMissClick]); + return ( + + {(context) => ( + <> + {isOpen && ( + + )} + +
+ {!title || !tReady ? ( + + ) : ( + <> + + + + + )} +
+
+ + )} +
+ ); +}; + +Navigation.propTypes = { + tReady: PropTypes.bool, + isRootFolder: PropTypes.bool, + title: PropTypes.string, + canCreate: PropTypes.bool, + isDesktop: PropTypes.bool, + isTabletView: PropTypes.bool, + personal: PropTypes.bool, + onClickFolder: PropTypes.func, + navigationItems: PropTypes.arrayOf(PropTypes.object), + getContextOptionsPlus: PropTypes.func, + getContextOptionsFolder: PropTypes.func, + onBackToParentFolder: PropTypes.func, +}; + +export default Navigation; diff --git a/packages/asc-web-common/components/Navigation/StyledNavigation.js b/packages/asc-web-common/components/Navigation/StyledNavigation.js new file mode 100644 index 0000000000..9bfabfe1cc --- /dev/null +++ b/packages/asc-web-common/components/Navigation/StyledNavigation.js @@ -0,0 +1,83 @@ +import styled, { css } from 'styled-components'; +import { isMobile, isMobileOnly } from 'react-device-detect'; +import { tablet, desktop, mobile } from '@appserver/components/utils/device'; + +const StyledContainer = styled.div` + .header-container { + position: relative; + height: ${isMobile ? (isMobileOnly ? '53px !important' : '61px !important') : '53px'}; + align-items: center; + max-width: ${(props) => props.width}px; + @media ${tablet} { + height: 63px; + } + + @media ${mobile} { + height: 53px; + } + ${(props) => + props.title && + css` + display: grid; + grid-template-columns: ${(props) => + props.isRootFolder + ? 'auto auto 1fr' + : props.canCreate + ? 'auto auto auto auto 1fr' + : 'auto auto auto 1fr'}; + + @media ${tablet} { + grid-template-columns: ${(props) => + props.isRootFolder + ? '1fr auto' + : props.canCreate + ? 'auto 1fr auto auto' + : 'auto 1fr auto'}; + } + `} + + .arrow-button { + margin-right: 15px; + min-width: 17px; + padding: 16px 0 12px; + align-items: center; + + @media ${tablet} { + padding: 20px 0 16px 8px; + margin-left: -8px; + margin-right: 16px; + } + } + + .add-button { + margin-bottom: -1px; + margin-left: 16px; + + @media ${tablet} { + margin-left: auto; + + & > div:first-child { + padding: 8px 8px 8px 8px; + margin-right: -8px; + } + } + } + + .option-button { + margin-bottom: -1px; + + @media (min-width: 1024px) { + margin-left: 8px; + } + + @media ${tablet} { + & > div:first-child { + padding: 8px 8px 8px 8px; + margin-right: -8px; + } + } + } + } +`; + +export default StyledContainer; diff --git a/packages/asc-web-common/components/Navigation/index.js b/packages/asc-web-common/components/Navigation/index.js new file mode 100644 index 0000000000..173ff5a1c2 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/index.js @@ -0,0 +1 @@ +export default from './Navigation'; diff --git a/packages/asc-web-common/components/Navigation/sub-components/arrow-btn.js b/packages/asc-web-common/components/Navigation/sub-components/arrow-btn.js new file mode 100644 index 0000000000..70e183b61e --- /dev/null +++ b/packages/asc-web-common/components/Navigation/sub-components/arrow-btn.js @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import IconButton from '@appserver/components/icon-button'; + +const ArrowButton = ({ isRootFolder, onBackToParentFolder }) => { + return ( + !isRootFolder && ( + + ) + ); +}; + +export default React.memo(ArrowButton); diff --git a/packages/asc-web-common/components/Navigation/sub-components/control-btn.js b/packages/asc-web-common/components/Navigation/sub-components/control-btn.js new file mode 100644 index 0000000000..47dbcec9eb --- /dev/null +++ b/packages/asc-web-common/components/Navigation/sub-components/control-btn.js @@ -0,0 +1,63 @@ +import React from 'react'; +import styled from 'styled-components'; +import PropTypes from 'prop-types'; +import ContextMenuButton from '@appserver/components/context-menu-button'; + +const StyledContainer = styled.div` + margin-left: 4px; + display: flex; + align-items: center; +`; + +const ControlButtons = ({ + personal, + isRootFolder, + canCreate, + getContextOptionsFolder, + getContextOptionsPlus, +}) => { + return !isRootFolder && canCreate ? ( + + + {!personal && ( + + )} + + ) : ( + canCreate && ( + + ) + ); +}; + +export default React.memo(ControlButtons); diff --git a/packages/asc-web-common/components/Navigation/sub-components/drop-box.js b/packages/asc-web-common/components/Navigation/sub-components/drop-box.js new file mode 100644 index 0000000000..f9095a37a6 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/sub-components/drop-box.js @@ -0,0 +1,236 @@ +import React, { useCallback, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import styled, { css } from 'styled-components'; + +import { VariableSizeList } from 'react-window'; +import CustomScrollbarsVirtualList from '@appserver/components/scrollbar/custom-scrollbars-virtual-list'; + +import ArrowButton from './arrow-btn'; +import Text from './text'; +import ControlButtons from './control-btn'; +import Item from './item'; + +import { isMobile, isMobileOnly } from 'react-device-detect'; +import { + tablet, + mobile, + isMobile as IsMobileUtils, + isTablet as isTabletUtils, +} from '@appserver/components/utils/device'; + +const StyledBox = styled.div` + position: absolute; + top: 1px; + left: ${isMobile ? '-16px' : '-24px'}; + ${isMobile && + css` + width: 100vw !important; + `} + height: fit-content; + min-width: 185px; + ${(props) => + props.changeWidth && + !isMobile && + css` + width: ${(props) => `calc(${props.width}px + 24px)`}; + `} + z-index: 399; + display: flex; + flex-direction: column; + + background: #ffffff; + + filter: drop-shadow(0px 12px 40px rgba(4, 15, 27, 0.12)); + border-radius: 0px 0px 6px 6px; + + @media ${tablet} { + left: -16px; + width: 100vw; + } +`; + +const StyledContainer = styled.div` + position: relative; + top: -1px; + align-items: center; + min-width: 100px; + max-width: calc(100vw - 32px); + height: ${isMobile ? (isMobileOnly ? '53px !important' : '61px !important') : '53px'}; + padding: ${isMobile ? '0px 16px' : '0px 24px'}; + @media ${tablet} { + padding: 0px 16px; + height: 61px; + } + + @media ${mobile} { + height: 53px; + } + display: grid; + grid-template-columns: ${(props) => + props.canCreate ? 'auto auto auto auto 1fr' : 'auto auto auto 1fr'}; + + @media ${tablet} { + grid-template-columns: ${(props) => (props.canCreate ? 'auto 1fr auto auto' : 'auto 1fr auto')}; + } + + .arrow-button { + margin-right: 15px; + min-width: 17px; + padding: 16px 0 12px; + align-items: center; + + @media ${tablet} { + padding: 20px 0 16px 8px; + margin-left: -8px; + margin-right: 16px; + } + } + + .add-button { + margin-bottom: -1px; + margin-left: 16px; + + @media ${tablet} { + margin-left: auto; + + & > div:first-child { + padding: 8px 8px 8px 8px; + margin-right: -8px; + } + } + } + + .option-button { + margin-bottom: -1px; + + @media (min-width: 1024px) { + margin-left: 8px; + } + + @media ${tablet} { + & > div:first-child { + padding: 8px 8px 8px 8px; + margin-right: -8px; + } + } + } +`; + +const Row = React.memo(({ data, index, style }) => { + const isRoot = index === data[0].length - 1; + const paddingBottom = isRoot ? '20px' : 0; + return ( + + ); +}); + +const DropBox = React.forwardRef( + ( + { + width, + height, + changeWidth, + isRootFolder, + onBackToParentFolder, + title, + personal, + canCreate, + navigationItems, + getContextOptionsFolder, + getContextOptionsPlus, + toggleDropBox, + onClickAvailable, + }, + ref, + ) => { + const countItems = navigationItems.length; + + const getItemSize = (index) => { + if (index === countItems - 1) return 29; + return isMobile || IsMobileUtils() || isTabletUtils() ? 36 : 30; + }; + + const getListHeight = useCallback(() => { + const itemsHeight = navigationItems.map((item, index) => getItemSize(index)); + + const currentHeight = itemsHeight.reduce((a, b) => a + b); + + if (isMobileOnly) + return currentHeight + 30 > height - 109 ? height - 109 : currentHeight + 30; + if (isMobile) return currentHeight + 30 > height - 120 ? height - 120 : currentHeight + 30; + return currentHeight + 20 > height - 53 ? height - 53 : currentHeight + 20; + }, [height]); + + // useEffect(() => { + // const items = []; + // const itemsText = []; + // const sectionWidth = document.getElementById('section').offsetWidth; + // navigationItems.forEach((item) => { + // items.push(document.getElementById(item.id)); + // itemsText.push(document.getElementById(`item-text-${item.id}`)); + // }); + // let maxTextWidth = 0; + + // itemsText.forEach((item) => { + // item.offsetWidth > maxTextWidth ? (maxTextWidth = item.offsetWidth) : null; + // }); + + // if (sectionWidth < maxTextWidth + 57) { + // setCurrentWidth(sectionWidth); + // } else { + // setCurrentWidth(maxTextWidth + 57); + // } + + // items.forEach((item, index) => {}); + // }, []); + return ( + + + + + + + + + {Row} + + + ); + }, +); + +DropBox.propTypes = { + width: PropTypes.number, + changeWidth: PropTypes.bool, + isRootFolder: PropTypes.bool, + onBackToParentFolder: PropTypes.func, + title: PropTypes.string, + personal: PropTypes.bool, + canCreate: PropTypes.bool, + navigationItems: PropTypes.arrayOf(PropTypes.object), + getContextOptionsFolder: PropTypes.func, + getContextOptionsPlus: PropTypes.func, + toggleDropBox: PropTypes.func, + onClickAvailable: PropTypes.func, +}; + +export default React.memo(DropBox); diff --git a/packages/asc-web-common/components/Navigation/sub-components/item.js b/packages/asc-web-common/components/Navigation/sub-components/item.js new file mode 100644 index 0000000000..635e148072 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/sub-components/item.js @@ -0,0 +1,86 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import styled from 'styled-components'; + +import Text from '@appserver/components/text'; + +import DefaultIcon from '../svg/default.react.svg'; +import RootIcon from '../svg/root.react.svg'; +import DefaultTabletIcon from '../svg/default.tablet.react.svg'; +import RootTabletIcon from '../svg/root.tablet.react.svg'; + +import { isMobile } from 'react-device-detect'; +import { tablet, isTablet, isMobile as IsMobileUtils } from '@appserver/components/utils/device'; + +const StyledItem = styled.div` + height: auto; + width: fit-content !important; + position: relative; + display: grid; + align-items: end; + grid-template-columns: 17px auto; + cursor: pointer; + padding: ${isMobile ? '0px 16px' : '0px 24px'}; + + @media ${tablet} { + padding: 0px 16px; + } +`; + +const StyledIconWrapper = styled.div` + width: 19px; + display: flex; + align-items: ${(props) => (props.isRoot ? 'center' : 'flex-end')}; + justify-content: center; +`; + +const StyledText = styled(Text)` + margin-left: 10px; + height: 19px; + line-height: 19px; + position: relative; + bottom: -2px; +`; + +const Item = ({ id, title, isRoot, onClick, ...rest }) => { + const onClickAvailable = () => { + onClick && onClick(id); + }; + + React; + + return ( + + + {isMobile || isTablet() || IsMobileUtils() ? ( + isRoot ? ( + + ) : ( + + ) + ) : isRoot ? ( + + ) : ( + + )} + + + {title} + + + ); +}; + +Item.propTypes = { + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + title: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + isRoot: PropTypes.bool, + onClick: PropTypes.func, +}; + +export default React.memo(Item); diff --git a/packages/asc-web-common/components/Navigation/sub-components/text.js b/packages/asc-web-common/components/Navigation/sub-components/text.js new file mode 100644 index 0000000000..10eda6b706 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/sub-components/text.js @@ -0,0 +1,84 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; +import PropTypes from 'prop-types'; + +import ExpanderDownIcon from '@appserver/components/public/static/images/expander-down.react.svg'; +import commonIconsStyles from '@appserver/components/utils/common-icons-style'; + +import Headline from '@appserver/common/components/Headline'; + +import { tablet } from '@appserver/components/utils/device'; +import { isMobile } from 'react-device-detect'; + +const StyledTextContainer = styled.div` + height: ${isMobile ? '21px !important' : '18px'}; + width: fit-content; + position: relative; + display: grid; + grid-template-columns: auto 14px; + + align-items: center; + ${(props) => !props.isRootFolder && 'cursor: pointer'}; + @media ${tablet} { + height: 21px; + } +`; + +const StyledHeadline = styled(Headline)` + min-width: 30px; + width: 100%; + font-weight: 700; + font-size: ${isMobile ? '21px !important' : '18px'}; + line-height: ${isMobile ? '28px !important' : '24px'}; + @media ${tablet} { + font-size: 21px; + line-height: 28px; + } +`; + +const StyledExpanderDownIcon = styled(ExpanderDownIcon)` + min-width: 8px !important; + width: 8px !important; + min-height: 18px !important; + padding-left: 6px; + + ${commonIconsStyles}; +`; + +const StyledExpanderDownIconRotate = styled(ExpanderDownIcon)` + min-width: 8px !important; + width: 8px !important; + min-height: 18px !important; + padding-right: 6px; + transform: rotate(-180deg); + + ${commonIconsStyles}; +`; + +const Text = ({ title, isRootFolder, isOpen, onClick, ...rest }) => { + return ( + + + {title} + + {!isRootFolder ? ( + isOpen ? ( + + ) : ( + + ) + ) : ( + <> + )} + + ); +}; + +Text.propTypes = { + title: PropTypes.string, + isOpen: PropTypes.bool, + isRootFolder: PropTypes.bool, + onCLick: PropTypes.func, +}; + +export default React.memo(Text); diff --git a/packages/asc-web-common/components/Navigation/svg/default.react.svg b/packages/asc-web-common/components/Navigation/svg/default.react.svg new file mode 100644 index 0000000000..3f97764c2c --- /dev/null +++ b/packages/asc-web-common/components/Navigation/svg/default.react.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/asc-web-common/components/Navigation/svg/default.tablet.react.svg b/packages/asc-web-common/components/Navigation/svg/default.tablet.react.svg new file mode 100644 index 0000000000..89b4986c65 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/svg/default.tablet.react.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/asc-web-common/components/Navigation/svg/root.react.svg b/packages/asc-web-common/components/Navigation/svg/root.react.svg new file mode 100644 index 0000000000..b9c60b1d0e --- /dev/null +++ b/packages/asc-web-common/components/Navigation/svg/root.react.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/asc-web-common/components/Navigation/svg/root.tablet.react.svg b/packages/asc-web-common/components/Navigation/svg/root.tablet.react.svg new file mode 100644 index 0000000000..e3464505a6 --- /dev/null +++ b/packages/asc-web-common/components/Navigation/svg/root.tablet.react.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/asc-web-common/components/PageLayout/sub-components/section-header.js b/packages/asc-web-common/components/PageLayout/sub-components/section-header.js index b96db37a95..defd813022 100644 --- a/packages/asc-web-common/components/PageLayout/sub-components/section-header.js +++ b/packages/asc-web-common/components/PageLayout/sub-components/section-header.js @@ -1,13 +1,14 @@ -import React from "react"; -import styled, { css } from "styled-components"; -import equal from "fast-deep-equal/react"; -import classnames from "classnames"; -import PropTypes from "prop-types"; -import { LayoutContextConsumer } from "studio/Layout/context"; -import { isMobile } from "react-device-detect"; -import { tablet, desktop } from "@appserver/components/utils/device"; -import NoUserSelect from "@appserver/components/utils/commonStyles"; +import React from 'react'; +import styled, { css } from 'styled-components'; +import equal from 'fast-deep-equal/react'; +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import { LayoutContextConsumer } from 'studio/Layout/context'; +import { isMobile } from 'react-device-detect'; +import { tablet, desktop } from '@appserver/components/utils/device'; +import NoUserSelect from '@appserver/components/utils/commonStyles'; const StyledSectionHeader = styled.div` + position: relative; border-bottom: 1px solid #eceef1; height: 55px; margin-right: 24px; @@ -19,7 +20,7 @@ const StyledSectionHeader = styled.div` height: 49px; min-height: 48px; max-height: 49px; - width: ${(props) => !props.isLoaded && "100%"}; + width: ${(props) => !props.isLoaded && '100%'}; margin-top: 64px; @media ${tablet} { margin-top: 55px; @@ -44,8 +45,7 @@ const StyledSectionHeader = styled.div` position: fixed; top: 56px; - width: ${(props) => - props.isArticlePinned ? `calc(100% - 272px)` : "100%"}; + width: ${(props) => (props.isArticlePinned ? `calc(100% - 272px)` : '100%')}; background-color: #fff; z-index: 149; @@ -67,8 +67,7 @@ const StyledSectionHeader = styled.div` .group-button-menu-container { padding-bottom: 0 !important; > div:first-child { - top: ${(props) => - !props.isSectionHeaderVisible ? "56px" : "0px"} !important; + top: ${(props) => (!props.isSectionHeaderVisible ? '56px' : '0px')} !important; @media ${desktop} { ${isMobile && @@ -110,12 +109,10 @@ class SectionHeader extends React.Component { {(value) => ( + isSectionHeaderVisible={value.isVisible}>
@@ -126,7 +123,7 @@ class SectionHeader extends React.Component { } } -SectionHeader.displayName = "SectionHeader"; +SectionHeader.displayName = 'SectionHeader'; SectionHeader.propTypes = { isArticlePinned: PropTypes.bool, diff --git a/packages/asc-web-common/components/PageLayout/sub-components/section.js b/packages/asc-web-common/components/PageLayout/sub-components/section.js index 65e815866c..5033d3fdf1 100644 --- a/packages/asc-web-common/components/PageLayout/sub-components/section.js +++ b/packages/asc-web-common/components/PageLayout/sub-components/section.js @@ -1,13 +1,7 @@ -import React from "react"; -import styled, { css } from "styled-components"; -import { tablet, size } from "@appserver/components/utils/device"; -import { - isIOS, - isTablet, - isSafari, - isChrome, - isMobile, -} from "react-device-detect"; +import React from 'react'; +import styled, { css } from 'styled-components'; +import { tablet, size } from '@appserver/components/utils/device'; +import { isIOS, isTablet, isSafari, isChrome, isMobile } from 'react-device-detect'; const tabletProps = css` .section-header_filter { @@ -57,13 +51,11 @@ const StyledSection = styled.section` padding: 0 0 0 16px; ${tabletProps}; } - ${ - isMobile && - css` - ${tabletProps}; - min-width: 100px; - ` - } + ${isMobile && + css` + ${tabletProps}; + min-width: 100px; + `} `; class Section extends React.Component { @@ -86,7 +78,7 @@ class Section extends React.Component { render() { //console.log("PageLayout Section render"); - return ; + return ; } } diff --git a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js index 65cf59bbd9..5b836134b9 100644 --- a/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js +++ b/products/ASC.Files/Client/src/pages/Home/Section/Header/index.js @@ -1,149 +1,151 @@ -import React from "react"; -import copy from "copy-to-clipboard"; -import styled, { css } from "styled-components"; -import { withRouter } from "react-router"; -import toastr from "studio/toastr"; -import Loaders from "@appserver/common/components/Loaders"; -import Headline from "@appserver/common/components/Headline"; -import { FilterType, FileAction } from "@appserver/common/constants"; -import { withTranslation } from "react-i18next"; -import { isMobile } from "react-device-detect"; -import ContextMenuButton from "@appserver/components/context-menu-button"; -import DropDownItem from "@appserver/components/drop-down-item"; -import GroupButtonsMenu from "@appserver/components/group-buttons-menu"; -import IconButton from "@appserver/components/icon-button"; -import { tablet, desktop } from "@appserver/components/utils/device"; -import { Consumer } from "@appserver/components/utils/context"; -import { inject, observer } from "mobx-react"; +import React from 'react'; +import copy from 'copy-to-clipboard'; +import styled, { css } from 'styled-components'; +import { withRouter } from 'react-router'; +import toastr from 'studio/toastr'; +import Loaders from '@appserver/common/components/Loaders'; +import Headline from '@appserver/common/components/Headline'; +import { FilterType, FileAction } from '@appserver/common/constants'; +import { withTranslation } from 'react-i18next'; +import { isMobile } from 'react-device-detect'; +import ContextMenuButton from '@appserver/components/context-menu-button'; +import DropDownItem from '@appserver/components/drop-down-item'; +import GroupButtonsMenu from '@appserver/components/group-buttons-menu'; +import IconButton from '@appserver/components/icon-button'; +import { tablet, desktop, isTablet } from '@appserver/components/utils/device'; +import { Consumer } from '@appserver/components/utils/context'; +import { inject, observer } from 'mobx-react'; +import Navigation from '@appserver/common/components/Navigation'; -const StyledContainer = styled.div` - .header-container { - position: relative; - ${(props) => - props.title && - css` - display: grid; - grid-template-columns: ${(props) => - props.isRootFolder - ? "auto auto 1fr" - : props.canCreate - ? "auto auto auto auto 1fr" - : "auto auto auto 1fr"}; +// const StyledContainer = styled.div` +// .header-container { +// position: relative; +// ${(props) => +// props.title && +// css` +// display: grid; +// grid-template-columns: ${(props) => +// props.isRootFolder +// ? 'auto auto 1fr' +// : props.canCreate +// ? 'auto auto auto auto 1fr' +// : 'auto auto auto 1fr'}; - @media ${tablet} { - grid-template-columns: ${(props) => - props.isRootFolder - ? "1fr auto" - : props.canCreate - ? "auto 1fr auto auto" - : "auto 1fr auto"}; - } - `} - align-items: center; - max-width: calc(100vw - 32px); +// @media ${tablet} { +// grid-template-columns: ${(props) => +// props.isRootFolder +// ? '1fr auto' +// : props.canCreate +// ? 'auto 1fr auto auto' +// : 'auto 1fr auto'}; +// } +// `} +// align-items: center; +// max-width: calc(100vw - 32px); - @media ${tablet} { - .headline-header { - margin-left: -1px; - } - } - .arrow-button { - margin-right: 15px; - min-width: 17px; +// @media ${tablet} { +// .headline-header { +// margin-left: -1px; +// } +// } +// .arrow-button { +// margin-right: 15px; +// min-width: 17px; - @media ${tablet} { - padding: 8px 0 8px 8px; - margin-left: -8px; - margin-right: 16px; - } - } +// @media ${tablet} { +// padding: 8px 0 8px 8px; +// margin-left: -8px; +// margin-right: 16px; +// } +// } - .add-button { - margin-bottom: -1px; - margin-left: 16px; +// .add-button { +// margin-bottom: -1px; +// margin-left: 16px; - @media ${tablet} { - margin-left: auto; +// @media ${tablet} { +// margin-left: auto; - & > div:first-child { - padding: 8px 8px 8px 8px; - margin-right: -8px; - } - } - } +// & > div:first-child { +// padding: 8px 8px 8px 8px; +// margin-right: -8px; +// } +// } +// } - .option-button { - margin-bottom: -1px; +// .option-button { +// margin-bottom: -1px; - @media (min-width: 1024px) { - margin-left: 8px; - } +// @media (min-width: 1024px) { +// margin-left: 8px; +// } - @media ${tablet} { - & > div:first-child { - padding: 8px 8px 8px 8px; - margin-right: -8px; - } - } - } - } +// @media ${tablet} { +// & > div:first-child { +// padding: 8px 8px 8px 8px; +// margin-right: -8px; +// } +// } +// } +// } - .group-button-menu-container { - margin: 0 -16px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - padding-bottom: 56px; +// .group-button-menu-container { +// margin: 0 -16px; +// -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +// padding-bottom: 56px; - ${isMobile && - css` - position: sticky; - `} +// ${isMobile && +// css` +// position: sticky; +// `} - ${(props) => - !props.isTabletView - ? props.width && - isMobile && - css` - width: ${props.width + 40 + "px"}; - ` - : props.width && - isMobile && - css` - width: ${props.width + 32 + "px"}; - `} +// ${(props) => +// !props.isTabletView +// ? props.width && +// isMobile && +// css` +// width: ${props.width + 40 + 'px'}; +// ` +// : props.width && +// isMobile && +// css` +// width: ${props.width + 32 + 'px'}; +// `} - @media ${tablet} { - padding-bottom: 0; - ${!isMobile && - css` - height: 56px; - `} - & > div:first-child { - ${(props) => - !isMobile && - props.width && - css` - width: ${props.width + 16 + "px"}; - `} +// @media ${tablet} { +// padding-bottom: 0; +// ${!isMobile && +// css` +// height: 56px; +// `} +// & > div:first-child { +// ${(props) => +// !isMobile && +// props.width && +// css` +// width: ${props.width + 16 + 'px'}; +// `} - position: absolute; - ${(props) => - !props.isDesktop && - css` - top: 56px; - `} - z-index: 180; - } - } +// position: absolute; +// ${(props) => +// !props.isDesktop && +// css` +// top: 56px; +// `} +// z-index: 180; +// } +// } - @media ${desktop} { - margin: 0 -24px; - } - } -`; +// @media ${desktop} { +// margin: 0 -24px; +// } +// } +// `; class SectionHeaderContent extends React.Component { constructor(props) { super(props); + this.state = { navigationItems: [] }; } onCreate = (format) => { @@ -154,44 +156,44 @@ class SectionHeaderContent extends React.Component { }); }; - createDocument = () => this.onCreate("docx"); + createDocument = () => this.onCreate('docx'); - createSpreadsheet = () => this.onCreate("xlsx"); + createSpreadsheet = () => this.onCreate('xlsx'); - createPresentation = () => this.onCreate("pptx"); + createPresentation = () => this.onCreate('pptx'); createFolder = () => this.onCreate(); - uploadToFolder = () => console.log("Upload To Folder click"); + uploadToFolder = () => console.log('Upload To Folder click'); getContextOptionsPlus = () => { const { t } = this.props; return [ { - key: "new-document", - label: t("NewDocument"), + key: 'new-document', + label: t('NewDocument'), onClick: this.createDocument, }, { - key: "new-spreadsheet", - label: t("NewSpreadsheet"), + key: 'new-spreadsheet', + label: t('NewSpreadsheet'), onClick: this.createSpreadsheet, }, { - key: "new-presentation", - label: t("NewPresentation"), + key: 'new-presentation', + label: t('NewPresentation'), onClick: this.createPresentation, }, { - key: "new-folder", - label: t("NewFolder"), + key: 'new-folder', + label: t('NewFolder'), onClick: this.createFolder, }, - { key: "separator", isSeparator: true }, + { key: 'separator', isSeparator: true }, { - key: "make-invitation-link", - label: t("UploadToFolder"), + key: 'make-invitation-link', + label: t('UploadToFolder'), onClick: this.uploadToFolder, disabled: true, }, @@ -202,21 +204,19 @@ class SectionHeaderContent extends React.Component { const { currentFolderId } = this.props; const { t } = this.props; - copy( - `${window.location.origin}/products/files/filter?folder=${currentFolderId}` - ); + copy(`${window.location.origin}/products/files/filter?folder=${currentFolderId}`); - toastr.success(t("Translations:LinkCopySuccess")); + toastr.success(t('Translations:LinkCopySuccess')); }; onMoveAction = () => this.props.setMoveToPanelVisible(true); onCopyAction = () => this.props.setCopyPanelVisible(true); downloadAction = () => this.props - .downloadAction(this.props.t("Translations:ArchivingData")) + .downloadAction(this.props.t('Translations:ArchivingData')) .catch((err) => toastr.error(err)); - renameAction = () => console.log("renameAction click"); + renameAction = () => console.log('renameAction click'); onOpenSharingPanel = () => this.props.setSharingPanelVisible(true); onDeleteAction = () => { @@ -232,9 +232,9 @@ class SectionHeaderContent extends React.Component { setDeleteDialogVisible(true); } else { const translations = { - deleteOperation: t("Translations:DeleteOperation"), - deleteFromTrash: t("Translations:DeleteFromTrash"), - deleteSelectedElem: t("Translations:DeleteSelectedElem"), + deleteOperation: t('Translations:DeleteOperation'), + deleteFromTrash: t('Translations:DeleteFromTrash'), + deleteSelectedElem: t('Translations:DeleteSelectedElem'), }; deleteAction(translations).catch((err) => toastr.error(err)); @@ -247,45 +247,45 @@ class SectionHeaderContent extends React.Component { const { t } = this.props; return [ { - key: "sharing-settings", - label: t("SharingSettings"), + key: 'sharing-settings', + label: t('SharingSettings'), onClick: this.onOpenSharingPanel, disabled: true, }, { - key: "link-portal-users", - label: t("LinkForPortalUsers"), + key: 'link-portal-users', + label: t('LinkForPortalUsers'), onClick: this.createLinkForPortalUsers, disabled: false, }, - { key: "separator-2", isSeparator: true }, + { key: 'separator-2', isSeparator: true }, { - key: "move-to", - label: t("MoveTo"), + key: 'move-to', + label: t('MoveTo'), onClick: this.onMoveAction, disabled: true, }, { - key: "copy", - label: t("Translations:Copy"), + key: 'copy', + label: t('Translations:Copy'), onClick: this.onCopyAction, disabled: true, }, { - key: "download", - label: t("Common:Download"), + key: 'download', + label: t('Common:Download'), onClick: this.downloadAction, disabled: true, }, { - key: "rename", - label: t("Rename"), + key: 'rename', + label: t('Rename'), onClick: this.renameAction, disabled: true, }, { - key: "delete", - label: t("Common:Delete"), + key: 'delete', + label: t('Common:Delete'), onClick: this.onDeleteAction, disabled: true, }, @@ -299,7 +299,7 @@ class SectionHeaderContent extends React.Component { }; onCheck = (checked) => { - this.props.setSelected(checked ? "all" : "none"); + this.props.setSelected(checked ? 'all' : 'none'); }; onSelect = (item) => { @@ -307,7 +307,7 @@ class SectionHeaderContent extends React.Component { }; onClose = () => { - this.props.setSelected("close"); + this.props.setSelected('close'); }; getMenuItems = () => { @@ -321,11 +321,11 @@ class SectionHeaderContent extends React.Component { let menu = [ { - label: t("Common:Select"), + label: t('Common:Select'), isDropdown: true, isSeparator: true, isSelect: true, - fontWeight: "bold", + fontWeight: 'bold', children, onSelect: this.onSelect, }, @@ -336,125 +336,146 @@ class SectionHeaderContent extends React.Component { return menu; }; + onClickFolder = (data) => { + const { setSelectedNode, setIsLoading, fetchFiles } = this.props; + setSelectedNode(data); + setIsLoading(true); + fetchFiles(data, null, true, false) + .catch((err) => toastr.error(err)) + .finally(() => setIsLoading(false)); + }; + render() { //console.log("Body header render"); const { - t, tReady, - isHeaderVisible, - isHeaderChecked, - isHeaderIndeterminate, isRootFolder, title, canCreate, isDesktop, isTabletView, personal, - viewAs, + navigationPath, } = this.props; - const menuItems = this.getMenuItems(); return ( - - {(context) => ( - - {isHeaderVisible && viewAs !== "table" ? ( -
- -
- ) : ( -
- {!title || !tReady ? ( - - ) : ( - <> - {!isRootFolder && ( - - )} - - {title} - - {!isRootFolder && canCreate ? ( - <> - - {!personal && ( - - )} - - ) : ( - canCreate && ( - - ) - )} - - )} -
- )} -
- )} -
+ + // + // {(context) => ( + // + // {isHeaderVisible && viewAs !== "table" ? ( + //
+ // + //
+ // ) : ( + //
+ // {!title || !tReady ? ( + // + // ) : ( + // <> + // {!isRootFolder && ( + // + // )} + // + // {title} + // + // {!isRootFolder && canCreate ? ( + // <> + // + // {!personal && ( + // + // )} + // + // ) : ( + // canCreate && ( + // + // ) + // )} + // + // )} + //
+ // )} + //
+ // )} + //
); } } @@ -465,6 +486,7 @@ export default inject( filesStore, dialogsStore, selectedFolderStore, + treeFoldersStore, filesActionsStore, settingsStore, }) => { @@ -499,6 +521,8 @@ export default inject( title: selectedFolderStore.title, parentId: selectedFolderStore.parentId, currentFolderId: selectedFolderStore.id, + pathParts: selectedFolderStore.pathParts, + navigationPath: selectedFolderStore.navigationPath, filter, canCreate, isHeaderVisible, @@ -510,6 +534,8 @@ export default inject( personal: auth.settingsStore.personal, viewAs, cbMenuItems, + setSelectedNode: treeFoldersStore.setSelectedNode, + getFolderInfo: treeFoldersStore.getFolderInfo, setSelected, setAction, @@ -524,9 +550,5 @@ export default inject( getHeaderMenu, getCheckboxItemLabel, }; - } -)( - withTranslation(["Home", "Common", "Translations"])( - withRouter(observer(SectionHeaderContent)) - ) -); + }, +)(withTranslation(['Home', 'Common', 'Translations'])(withRouter(observer(SectionHeaderContent)))); diff --git a/products/ASC.Files/Client/src/pages/Home/index.js b/products/ASC.Files/Client/src/pages/Home/index.js index 952f754b42..c63f7d2083 100644 --- a/products/ASC.Files/Client/src/pages/Home/index.js +++ b/products/ASC.Files/Client/src/pages/Home/index.js @@ -1,32 +1,32 @@ -import React from "react"; +import React from 'react'; //import PropTypes from "prop-types"; -import { withRouter } from "react-router"; -import { isMobile } from "react-device-detect"; -import axios from "axios"; -import toastr from "@appserver/components/toast/toastr"; -import PageLayout from "@appserver/common/components/PageLayout"; -import { showLoader, hideLoader } from "@appserver/common/utils"; -import FilesFilter from "@appserver/common/api/files/filter"; -import { getGroup } from "@appserver/common/api/groups"; -import { getUserById } from "@appserver/common/api/people"; -import { withTranslation, Trans } from "react-i18next"; +import { withRouter } from 'react-router'; +import { isMobile } from 'react-device-detect'; +import axios from 'axios'; +import toastr from '@appserver/components/toast/toastr'; +import PageLayout from '@appserver/common/components/PageLayout'; +import { showLoader, hideLoader } from '@appserver/common/utils'; +import FilesFilter from '@appserver/common/api/files/filter'; +import { getGroup } from '@appserver/common/api/groups'; +import { getUserById } from '@appserver/common/api/people'; +import { withTranslation, Trans } from 'react-i18next'; import { ArticleBodyContent, ArticleHeaderContent, ArticleMainButtonContent, -} from "../../components/Article"; +} from '../../components/Article'; import { SectionBodyContent, SectionFilterContent, SectionHeaderContent, SectionPagingContent, -} from "./Section"; +} from './Section'; -import { createTreeFolders } from "../../helpers/files-helpers"; -import MediaViewer from "./MediaViewer"; -import DragTooltip from "../../components/DragTooltip"; -import { observer, inject } from "mobx-react"; -import config from "../../../package.json"; +import { createTreeFolders } from '../../helpers/files-helpers'; +import MediaViewer from './MediaViewer'; +import DragTooltip from '../../components/DragTooltip'; +import { observer, inject } from 'mobx-react'; +import config from '../../../package.json'; class PureHome extends React.Component { componentDidMount() { @@ -42,19 +42,17 @@ class PureHome extends React.Component { getFileInfo, } = this.props; - const reg = new RegExp(`${homepage}((/?)$|/filter)`, "gm"); //TODO: Always find? + const reg = new RegExp(`${homepage}((/?)$|/filter)`, 'gm'); //TODO: Always find? const match = window.location.pathname.match(reg); let filterObj = null; - if (window.location.href.indexOf("/files/#preview") > 1) { + if (window.location.href.indexOf('/files/#preview') > 1) { const pathname = window.location.href; - const fileId = pathname.slice(pathname.indexOf("#preview") + 9); + const fileId = pathname.slice(pathname.indexOf('#preview') + 9); getFileInfo(fileId) .then((data) => { - const canOpenPlayer = mediaViewersFormatsStore.isMediaOrImage( - data.fileExst - ); + const canOpenPlayer = mediaViewersFormatsStore.isMediaOrImage(data.fileExst); const file = { ...data, canOpenPlayer }; setToPreviewFile(file, true); }) @@ -83,7 +81,7 @@ class PureHome extends React.Component { if (filterObj && filterObj.authorType) { const authorType = filterObj.authorType; - const indexOfUnderscore = authorType.indexOf("_"); + const indexOfUnderscore = authorType.indexOf('_'); const type = authorType.slice(0, indexOfUnderscore); const itemId = authorType.slice(indexOfUnderscore + 1); @@ -105,9 +103,9 @@ class PureHome extends React.Component { const newFilter = filter ? filter.clone() : FilesFilter.getDefault(); const requests = [Promise.resolve(newFilter)]; - if (type === "group") { + if (type === 'group') { requests.push(getGroup(itemId)); - } else if (type === "user") { + } else if (type === 'user') { requests.push(getUserById(itemId)); } @@ -117,16 +115,16 @@ class PureHome extends React.Component { .all(requests) .catch((err) => { Promise.resolve(FilesFilter.getDefault()); - console.warn("Filter restored by default", err); + console.warn('Filter restored by default', err); }) .then((data) => { const filter = data[0]; const result = data[1]; if (result) { - const type = result.displayName ? "user" : "group"; + const type = result.displayName ? 'user' : 'group'; const selectedItem = { key: result.id, - label: type === "user" ? result.displayName : result.name, + label: type === 'user' ? result.displayName : result.name, type, }; filter.selectedItem = selectedItem; @@ -154,7 +152,7 @@ class PureHome extends React.Component { fetchDefaultFiles = () => { const { isVisitor, fetchFiles, setIsLoading, setFirstLoad } = this.props; const filterObj = FilesFilter.getDefault(); - const folderId = isVisitor ? "@common" : filterObj.folder; + const folderId = isVisitor ? '@common' : filterObj.folder; fetchFiles(folderId).finally(() => { setIsLoading(false); @@ -171,31 +169,31 @@ class PureHome extends React.Component { showOperationToast = (type, qty, title) => { const { t } = this.props; switch (type) { - case "move": + case 'move': if (qty > 1) { return toastr.success( {{ qty }} elements has been moved - + , ); } return toastr.success( {{ title }} moved - + , ); - case "duplicate": + case 'duplicate': if (qty > 1) { return toastr.success( {{ qty }} elements copied - + , ); } return toastr.success( {{ title }} copied - + , ); default: break; @@ -213,8 +211,7 @@ class PureHome extends React.Component { } = this.props; setUploadPanelVisible(!uploadPanelVisible); - if (primaryProgressDataVisible && uploaded && converted) - clearPrimaryProgressData(); + if (primaryProgressDataVisible && uploaded && converted) clearPrimaryProgressData(); }; componentDidUpdate(prevProps) { const { @@ -227,15 +224,8 @@ class PureHome extends React.Component { if (this.props.isHeaderVisible !== prevProps.isHeaderVisible) { this.props.setHeaderVisible(this.props.isHeaderVisible); } - if ( - isProgressFinished && - isProgressFinished !== prevProps.isProgressFinished - ) { - this.showOperationToast( - secondaryProgressDataStoreIcon, - selectionLength, - selectionTitle - ); + if (isProgressFinished && isProgressFinished !== prevProps.isProgressFinished) { + this.showOperationToast(secondaryProgressDataStoreIcon, selectionLength, selectionTitle); } } @@ -283,16 +273,13 @@ class PureHome extends React.Component { showSecondaryButtonAlert={secondaryProgressDataStoreAlert} viewAs={viewAs} hideAside={ - !!fileActionId || - primaryProgressDataVisible || - secondaryProgressDataStoreVisible + !!fileActionId || primaryProgressDataVisible || secondaryProgressDataStoreVisible } isLoaded={!firstLoad} isHeaderVisible={isHeaderVisible} onOpenUploadPanel={this.showUploadPanel} firstLoad={firstLoad} - dragging={dragging} - > + dragging={dragging}> @@ -325,21 +312,11 @@ class PureHome extends React.Component { } } -const Home = withTranslation("Home")(PureHome); +const Home = withTranslation('Home')(PureHome); export default inject( - ({ - auth, - filesStore, - uploadDataStore, - treeFoldersStore, - mediaViewerDataStore, - formatsStore, - }) => { - const { - secondaryProgressDataStore, - primaryProgressDataStore, - } = uploadDataStore; + ({ auth, filesStore, uploadDataStore, treeFoldersStore, mediaViewerDataStore, formatsStore }) => { + const { secondaryProgressDataStore, primaryProgressDataStore } = uploadDataStore; const { firstLoad, setFirstLoad, @@ -358,12 +335,7 @@ export default inject( const { mediaViewersFormatsStore } = formatsStore; const { id } = fileActionStore; - const { - isRecycleBinFolder, - isPrivacyFolder, - expandedKeys, - setExpandedKeys, - } = treeFoldersStore; + const { isRecycleBinFolder, isPrivacyFolder, expandedKeys, setExpandedKeys } = treeFoldersStore; const { visible: primaryProgressDataVisible, @@ -381,17 +353,10 @@ export default inject( isSecondaryProgressFinished: isProgressFinished, } = secondaryProgressDataStore; - const { - setUploadPanelVisible, - startUpload, - uploaded, - converted, - } = uploadDataStore; + const { setUploadPanelVisible, startUpload, uploaded, converted } = uploadDataStore; const selectionLength = isProgressFinished ? selection.length : null; - const selectionTitle = isProgressFinished - ? filesStore.selectionTitle - : null; + const selectionTitle = isProgressFinished ? filesStore.selectionTitle : null; const { setToPreviewFile } = mediaViewerDataStore; if (!firstLoad) { @@ -444,5 +409,5 @@ export default inject( mediaViewersFormatsStore, getFileInfo, }; - } + }, )(withRouter(observer(Home))); diff --git a/products/ASC.Files/Client/src/store/FilesStore.js b/products/ASC.Files/Client/src/store/FilesStore.js index 76809ef31b..64298d8956 100644 --- a/products/ASC.Files/Client/src/store/FilesStore.js +++ b/products/ASC.Files/Client/src/store/FilesStore.js @@ -1,24 +1,24 @@ -import { makeAutoObservable } from "mobx"; -import api from "@appserver/common/api"; +import { makeAutoObservable } from 'mobx'; +import api from '@appserver/common/api'; import { FolderType, FilterType, FileType, FileAction, AppServerConfig, -} from "@appserver/common/constants"; -import history from "@appserver/common/history"; -import { loopTreeFolders } from "../helpers/files-helpers"; -import config from "../../package.json"; -import { combineUrl } from "@appserver/common/utils"; -import { updateTempContent } from "@appserver/common/utils"; -import { thumbnailStatuses } from "../helpers/constants"; -import { isMobile } from "react-device-detect"; -import { openDocEditor } from "../helpers/utils"; -import toastr from "studio/toastr"; +} from '@appserver/common/constants'; +import history from '@appserver/common/history'; +import { loopTreeFolders } from '../helpers/files-helpers'; +import config from '../../package.json'; +import { combineUrl } from '@appserver/common/utils'; +import { updateTempContent } from '@appserver/common/utils'; +import { thumbnailStatuses } from '../helpers/constants'; +import { isMobile } from 'react-device-detect'; +import { openDocEditor } from '../helpers/utils'; +import toastr from 'studio/toastr'; const { FilesFilter } = api; -const storageViewAs = localStorage.getItem("viewAs"); +const storageViewAs = localStorage.getItem('viewAs'); class FilesStore { authStore; @@ -32,10 +32,9 @@ class FilesStore { isLoaded = false; isLoading = false; - viewAs = - isMobile && storageViewAs !== "tile" ? "row" : storageViewAs || "table"; + viewAs = isMobile && storageViewAs !== 'tile' ? 'row' : storageViewAs || 'table'; dragging = false; - privacyInstructions = "https://www.onlyoffice.com/private-rooms.aspx"; + privacyInstructions = 'https://www.onlyoffice.com/private-rooms.aspx'; isInit = false; tooltipPageX = 0; @@ -47,7 +46,7 @@ class FilesStore { folders = []; selection = []; bufferSelection = []; - selected = "close"; + selected = 'close'; filter = FilesFilter.getDefault(); //TODO: FILTER loadTimeout = null; @@ -59,10 +58,10 @@ class FilesStore { selectedFolderStore, treeFoldersStore, formatsStore, - filesSettingsStore + filesSettingsStore, ) { const pathname = window.location.pathname.toLowerCase(); - this.isEditor = pathname.indexOf("doceditor") !== -1; + this.isEditor = pathname.indexOf('doceditor') !== -1; makeAutoObservable(this); this.authStore = authStore; @@ -81,7 +80,7 @@ class FilesStore { setViewAs = (viewAs) => { this.viewAs = viewAs; - localStorage.setItem("viewAs", viewAs); + localStorage.setItem('viewAs', viewAs); }; setDragging = (dragging) => { @@ -113,11 +112,11 @@ class FilesStore { let operationName; if (this.authStore.isAdmin && isShareFolder) { - operationName = "copy"; + operationName = 'copy'; } else if (!this.authStore.isAdmin && (isShareFolder || isCommonFolder)) { - operationName = "copy"; + operationName = 'copy'; } else { - operationName = "move"; + operationName = 'move'; } return { @@ -152,10 +151,7 @@ class FilesStore { } if (!this.isEditor) { - requests.push( - getPortalCultures(), - this.treeFoldersStore.fetchTreeFolders() - ); + requests.push(getPortalCultures(), this.treeFoldersStore.fetchTreeFolders()); if (isDesktopClient) { requests.push(getIsEncryptionSupport(), getEncryptionKeys()); @@ -191,7 +187,7 @@ class FilesStore { getFilesChecked = (file, selected) => { const type = file.fileType; switch (selected) { - case "all": + case 'all': return true; case FilterType.FoldersOnly.toString(): return file.parentId; @@ -259,43 +255,26 @@ class FilesStore { setFilterUrl = (filter) => { const urlFilter = filter.toUrlParams(); - history.push( - combineUrl( - AppServerConfig.proxyURL, - config.homepage, - `/filter?${urlFilter}` - ) - ); + history.push(combineUrl(AppServerConfig.proxyURL, config.homepage, `/filter?${urlFilter}`)); }; - fetchFiles = ( - folderId, - filter, - clearFilter = true, - withSubfolders = false - ) => { - const { - treeFolders, - setSelectedNode, - getSubfolders, - } = this.treeFoldersStore; + fetchFiles = (folderId, filter, clearFilter = true, withSubfolders = false) => { + const { treeFolders, setSelectedNode, getSubfolders } = this.treeFoldersStore; const filterData = filter ? filter.clone() : FilesFilter.getDefault(); filterData.folder = folderId; - const filterStorageItem = localStorage.getItem( - `UserFilter=${this.userStore.user.id}` - ); + const filterStorageItem = localStorage.getItem(`UserFilter=${this.userStore.user.id}`); if (filterStorageItem && !filter) { - const splitFilter = filterStorageItem.split(","); + const splitFilter = filterStorageItem.split(','); filterData.sortBy = splitFilter[0]; filterData.pageCount = splitFilter[1]; filterData.sortOrder = splitFilter[2]; } - setSelectedNode([folderId + ""]); + setSelectedNode([folderId + '']); //TODO: fix @my let requestCounter = 1; @@ -303,8 +282,7 @@ class FilesStore { api.files .getFolder(folderId, filterData) .then(async (data) => { - const isRecycleBinFolder = - data.current.rootFolderType === FolderType.TRASH; + const isRecycleBinFolder = data.current.rootFolderType === FolderType.TRASH; if (!isRecycleBinFolder && withSubfolders) { const path = data.pathParts.slice(0); @@ -313,8 +291,7 @@ class FilesStore { loopTreeFolders(path, treeFolders, subfolders, foldersCount); } - const isPrivacyFolder = - data.current.rootFolderType === FolderType.Privacy; + const isPrivacyFolder = data.current.rootFolderType === FolderType.Privacy; filterData.total = data.total; this.setFilesFilter(filterData); //TODO: FILTER @@ -323,13 +300,24 @@ class FilesStore { if (clearFilter) { this.fileActionStore.setAction({ type: null }); - this.setSelected("close"); + this.setSelected('close'); } + const navigationPath = await Promise.all( + data.pathParts.map(async (folder) => { + const data = await api.files.getFolderInfo(folder); + + return { id: folder, title: data.title }; + }), + ).then((res) => { + return res.filter((item, index) => index !== res.length - 1).reverse(); + }); + this.selectedFolderStore.setSelectedFolder({ folders: data.folders, ...data.current, pathParts: data.pathParts, + navigationPath: navigationPath, ...{ new: data.new }, }); @@ -344,15 +332,13 @@ class FilesStore { if (!requestCounter) return; requestCounter--; - if (folderId === "@my" /* && !this.isInit */) { + if (folderId === '@my' /* && !this.isInit */) { setTimeout(() => { return request(); }, 5000); } else { this.treeFoldersStore.fetchTreeFolders(); - return this.fetchFiles( - this.userStore.user.isVisitor ? "@common" : "@my" - ); + return this.fetchFiles(this.userStore.user.isVisitor ? '@common' : '@my'); } }); @@ -360,9 +346,7 @@ class FilesStore { }; isFileSelected = (fileId, parentId) => { - const item = this.selection.find( - (x) => x.id === fileId && x.parentId === parentId - ); + const item = this.selection.find((x) => x.id === fileId && x.parentId === parentId); return item !== undefined; }; @@ -376,26 +360,19 @@ class FilesStore { deselectFile = (file) => { const { id, parentId } = file; const isFileSelected = this.isFileSelected(id, parentId); - if (isFileSelected) - this.selection = this.selection.filter((x) => x.id !== id); + if (isFileSelected) this.selection = this.selection.filter((x) => x.id !== id); }; - removeOptions = (options, toRemoveArray) => - options.filter((o) => !toRemoveArray.includes(o)); + removeOptions = (options, toRemoveArray) => options.filter((o) => !toRemoveArray.includes(o)); getFilesContextOptions = (item, canOpenPlayer) => { - const isVisitor = - (this.userStore.user && this.userStore.user.isVisitor) || false; + const isVisitor = (this.userStore.user && this.userStore.user.isVisitor) || false; const isFile = !!item.fileExst || item.contentLength; - const isFavorite = - item.fileStatus === 32 || - item.fileStatus === 33 || - item.fileStatus === 34; + const isFavorite = item.fileStatus === 32 || item.fileStatus === 33 || item.fileStatus === 34; const isFullAccess = item.access < 2; const withoutShare = false; //TODO: need this prop const isThirdPartyItem = !!item.providerKey; - const hasNew = - item.new > 0 || item.fileStatus === 2 || item.fileStatus === 34; + const hasNew = item.new > 0 || item.fileStatus === 2 || item.fileStatus === 34; const canConvert = false; //TODO: fix of added convert check; const isEncrypted = item.encrypted; const isDocuSign = false; //TODO: need this prop; @@ -415,8 +392,7 @@ class FilesStore { const { canWebEdit, canViewedDocs } = this.formatsStore.docserviceStore; - const isThirdPartyFolder = - item.providerKey && item.id === item.rootFolderId; + const isThirdPartyFolder = item.providerKey && item.id === item.rootFolderId; const isShareItem = isShare(item.rootFolderType); const isCommonFolder = isCommon(item.rootFolderType); const isMyFolder = isMy(item.rootFolderType); @@ -427,229 +403,212 @@ class FilesStore { if (isFile) { let fileOptions = [ //"open", - "edit", - "preview", - "view", - "separator0", - "sharing-settings", - "external-link", - "owner-change", - "link-for-portal-users", - "send-by-email", - "docu-sign", - "version", //category - "finalize-version", - "show-version-history", - "block-unblock-version", //need split - "separator1", - "open-location", - "mark-read", - "mark-as-favorite", - "remove-from-favorites", - "download", - "download-as", - "convert", - "move", //category - "move-to", - "copy-to", - "copy", - "restore", - "rename", - "separator2", - "unsubscribe", - "delete", + 'edit', + 'preview', + 'view', + 'separator0', + 'sharing-settings', + 'external-link', + 'owner-change', + 'link-for-portal-users', + 'send-by-email', + 'docu-sign', + 'version', //category + 'finalize-version', + 'show-version-history', + 'block-unblock-version', //need split + 'separator1', + 'open-location', + 'mark-read', + 'mark-as-favorite', + 'remove-from-favorites', + 'download', + 'download-as', + 'convert', + 'move', //category + 'move-to', + 'copy-to', + 'copy', + 'restore', + 'rename', + 'separator2', + 'unsubscribe', + 'delete', ]; if (personal) { fileOptions = this.removeOptions(fileOptions, [ - "owner-change", - "link-for-portal-users", - "docu-sign", - "mark-read", - "unsubscribe", + 'owner-change', + 'link-for-portal-users', + 'docu-sign', + 'mark-read', + 'unsubscribe', ]); if (!this.isWebEditSelected && !canViewedDocs(item.fileExst)) { - fileOptions = this.removeOptions(fileOptions, ["sharing-settings"]); + fileOptions = this.removeOptions(fileOptions, ['sharing-settings']); } } if (!this.isWebEditSelected) { - fileOptions = this.removeOptions(fileOptions, ["download-as"]); + fileOptions = this.removeOptions(fileOptions, ['download-as']); } if (!canConvert || isEncrypted) { - fileOptions = this.removeOptions(fileOptions, ["convert"]); + fileOptions = this.removeOptions(fileOptions, ['convert']); } if (!canOpenPlayer) { - fileOptions = this.removeOptions(fileOptions, ["view"]); + fileOptions = this.removeOptions(fileOptions, ['view']); } else { - fileOptions = this.removeOptions(fileOptions, ["edit", "preview"]); + fileOptions = this.removeOptions(fileOptions, ['edit', 'preview']); } if (!isDocuSign) { - fileOptions = this.removeOptions(fileOptions, ["docu-sign"]); + fileOptions = this.removeOptions(fileOptions, ['docu-sign']); } if (isEditing) { - fileOptions = this.removeOptions(fileOptions, [ - "finalize-version", - "move-to", - "delete", - ]); + fileOptions = this.removeOptions(fileOptions, ['finalize-version', 'move-to', 'delete']); if (isThirdPartyFolder) { - fileOptions = this.removeOptions(fileOptions, ["rename"]); + fileOptions = this.removeOptions(fileOptions, ['rename']); } } if (isFavorite) { - fileOptions = this.removeOptions(fileOptions, ["mark-as-favorite"]); + fileOptions = this.removeOptions(fileOptions, ['mark-as-favorite']); } else { - fileOptions = this.removeOptions(fileOptions, [ - "remove-from-favorites", - ]); + fileOptions = this.removeOptions(fileOptions, ['remove-from-favorites']); if (isFavoritesFolder) { - fileOptions = this.removeOptions(fileOptions, ["mark-as-favorite"]); + fileOptions = this.removeOptions(fileOptions, ['mark-as-favorite']); } } if (isFavoritesFolder) { - fileOptions = this.removeOptions(fileOptions, [ - "move-to", - "delete", - "copy", - ]); + fileOptions = this.removeOptions(fileOptions, ['move-to', 'delete', 'copy']); if (!isFavorite) { - fileOptions = this.removeOptions(fileOptions, ["separator2"]); + fileOptions = this.removeOptions(fileOptions, ['separator2']); } } if (isEncrypted) { fileOptions = this.removeOptions(fileOptions, [ - "open", - "edit", - "link-for-portal-users", - "external-link", - "send-by-email", - "block-unblock-version", //need split - "version", //category - "finalize-version", - "copy-to", - "copy", - "mark-as-favorite", + 'open', + 'edit', + 'link-for-portal-users', + 'external-link', + 'send-by-email', + 'block-unblock-version', //need split + 'version', //category + 'finalize-version', + 'copy-to', + 'copy', + 'mark-as-favorite', ]); } if (isRecentFolder) { - fileOptions = this.removeOptions(fileOptions, ["delete"]); + fileOptions = this.removeOptions(fileOptions, ['delete']); if (!isFavorite) { - fileOptions = this.removeOptions(fileOptions, ["separator2"]); + fileOptions = this.removeOptions(fileOptions, ['separator2']); } } if (isFavoritesFolder || isRecentFolder) { fileOptions = this.removeOptions(fileOptions, [ - "copy", - "move-to", + 'copy', + 'move-to', //"sharing-settings", - "unsubscribe", - "separator2", + 'unsubscribe', + 'separator2', ]); } if (isRecycleBinFolder) { fileOptions = this.removeOptions(fileOptions, [ - "open", - "open-location", - "view", - "preview", - "edit", - "link-for-portal-users", - "sharing-settings", - "external-link", - "send-by-email", - "block-unblock-version", //need split - "version", //category - "finalize-version", - "show-version-history", - "move", //category - "move-to", - "copy-to", - "copy", - "mark-read", - "mark-as-favorite", - "remove-from-favorites", - "rename", - "separator0", - "separator1", + 'open', + 'open-location', + 'view', + 'preview', + 'edit', + 'link-for-portal-users', + 'sharing-settings', + 'external-link', + 'send-by-email', + 'block-unblock-version', //need split + 'version', //category + 'finalize-version', + 'show-version-history', + 'move', //category + 'move-to', + 'copy-to', + 'copy', + 'mark-read', + 'mark-as-favorite', + 'remove-from-favorites', + 'rename', + 'separator0', + 'separator1', ]); } else { - fileOptions = this.removeOptions(fileOptions, ["restore"]); + fileOptions = this.removeOptions(fileOptions, ['restore']); } if (!isFullAccess) { fileOptions = this.removeOptions(fileOptions, [ - "finalize-version", - "rename", - "block-unblock-version", - "copy", - "sharing-settings", + 'finalize-version', + 'rename', + 'block-unblock-version', + 'copy', + 'sharing-settings', ]); } if (isVisitor) { fileOptions = this.removeOptions(fileOptions, [ - "block-unblock-version", - "finalize-version", - "mark-as-favorite", - "remove-from-favorites", + 'block-unblock-version', + 'finalize-version', + 'mark-as-favorite', + 'remove-from-favorites', ]); if (!isFullAccess) { - fileOptions = this.removeOptions(fileOptions, ["rename"]); + fileOptions = this.removeOptions(fileOptions, ['rename']); } } if (!this.canShareOwnerChange(item)) { - fileOptions = this.removeOptions(fileOptions, ["owner-change"]); + fileOptions = this.removeOptions(fileOptions, ['owner-change']); } if (isThirdPartyItem) { - fileOptions = this.removeOptions(fileOptions, [ - "owner-change", - "finalize-version", - "copy", - ]); + fileOptions = this.removeOptions(fileOptions, ['owner-change', 'finalize-version', 'copy']); } if (isCommonFolder) { if (!this.userAccess) { fileOptions = this.removeOptions(fileOptions, [ - "owner-change", - "move-to", - "delete", - "copy", - "separator2", + 'owner-change', + 'move-to', + 'delete', + 'copy', + 'separator2', ]); if (!isFavorite) { - fileOptions = this.removeOptions(fileOptions, ["separator2"]); + fileOptions = this.removeOptions(fileOptions, ['separator2']); } } } if (withoutShare) { - fileOptions = this.removeOptions(fileOptions, [ - "sharing-settings", - "external-link", - ]); + fileOptions = this.removeOptions(fileOptions, ['sharing-settings', 'external-link']); } if (!hasNew) { - fileOptions = this.removeOptions(fileOptions, ["mark-read"]); + fileOptions = this.removeOptions(fileOptions, ['mark-read']); } if ( @@ -659,221 +618,192 @@ class FilesStore { (isMyFolder && (this.filter.filterType || this.filter.search)) ) ) { - fileOptions = this.removeOptions(fileOptions, ["open-location"]); + fileOptions = this.removeOptions(fileOptions, ['open-location']); } if (isShareItem) { if (!isFullAccess) { - fileOptions = this.removeOptions(fileOptions, ["edit"]); + fileOptions = this.removeOptions(fileOptions, ['edit']); } if (isShareFolder) { - fileOptions = this.removeOptions(fileOptions, [ - "copy", - "move-to", - "delete", - ]); + fileOptions = this.removeOptions(fileOptions, ['copy', 'move-to', 'delete']); } } else if (!isEncrypted) { - fileOptions = this.removeOptions(fileOptions, ["unsubscribe"]); + fileOptions = this.removeOptions(fileOptions, ['unsubscribe']); } if (isPrivacyFolder) { fileOptions = this.removeOptions(fileOptions, [ - "preview", - "view", - "separator0", - "copy", - "download-as", + 'preview', + 'view', + 'separator0', + 'copy', + 'download-as', ]); if (!isDesktopClient) { - fileOptions = this.removeOptions(fileOptions, ["sharing-settings"]); + fileOptions = this.removeOptions(fileOptions, ['sharing-settings']); } fileOptions = this.removeOptions( fileOptions, - isFileOwner ? ["unsubscribe"] : ["move-to", "delete"] + isFileOwner ? ['unsubscribe'] : ['move-to', 'delete'], ); } if ( !canWebEdit(item.fileExst) && !canViewedDocs(item.fileExst) && - !fileOptions.includes("view") + !fileOptions.includes('view') ) { - fileOptions = this.removeOptions(fileOptions, [ - "edit", - "preview", - "separator0", - ]); + fileOptions = this.removeOptions(fileOptions, ['edit', 'preview', 'separator0']); } if (!canWebEdit(item.fileExst) && canViewedDocs(item.fileExst)) { - fileOptions = this.removeOptions(fileOptions, ["edit"]); + fileOptions = this.removeOptions(fileOptions, ['edit']); } return fileOptions; } else { let folderOptions = [ - "open", - "separator0", - "sharing-settings", - "owner-change", - "link-for-portal-users", - "separator1", - "open-location", - "download", - "move", //category - "move-to", - "copy-to", - "mark-read", - "restore", - "rename", - "change-thirdparty-info", - "separator2", - "unsubscribe", - "delete", + 'open', + 'separator0', + 'sharing-settings', + 'owner-change', + 'link-for-portal-users', + 'separator1', + 'open-location', + 'download', + 'move', //category + 'move-to', + 'copy-to', + 'mark-read', + 'restore', + 'rename', + 'change-thirdparty-info', + 'separator2', + 'unsubscribe', + 'delete', ]; if (personal) { folderOptions = this.removeOptions(folderOptions, [ - "sharing-settings", - "owner-change", - "link-for-portal-users", - "separator1", - "docu-sign", - "mark-read", - "unsubscribe", + 'sharing-settings', + 'owner-change', + 'link-for-portal-users', + 'separator1', + 'docu-sign', + 'mark-read', + 'unsubscribe', ]); } if (isPrivacyFolder) { - folderOptions = this.removeOptions(folderOptions, [ - "sharing-settings", - "copy", - "copy-to", - ]); + folderOptions = this.removeOptions(folderOptions, ['sharing-settings', 'copy', 'copy-to']); if (!isDesktopClient) { - folderOptions = this.removeOptions(folderOptions, ["rename"]); + folderOptions = this.removeOptions(folderOptions, ['rename']); } } if (isShareItem) { if (isShareFolder) { - folderOptions = this.removeOptions(folderOptions, [ - "move-to", - "delete", - ]); + folderOptions = this.removeOptions(folderOptions, ['move-to', 'delete']); } } else { - folderOptions = this.removeOptions(folderOptions, ["unsubscribe"]); + folderOptions = this.removeOptions(folderOptions, ['unsubscribe']); } if (isRecycleBinFolder) { folderOptions = this.removeOptions(folderOptions, [ - "open", - "link-for-portal-users", - "sharing-settings", - "move", - "move-to", - "copy-to", - "mark-read", - "rename", - "separator0", - "separator1", + 'open', + 'link-for-portal-users', + 'sharing-settings', + 'move', + 'move-to', + 'copy-to', + 'mark-read', + 'rename', + 'separator0', + 'separator1', ]); } else { - folderOptions = this.removeOptions(folderOptions, ["restore"]); + folderOptions = this.removeOptions(folderOptions, ['restore']); } if (!isFullAccess) { //TODO: if added Projects, add project folder check - folderOptions = this.removeOptions(folderOptions, [ - "rename", - "change-thirdparty-info", - ]); + folderOptions = this.removeOptions(folderOptions, ['rename', 'change-thirdparty-info']); } if (!this.canShareOwnerChange(item)) { - folderOptions = this.removeOptions(folderOptions, ["owner-change"]); + folderOptions = this.removeOptions(folderOptions, ['owner-change']); } if (!isFullAccess) { folderOptions = this.removeOptions(folderOptions, [ - "owner-change", - "move-to", - "delete", - "change-thirdparty-info", + 'owner-change', + 'move-to', + 'delete', + 'change-thirdparty-info', ]); if (!isShareItem) { - folderOptions = this.removeOptions(folderOptions, ["separator2"]); + folderOptions = this.removeOptions(folderOptions, ['separator2']); } if (isVisitor) { - folderOptions = this.removeOptions(folderOptions, ["rename"]); + folderOptions = this.removeOptions(folderOptions, ['rename']); } } if (withoutShare) { - folderOptions = this.removeOptions(folderOptions, ["sharing-settings"]); + folderOptions = this.removeOptions(folderOptions, ['sharing-settings']); } if (!hasNew) { - folderOptions = this.removeOptions(folderOptions, ["mark-read"]); + folderOptions = this.removeOptions(folderOptions, ['mark-read']); } if (isThirdPartyFolder) { - folderOptions = this.removeOptions(folderOptions, ["move-to"]); + folderOptions = this.removeOptions(folderOptions, ['move-to']); if (isDesktopClient) { - folderOptions = this.removeOptions(folderOptions, [ - "separator2", - "delete", - ]); + folderOptions = this.removeOptions(folderOptions, ['separator2', 'delete']); } } else { - folderOptions = this.removeOptions(folderOptions, [ - "change-thirdparty-info", - ]); + folderOptions = this.removeOptions(folderOptions, ['change-thirdparty-info']); } if (isThirdPartyItem) { - folderOptions = this.removeOptions(folderOptions, ["owner-change"]); + folderOptions = this.removeOptions(folderOptions, ['owner-change']); if (isShareFolder) { - folderOptions = this.removeOptions(folderOptions, [ - "change-thirdparty-info", - ]); + folderOptions = this.removeOptions(folderOptions, ['change-thirdparty-info']); } else { if (isDesktopClient) { - folderOptions = this.removeOptions(folderOptions, [ - "change-thirdparty-info", - ]); + folderOptions = this.removeOptions(folderOptions, ['change-thirdparty-info']); } - folderOptions = this.removeOptions(folderOptions, ["remove"]); + folderOptions = this.removeOptions(folderOptions, ['remove']); if (!item) { //For damaged items folderOptions = this.removeOptions(folderOptions, [ - "open", - "download", - "copy-to", - "rename", + 'open', + 'download', + 'copy-to', + 'rename', ]); } } } else { - folderOptions = this.removeOptions(folderOptions, [ - "change-thirdparty-info", - ]); + folderOptions = this.removeOptions(folderOptions, ['change-thirdparty-info']); } if (!(isMyFolder && (this.filter.filterType || this.filter.search))) { - folderOptions = this.removeOptions(folderOptions, ["open-location"]); + folderOptions = this.removeOptions(folderOptions, ['open-location']); } return folderOptions; @@ -928,9 +858,7 @@ class FilesStore { }; updateFile = (fileId, title) => { - return api.files - .updateFile(fileId, title) - .then((file) => this.setFile(file)); + return api.files.updateFile(fileId, title).then((file) => this.setFile(file)); }; renameFolder = (folderId, title) => { @@ -955,8 +883,7 @@ class FilesStore { const isCommonFolder = this.treeFoldersStore.commonFolder && this.selectedFolderStore.pathParts && - this.treeFoldersStore.commonFolder.id === - this.selectedFolderStore.pathParts[0]; + this.treeFoldersStore.commonFolder.id === this.selectedFolderStore.pathParts[0]; if (item.providerKey || !isCommonFolder) { return false; @@ -971,8 +898,7 @@ class FilesStore { get canShare() { const folderType = this.selectedFolderStore.rootFolderType; - const isVisitor = - (this.userStore.user && this.userStore.user.isVisitor) || false; + const isVisitor = (this.userStore.user && this.userStore.user.isVisitor) || false; if (isVisitor) { return false; @@ -1001,20 +927,14 @@ class FilesStore { get currentFilesCount() { const serviceFilesCount = this.getServiceFilesCount(); const filesCount = this.getFilesCount(); - return this.selectedFolderStore.providerItem - ? serviceFilesCount - : filesCount; + return this.selectedFolderStore.providerItem ? serviceFilesCount : filesCount; } get iconOfDraggedFile() { const { getIcon } = this.formatsStore.iconFormatsStore; if (this.selection.length === 1) { - return getIcon( - 24, - this.selection[0].fileExst, - this.selection[0].providerKey - ); + return getIcon(24, this.selection[0].fileExst, this.selection[0].providerKey); } return null; } @@ -1041,13 +961,10 @@ class FilesStore { return true; case FolderType.SHARE: const canCreateInSharedFolder = this.selectedFolderStore.access === 1; - return ( - !this.selectedFolderStore.isRootFolder && canCreateInSharedFolder - ); + return !this.selectedFolderStore.isRootFolder && canCreateInSharedFolder; case FolderType.Privacy: return ( - this.authStore.settingsStore.isDesktopClient && - this.settingsStore.isEncryptionSupport + this.authStore.settingsStore.isDesktopClient && this.settingsStore.isEncryptionSupport ); case FolderType.COMMON: return this.authStore.isAdmin; @@ -1067,7 +984,7 @@ class FilesStore { items.unshift({ id: -1, - title: "", + title: '', parentId: this.selectedFolderStore.id, fileExst: this.fileActionStore.extension, icon, @@ -1117,22 +1034,16 @@ class FilesStore { const { canConvert } = this.formatsStore.docserviceStore; - const canOpenPlayer = mediaViewersFormatsStore.isMediaOrImage( - item.fileExst - ); + const canOpenPlayer = mediaViewersFormatsStore.isMediaOrImage(item.fileExst); const previewUrl = canOpenPlayer - ? combineUrl( - AppServerConfig.proxyURL, - config.homepage, - `/#preview/${id}` - ) + ? combineUrl(AppServerConfig.proxyURL, config.homepage, `/#preview/${id}`) : null; const contextOptions = this.getFilesContextOptions(item, canOpenPlayer); //const isCanWebEdit = canWebEdit(item.fileExst); const icon = - this.viewAs !== "tile" + this.viewAs !== 'tile' ? getIcon(24, fileExst, providerKey, contentLength) : getIcon(32, fileExst, providerKey, contentLength); @@ -1144,11 +1055,7 @@ class FilesStore { const { isRecycleBinFolder } = this.treeFoldersStore; const folderUrl = isFolder - ? combineUrl( - AppServerConfig.proxyURL, - config.homepage, - `/filter?folder=${id}` - ) + ? combineUrl(AppServerConfig.proxyURL, config.homepage, `/filter?folder=${id}`) : null; const needConvert = canConvert(fileExst); @@ -1156,7 +1063,7 @@ class FilesStore { const docUrl = combineUrl( AppServerConfig.proxyURL, config.homepage, - `/doceditor?fileId=${id}${needConvert ? "&action=view" : ""}` + `/doceditor?fileId=${id}${needConvert ? '&action=view' : ''}`, ); const href = isRecycleBinFolder @@ -1223,32 +1130,23 @@ class FilesStore { get cbMenuItems() { const { mediaViewersFormatsStore, iconFormatsStore } = this.formatsStore; - const { - isDocument, - isPresentation, - isSpreadsheet, - isArchive, - } = iconFormatsStore; + const { isDocument, isPresentation, isSpreadsheet, isArchive } = iconFormatsStore; const { isImage, isVideo } = mediaViewersFormatsStore; - let cbMenu = ["all"]; + let cbMenu = ['all']; const filesItems = [...this.files, ...this.folders]; if (this.folders.length) cbMenu.push(FilterType.FoldersOnly); for (let item of filesItems) { if (isDocument(item.fileExst)) cbMenu.push(FilterType.DocumentsOnly); - else if (isPresentation(item.fileExst)) - cbMenu.push(FilterType.PresentationsOnly); - else if (isSpreadsheet(item.fileExst)) - cbMenu.push(FilterType.SpreadsheetsOnly); + else if (isPresentation(item.fileExst)) cbMenu.push(FilterType.PresentationsOnly); + else if (isSpreadsheet(item.fileExst)) cbMenu.push(FilterType.SpreadsheetsOnly); else if (isImage(item.fileExst)) cbMenu.push(FilterType.ImagesOnly); else if (isVideo(item.fileExst)) cbMenu.push(FilterType.MediaOnly); else if (isArchive(item.fileExst)) cbMenu.push(FilterType.ArchiveOnly); } - const hasFiles = cbMenu.some( - (elem) => elem !== "all" && elem !== FilterType.FoldersOnly - ); + const hasFiles = cbMenu.some((elem) => elem !== 'all' && elem !== FilterType.FoldersOnly); if (hasFiles) cbMenu.push(FilterType.FilesOnly); @@ -1259,36 +1157,32 @@ class FilesStore { getCheckboxItemLabel = (t, key) => { switch (key) { - case "all": - return t("All"); + case 'all': + return t('All'); case FilterType.FoldersOnly: - return t("Translations:Folders"); + return t('Translations:Folders'); case FilterType.DocumentsOnly: - return t("Common:Documents"); + return t('Common:Documents'); case FilterType.PresentationsOnly: - return t("Translations:Presentations"); + return t('Translations:Presentations'); case FilterType.SpreadsheetsOnly: - return t("Translations:Spreadsheets"); + return t('Translations:Spreadsheets'); case FilterType.ImagesOnly: - return t("Images"); + return t('Images'); case FilterType.MediaOnly: - return t("Media"); + return t('Media'); case FilterType.ArchiveOnly: - return t("Archives"); + return t('Archives'); case FilterType.FilesOnly: - return t("AllFiles"); + return t('AllFiles'); default: - return ""; + return ''; } }; get sortedFiles() { - const { - isSpreadsheet, - isPresentation, - isDocument, - } = this.formatsStore.iconFormatsStore; + const { isSpreadsheet, isPresentation, isDocument } = this.formatsStore.iconFormatsStore; const { filesConverts } = this.formatsStore.docserviceStore; let sortedFiles = { @@ -1330,8 +1224,7 @@ class FilesStore { return false; case FolderType.COMMON: return ( - this.authStore.isAdmin || - this.selection.some((x) => x.access === 0 || x.access === 1) + this.authStore.isAdmin || this.selection.some((x) => x.access === 0 || x.access === 1) ); case FolderType.Privacy: return true; @@ -1343,10 +1236,7 @@ class FilesStore { } get isAccessedSelected() { - return ( - this.selection.length && - this.selection.every((x) => x.access === 1 || x.access === 0) - ); + return this.selection.length && this.selection.every((x) => x.access === 1 || x.access === 0); } get isThirdPartyRootSelection() { @@ -1411,12 +1301,12 @@ class FilesStore { } = this.formatsStore.docserviceStore; if (selection[0].encrypted) { - return ["FullAccess", "DenyAccess"]; + return ['FullAccess', 'DenyAccess']; } let AccessOptions = []; - AccessOptions.push("ReadOnly", "DenyAccess"); + AccessOptions.push('ReadOnly', 'DenyAccess'); const webEdit = selection.find((x) => canWebEdit(x.fileExst)); @@ -1424,18 +1314,16 @@ class FilesStore { const webReview = selection.find((x) => canWebReview(x.fileExst)); - const formFillingDocs = selection.find((x) => - canFormFillingDocs(x.fileExst) - ); + const formFillingDocs = selection.find((x) => canFormFillingDocs(x.fileExst)); const webFilter = selection.find((x) => canWebFilterEditing(x.fileExst)); - if (webEdit || !externalAccess) AccessOptions.push("FullAccess"); + if (webEdit || !externalAccess) AccessOptions.push('FullAccess'); - if (webComment) AccessOptions.push("Comment"); - if (webReview) AccessOptions.push("Review"); - if (formFillingDocs) AccessOptions.push("FormFilling"); - if (webFilter) AccessOptions.push("FilterEditing"); + if (webComment) AccessOptions.push('Comment'); + if (webReview) AccessOptions.push('Review'); + if (formFillingDocs) AccessOptions.push('FormFilling'); + if (webFilter) AccessOptions.push('FilterEditing'); return AccessOptions; }; @@ -1455,16 +1343,16 @@ class FilesStore { const newSelection = []; for (let item of items) { - const value = item.getAttribute("value"); - const splitValue = value && value.split("_"); + const value = item.getAttribute('value'); + const splitValue = value && value.split('_'); const fileType = splitValue[0]; const id = - splitValue[splitValue.length - 1] === "draggable" - ? splitValue.slice(1, -1).join("_") - : splitValue.slice(1).join("_"); + splitValue[splitValue.length - 1] === 'draggable' + ? splitValue.slice(1, -1).join('_') + : splitValue.slice(1).join('_'); - if (fileType === "file") { + if (fileType === 'file') { newSelection.push(this.files.find((f) => f.id == id)); } else { newSelection.push(this.folders.find((f) => f.id == id)); @@ -1475,7 +1363,7 @@ class FilesStore { //need fo table view const clearSelection = Object.values( - newSelection.reduce((item, n) => ((item[n.id] = n), item), {}) + newSelection.reduce((item, n) => ((item[n.id] = n), item), {}), ); this.setSelection(clearSelection); @@ -1486,43 +1374,19 @@ class FilesStore { return api.files.getShareFiles(fileIds, folderIds); } - setShareFiles = ( - folderIds, - fileIds, - share, - notify, - sharingMessage, - externalAccess, - ownerId - ) => { + setShareFiles = (folderIds, fileIds, share, notify, sharingMessage, externalAccess, ownerId) => { let externalAccessRequest = []; if (fileIds.length === 1 && externalAccess !== null) { - externalAccessRequest = fileIds.map((id) => - api.files.setExternalAccess(id, externalAccess) - ); + externalAccessRequest = fileIds.map((id) => api.files.setExternalAccess(id, externalAccess)); } - const ownerChangeRequest = ownerId - ? [this.setFilesOwner(folderIds, fileIds, ownerId)] - : []; + const ownerChangeRequest = ownerId ? [this.setFilesOwner(folderIds, fileIds, ownerId)] : []; const shareRequest = !!share.length - ? [ - api.files.setShareFiles( - fileIds, - folderIds, - share, - notify, - sharingMessage - ), - ] + ? [api.files.setShareFiles(fileIds, folderIds, share, notify, sharingMessage)] : []; - const requests = [ - ...ownerChangeRequest, - ...shareRequest, - ...externalAccessRequest, - ]; + const requests = [...ownerChangeRequest, ...shareRequest, ...externalAccessRequest]; return Promise.all(requests); }; diff --git a/products/ASC.Files/Client/src/store/SelectedFolderStore.js b/products/ASC.Files/Client/src/store/SelectedFolderStore.js index c47ae2b924..484a1eb27d 100644 --- a/products/ASC.Files/Client/src/store/SelectedFolderStore.js +++ b/products/ASC.Files/Client/src/store/SelectedFolderStore.js @@ -1,4 +1,4 @@ -import { makeAutoObservable } from "mobx"; +import { makeAutoObservable } from 'mobx'; class SelectedFolderStore { folders = null; @@ -17,6 +17,7 @@ class SelectedFolderStore { updatedBy = null; rootFolderType = null; pathParts = null; + navigationPath = null; providerItem = null; constructor() { @@ -44,6 +45,7 @@ class SelectedFolderStore { this.updatedBy = null; this.rootFolderType = null; this.pathParts = null; + this.navigationPath = null; this.providerItem = null; };