Merge branch 'feature/navigation' into feature/virtual-rooms-1.2

This commit is contained in:
Timofey 2022-02-01 18:44:49 +08:00
commit f6090b4f58
18 changed files with 811 additions and 306 deletions

View File

@ -0,0 +1,154 @@
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 (
<Consumer>
{(context) => (
<>
{isOpen && (
<DropBox
{...rest}
ref={dropBoxRef}
changeWidth={changeWidth}
width={context.sectionWidth}
isRootFolder={isRootFolder}
onBackToParentFolder={onBackToParentFolder}
title={title}
personal={personal}
isRootFolder={isRootFolder}
canCreate={canCreate}
navigationItems={navigationItems}
getContextOptionsFolder={getContextOptionsFolder}
getContextOptionsPlus={getContextOptionsPlus}
toggleDropBox={toggleDropBox}
onClickAvailable={onClickAvailable}
/>
)}
<StyledContainer
width={context.sectionWidth}
isRootFolder={isRootFolder}
canCreate={canCreate}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}>
<div className="header-container">
{!title || !tReady ? (
<Loaders.SectionHeader />
) : (
<>
<ArrowButton
isRootFolder={isRootFolder}
onBackToParentFolder={onBackToParentFolder}
/>
<Text
title={title}
isOpen={false}
isRootFolder={isRootFolder}
onClick={toggleDropBox}
/>
<ControlButtons
personal={personal}
isRootFolder={isRootFolder}
canCreate={canCreate}
getContextOptionsFolder={getContextOptionsFolder}
getContextOptionsPlus={getContextOptionsPlus}
/>
</>
)}
</div>
</StyledContainer>
</>
)}
</Consumer>
);
};
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;

View File

@ -0,0 +1,75 @@
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 {
margin-top: 14px;
position: relative;
align-items: center;
max-width: ${(props) => props.width}px;
${(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;
align-items: center;
@media ${tablet} {
padding: 0 0 0 8px;
margin-left: -8px;
margin-right: 16px;
}
}
.add-button {
margin-left: 16px;
@media ${tablet} {
margin-left: auto;
& > div:first-child {
padding: 0px 8px 8px 8px;
margin-right: -8px;
}
}
}
.option-button {
@media (min-width: 1024px) {
margin-left: 8px;
}
@media ${tablet} {
& > div:first-child {
padding: 0px 8px 8px 8px;
margin-right: -8px;
}
}
}
}
`;
export default StyledContainer;

View File

@ -0,0 +1 @@
export default from './Navigation';

View File

@ -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 && (
<IconButton
iconName="/static/images/arrow.path.react.svg"
size="17"
color="#A3A9AE"
hoverColor="#657077"
isFill={true}
onClick={onBackToParentFolder}
className="arrow-button"
/>
)
);
};
export default React.memo(ArrowButton);

View File

@ -0,0 +1,71 @@
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 ? (
<StyledContainer>
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={getContextOptionsPlus}
isDisabled={false}
/>
{!personal && (
<ContextMenuButton
className="option-button"
directionX="right"
iconName="images/vertical-dots.react.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={getContextOptionsFolder}
isDisabled={false}
/>
)}
</StyledContainer>
) : (
canCreate && (
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={getContextOptionsPlus}
isDisabled={false}
/>
)
);
};
ControlButtons.propTypes = {
personal: PropTypes.bool,
isRootFolder: PropTypes.bool,
canCreate: PropTypes.bool,
getContextOptionsFolder: PropTypes.func,
getContextOptionsPlus: PropTypes.func,
};
export default React.memo(ControlButtons);

View File

@ -0,0 +1,219 @@
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: 0px;
left: ${isMobile ? "-16px" : "-20px"};
${isMobile &&
css`
width: 100vw !important;
max-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} {
top: 0px;
left: -16px;
width: 100vw;
max-width: 100vw !important;
}
`;
const StyledContainer = styled.div`
margin: 14px 0 7px;
position: relative;
top: 0px;
align-items: center;
min-width: 100px;
max-width: calc(100vw - 32px);
padding: ${isMobile ? "0px 16px" : "0px 20px"};
display: grid;
grid-template-columns: ${(props) =>
props.canCreate ? "auto auto auto auto 1fr" : "auto auto auto 1fr"};
@media ${tablet} {
top: ${!isMobile && "0px"};
padding: 0px 16px;
grid-template-columns: ${(props) =>
props.canCreate ? "auto 1fr auto" : "auto 1fr auto"};
}
@media ${mobile} {
}
.arrow-button {
margin-right: 15px;
min-width: 17px;
align-items: center;
@media ${tablet} {
padding: 0 0 0 8px;
margin-left: -8px;
margin-right: 16px;
}
}
.add-button {
margin-left: 16px;
@media ${tablet} {
margin-left: auto;
& > div:first-child {
padding: 0px 8px 8px 8px;
margin-right: -8px;
}
}
}
.option-button {
@media (min-width: 1024px) {
margin-left: 8px;
}
@media ${tablet} {
& > div:first-child {
padding: 0px 8px 8px 8px;
margin-right: -8px;
}
}
}
`;
const Row = React.memo(({ data, index, style }) => {
const isRoot = index === data[0].length - 1;
return (
<Item
key={data[0][index].id}
id={data[0][index].id}
title={data[0][index].title}
isRoot={isRoot}
onClick={data[1]}
style={{ ...style }}
/>
);
});
const DropBox = React.forwardRef(
(
{
width,
changeWidth,
isRootFolder,
onBackToParentFolder,
title,
personal,
canCreate,
navigationItems,
getContextOptionsFolder,
getContextOptionsPlus,
toggleDropBox,
onClickAvailable,
},
ref
) => {
const [dropBoxHeight, setDropBoxHeight] = React.useState(0);
const countItems = navigationItems.length;
const getItemSize = (index) => {
if (index === countItems - 1) return 51;
return isMobile || IsMobileUtils() || isTabletUtils() ? 36 : 30;
};
React.useEffect(() => {
const itemsHeight = navigationItems.map((item, index) =>
getItemSize(index)
);
const currentHeight = itemsHeight.reduce((a, b) => a + b);
setDropBoxHeight(
currentHeight > window.innerHeight - 99
? window.innerHeight - 99
: currentHeight
);
});
return (
<StyledBox ref={ref} width={width} changeWidth={changeWidth}>
<StyledContainer canCreate={canCreate}>
<ArrowButton
isRootFolder={isRootFolder}
onBackToParentFolder={onBackToParentFolder}
/>
<Text title={title} isOpen={true} onClick={toggleDropBox} />
<ControlButtons
personal={personal}
isRootFolder={isRootFolder}
canCreate={canCreate}
getContextOptionsFolder={getContextOptionsFolder}
getContextOptionsPlus={getContextOptionsPlus}
/>
</StyledContainer>
<VariableSizeList
height={dropBoxHeight}
width={"auto"}
itemCount={countItems}
itemSize={getItemSize}
itemData={[navigationItems, onClickAvailable]}
outerElementType={CustomScrollbarsVirtualList}
>
{Row}
</VariableSizeList>
</StyledBox>
);
}
);
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);

View File

@ -0,0 +1,85 @@
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: auto !important;
position: relative;
display: grid;
align-items: ${(props) => (props.isRoot ? 'baseline' : 'end')};
grid-template-columns: 17px auto;
cursor: pointer;
padding: ${isMobile ? '0px 16px' : '0px 24px'};
@media ${tablet} {
padding: 0px 16px;
max-width: 100vw !important;
}
`;
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;
position: relative;
bottom: ${(props) => (props.isRoot ? '2px' : '-1px')};
`;
const Item = ({ id, title, isRoot, onClick, ...rest }) => {
const onClickAvailable = () => {
onClick && onClick(id);
};
React;
return (
<StyledItem id={id} isRoot={isRoot} onClick={onClickAvailable} {...rest}>
<StyledIconWrapper isRoot={isRoot}>
{isMobile || isTablet() || IsMobileUtils() ? (
isRoot ? (
<RootTabletIcon />
) : (
<DefaultTabletIcon />
)
) : isRoot ? (
<RootIcon />
) : (
<DefaultIcon />
)}
</StyledIconWrapper>
<StyledText
isRoot={isRoot}
fontWeight={isRoot ? '600' : '400'}
isRoot={isRoot}
fontSize={'15px'}
truncate={true}>
{title}
</StyledText>
</StyledItem>
);
};
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);

View File

@ -0,0 +1,79 @@
import React from 'react';
import styled 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`
width: fit-content;
position: relative;
display: grid;
grid-template-columns: auto 14px;
align-items: center;
${(props) => !props.isRootFolder && 'cursor: pointer'};
`;
const StyledHeadline = styled(Headline)`
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 (
<StyledTextContainer isRootFolder={isRootFolder} onClick={onClick} {...rest}>
<StyledHeadline type="content" truncate={true}>
{title}
</StyledHeadline>
{!isRootFolder ? (
isOpen ? (
<StyledExpanderDownIconRotate />
) : (
<StyledExpanderDownIcon />
)
) : (
<></>
)}
</StyledTextContainer>
);
};
Text.propTypes = {
title: PropTypes.string,
isOpen: PropTypes.bool,
isRootFolder: PropTypes.bool,
onCLick: PropTypes.func,
};
export default React.memo(Text);

View File

@ -0,0 +1,4 @@
<svg width="19" height="30" viewBox="0 0 19 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 1V16" stroke="#DFE2E3" stroke-miterlimit="16" stroke-dasharray="2 2"/>
<circle cx="9.5" cy="23.5" r="2.5" stroke="#316DAA" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 259 B

View File

@ -0,0 +1,4 @@
<svg width="19" height="36" viewBox="0 0 19 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 1V22" stroke="#DFE2E3" stroke-miterlimit="16" stroke-dasharray="2 2"/>
<circle cx="9.5" cy="29.5" r="2.5" stroke="#316DAA" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 259 B

View File

@ -0,0 +1,4 @@
<svg width="19" height="31" viewBox="0 0 19 31" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 1L9.5 15" stroke="#DFE2E3" stroke-miterlimit="16" stroke-dasharray="2 2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.5 19L14 22.7386V27.5461C14 28.3491 13.3284 29 12.5 29H6.5C5.67157 29 5 28.3491 5 27.5461V22.7386L9.5 19ZM7 23.6302V27.0615H12V23.6302L9.5 21.5532L7 23.6302Z" fill="#316DAA"/>
</svg>

After

Width:  |  Height:  |  Size: 419 B

View File

@ -0,0 +1,4 @@
<svg width="19" height="36" viewBox="0 0 19 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 1L9.5 20" stroke="#DFE2E3" stroke-miterlimit="16" stroke-dasharray="2 2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.5 24L14 27.7386V32.5461C14 33.3491 13.3284 34 12.5 34H6.5C5.67157 34 5 33.3491 5 32.5461V27.7386L9.5 24ZM7 28.6302V32.0615H12V28.6302L9.5 26.5532L7 28.6302Z" fill="#316DAA"/>
</svg>

After

Width:  |  Height:  |  Size: 419 B

View File

@ -1,7 +1,7 @@
import React from "react";
import styled from "styled-components";
import equal from "fast-deep-equal/react";
import { tablet } from "@appserver/components/utils/device";
import React from 'react';
import styled from 'styled-components';
import equal from 'fast-deep-equal/react';
import { tablet } from '@appserver/components/utils/device';
const StyledArticleHeader = styled.div`
height: 39px;
@ -30,6 +30,6 @@ class ArticleHeader extends React.Component {
}
}
ArticleHeader.displayName = "ArticleHeader";
ArticleHeader.displayName = 'ArticleHeader';
export default ArticleHeader;

View File

@ -1,20 +1,21 @@
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;
height: 42px;
margin-right: 24px;
${NoUserSelect}
${isMobile &&
css`
height: 20px;
width: ${(props) => !props.isLoaded && "100%"};
width: ${(props) => !props.isLoaded && '100%'};
margin-top: 62px;
@media ${tablet} {
@ -23,14 +24,12 @@ const StyledSectionHeader = styled.div`
`}
@media ${desktop} {
${(props) =>
(props.viewAs === "table" || props.viewAs === "tile") &&
"margin-left: -4px"};
${(props) => (props.viewAs === 'table' || props.viewAs === 'tile') && 'margin-left: -4px'};
}
@media ${tablet} {
${(props) =>
props.viewAs !== "tablet" &&
props.viewAs !== 'tablet' &&
css`
height: 49px;
@ -60,8 +59,7 @@ const StyledSectionHeader = styled.div`
position: fixed;
top: 48px;
width: ${(props) =>
props.isArticlePinned ? `calc(100% - 272px)` : "100%"};
width: ${(props) => (props.isArticlePinned ? `calc(100% - 272px)` : '100%')};
background-color: #fff;
z-index: 149;
@ -83,8 +81,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 &&
@ -127,12 +124,10 @@ class SectionHeader extends React.Component {
<StyledSectionHeader
isArticlePinned={isArticlePinned}
isSectionHeaderVisible={value.isVisible}
viewAs={viewAs}
>
viewAs={viewAs}>
<div
className={classnames("section-header hidingHeader", {
"section-header--hidden":
value.isVisible === undefined ? false : !value.isVisible,
className={classnames('section-header hidingHeader', {
'section-header--hidden': value.isVisible === undefined ? false : !value.isVisible,
})}
{...rest}
/>
@ -143,7 +138,7 @@ class SectionHeader extends React.Component {
}
}
SectionHeader.displayName = "SectionHeader";
SectionHeader.displayName = 'SectionHeader';
SectionHeader.propTypes = {
isArticlePinned: PropTypes.bool,

View File

@ -1,7 +1,14 @@
import React from 'react';
import styled, { css } from 'styled-components';
import { tablet, size, mobile } from '@appserver/components/utils/device';
import { isIOS, isTablet, isSafari, isChrome, isMobileOnly, isMobile } from 'react-device-detect';
import React from "react";
import styled, { css } from "styled-components";
import { tablet, size, mobile } from "@appserver/components/utils/device";
import {
isIOS,
isTablet,
isSafari,
isChrome,
isMobileOnly,
isMobile,
} from "react-device-detect";
const tabletProps = css`
.section-header_filter {
@ -20,12 +27,12 @@ const StyledSection = styled.section`
display: flex;
flex-direction: column;
@media ${mobile} {
display: ${(props) => (!props.showText ? 'flex' : 'none')};
display: ${(props) => (!props.showText ? "flex" : "none")};
}
${isMobileOnly &&
css`
display: ${(props) => (!props.showText ? 'flex' : 'none')} !important;
display: ${(props) => (!props.showText ? "flex" : "none")} !important;
`}
//width: ${(props) => `${props.widthProp}px`};
.layout-progress-bar {
@ -94,7 +101,7 @@ class Section extends React.Component {
render() {
//console.log("PageLayout Section render");
return <StyledSection {...this.props} />;
return <StyledSection id="section" {...this.props} />;
}
}

View File

@ -15,167 +15,12 @@ import { tablet, desktop } from "@appserver/components/utils/device";
import { Consumer } from "@appserver/components/utils/context";
import { inject, observer } from "mobx-react";
import TableGroupMenu from "@appserver/components/table-container/TableGroupMenu";
const StyledContainer = styled.div`
.table-container_group-menu {
${(props) =>
props.viewAs === "table"
? css`
margin: 0px -20px;
width: calc(100% + 44px);
`
: css`
margin: 0px -24px;
width: calc(100% + 48px);
`}
@media ${tablet} {
margin: 0 -16px;
width: calc(100% + 32px);
}
}
.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"};
${(props) => !props.isLoading && "top: 7px;"}
}
`}
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} {
padding: 8px 0 8px 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;
}
}
}
.trash-button {
margin-bottom: -1px;
@media (min-width: 1024px) {
margin-left: 8px;
}
@media ${tablet} {
& > div:first-child {
margin-right: -8px;
}
}
}
}
.group-button-menu-container {
margin: 0 -16px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
${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"};
`}
@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: 48px;
`}
z-index: 180;
}
}
@media ${desktop} {
margin: 0 -24px;
}
}
`;
import Navigation from "@appserver/common/components/Navigation";
class SectionHeaderContent extends React.Component {
constructor(props) {
super(props);
this.state = { navigationItems: [] };
}
onCreate = (format) => {
@ -409,137 +254,54 @@ class SectionHeaderContent extends React.Component {
this.props.setSelected(checked ? "all" : "none");
};
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,
navigationPath,
getHeaderMenu,
viewAs,
isRecycleBinFolder,
isEmptyFilesList,
} = this.props;
const menuItems = this.getMenuItems();
const isLoading = !title || !tReady;
const headerMenu = getHeaderMenu(t);
return (
<Consumer>
{(context) => (
<StyledContainer
width={context.sectionWidth}
isRootFolder={isRootFolder}
canCreate={canCreate}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}
isLoading={isLoading}
viewAs={viewAs}
>
{isHeaderVisible ? (
<TableGroupMenu
checkboxOptions={menuItems}
onChange={this.onChange}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
/>
) : (
<div className="header-container">
{isLoading ? (
<Loaders.SectionHeader />
) : (
<>
{!isRootFolder && (
<IconButton
iconName="/static/images/arrow.path.react.svg"
size="17"
color="#A3A9AE"
hoverColor="#657077"
isFill={true}
onClick={this.onBackToParentFolder}
className="arrow-button"
/>
)}
<Headline
className="headline-header"
type="content"
truncate={true}
>
{title}
</Headline>
{!isRootFolder && canCreate ? (
<>
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/header.plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={this.getContextOptionsPlus}
isDisabled={false}
/>
<ContextMenuButton
className="option-button"
directionX="right"
iconName="images/vertical-dots.react.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={this.getContextOptionsFolder}
isDisabled={false}
/>
</>
) : (
canCreate && (
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/header.plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
isFill
getData={this.getContextOptionsPlus}
isDisabled={false}
/>
)
)}
{isRecycleBinFolder && !isEmptyFilesList && (
<span title={t("EmptyRecycleBin")}>
<IconButton
iconName="images/clear.active.react.svg"
size="15"
color="#A3A9AE"
hoverColor="#657077"
isFill={true}
onClick={this.onEmptyTrashAction}
className="trash-button"
/>
</span>
)}
</>
)}
</div>
)}
</StyledContainer>
)}
</Consumer>
<Navigation
isRootFolder={isRootFolder}
canCreate={canCreate}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}
personal={personal}
tReady={tReady}
menuItems={menuItems}
navigationItems={navigationPath}
getContextOptionsPlus={this.getContextOptionsPlus}
getContextOptionsFolder={this.getContextOptionsFolder}
onClose={this.onClose}
onClickFolder={this.onClickFolder}
onBackToParentFolder={this.onBackToParentFolder}
/>
);
}
}
@ -550,9 +312,9 @@ export default inject(
filesStore,
dialogsStore,
selectedFolderStore,
treeFoldersStore,
filesActionsStore,
settingsStore,
treeFoldersStore,
}) => {
const {
setSelected,
@ -568,7 +330,8 @@ export default inject(
setIsLoading,
cbMenuItems,
getCheckboxItemLabel,
isEmptyFilesList, getFolderInfo,
isEmptyFilesList,
getFolderInfo,
setBufferSelection,
viewAs,
} = filesStore;
@ -592,6 +355,8 @@ export default inject(
title: selectedFolderStore.title,
parentId: selectedFolderStore.parentId,
currentFolderId: selectedFolderStore.id,
pathParts: selectedFolderStore.pathParts,
navigationPath: selectedFolderStore.navigationPath,
filter,
canCreate,
isHeaderVisible,
@ -602,6 +367,7 @@ export default inject(
confirmDelete: settingsStore.confirmDelete,
personal: auth.settingsStore.personal,
cbMenuItems,
setSelectedNode: treeFoldersStore.setSelectedNode,
getFolderInfo,
setSelected,
@ -625,7 +391,8 @@ export default inject(
setEmptyTrashDialogVisible,
isEmptyFilesList,
isPrivacyFolder,
viewAs, };
viewAs,
};
}
)(
withTranslation(["Home", "Common", "Translations"])(

View File

@ -352,10 +352,23 @@ class FilesStore {
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 },
});

View File

@ -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;
};