Merge branch 'feature/virtual-rooms-1.2' of github.com:ONLYOFFICE/AppServer into feature/virtual-rooms-1.2
@ -1,5 +1,5 @@
|
||||
{
|
||||
"kafka": {
|
||||
"BootstrapServers": "localhost:9092"
|
||||
"BootstrapServers": ""
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,11 @@ const Selector = (props) => {
|
||||
|
||||
const newGroupList = groupList;
|
||||
|
||||
newGroupList.find((group) => group.key === groupHeader.key).total = total;
|
||||
if (newGroupList.length > 0) {
|
||||
newGroupList.find(
|
||||
(group) => group.key === groupHeader.key
|
||||
).total = total;
|
||||
}
|
||||
|
||||
setGroupList(newGroupList);
|
||||
}
|
||||
@ -334,7 +338,7 @@ const Selector = (props) => {
|
||||
isDisabled={isDisabled}
|
||||
placeholder={searchPlaceHolderLabel}
|
||||
value={searchValue}
|
||||
onChange={onSearchChange}
|
||||
onSearchChange={onSearchChange}
|
||||
onClearSearch={onSearchReset}
|
||||
/>
|
||||
<div style={{ width: "100%", height: "100%" }} className="body-options">
|
||||
|
@ -31,7 +31,7 @@ const Article = ({
|
||||
toggleShowText,
|
||||
toggleArticleOpen,
|
||||
setIsMobileArticle,
|
||||
isLoading,
|
||||
isLoadedPage,
|
||||
children,
|
||||
...rest
|
||||
}) => {
|
||||
@ -117,7 +117,7 @@ const Article = ({
|
||||
handleWrapperClass="resizable-border not-selectable"
|
||||
>
|
||||
<SubArticleHeader
|
||||
isLoading={isLoading}
|
||||
isLoadedPage={isLoadedPage}
|
||||
showText={showText}
|
||||
onClick={toggleShowText}
|
||||
>
|
||||
@ -128,7 +128,7 @@ const Article = ({
|
||||
{articleMainButtonContent.props.children}
|
||||
</SubArticleMainButton>
|
||||
) : null}
|
||||
<SubArticleBody isLoading={isLoading} showText={showText}>
|
||||
<SubArticleBody showText={showText}>
|
||||
{articleBodyContent ? articleBodyContent.props.children : null}
|
||||
</SubArticleBody>
|
||||
</Resizable>
|
||||
|
@ -1,10 +1,8 @@
|
||||
import React from "react";
|
||||
import Scrollbar from "@appserver/components/scrollbar";
|
||||
import LoaderArticleBody from "./article-body-loader";
|
||||
const ArticleBody = ({ children, isLoading = false }) => {
|
||||
return isLoading ? (
|
||||
<LoaderArticleBody />
|
||||
) : (
|
||||
|
||||
const ArticleBody = ({ children }) => {
|
||||
return (
|
||||
<Scrollbar className="article-body__scrollbar" stype="mediumBlack">
|
||||
{children}
|
||||
</Scrollbar>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { isTablet as isTabletUtils } from "@appserver/components/utils/device";
|
||||
import { isTablet } from "react-device-detect";
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import {
|
||||
StyledArticleHeader,
|
||||
StyledHeading,
|
||||
@ -15,12 +15,22 @@ const ArticleHeader = ({
|
||||
showText,
|
||||
children,
|
||||
onClick,
|
||||
isLoading = false,
|
||||
isLoadedPage,
|
||||
isLoaded,
|
||||
tReady,
|
||||
setIsLoadedArticleHeader,
|
||||
...rest
|
||||
}) => {
|
||||
const heightLoader = isTabletUtils() || isTablet ? "20px" : "32px";
|
||||
const isLoadedSetting = isLoaded;
|
||||
const commonSettings = location.pathname.includes("common");
|
||||
|
||||
return isLoading ? (
|
||||
useEffect(() => {
|
||||
if (isLoadedSetting) setIsLoadedArticleHeader(isLoadedSetting);
|
||||
}, [isLoadedSetting]);
|
||||
|
||||
const heightLoader = isTabletUtils() || isTablet ? "20px" : "32px";
|
||||
const showLoader = commonSettings ? !isLoadedPage : false;
|
||||
return showLoader ? (
|
||||
<StyledArticleHeader>
|
||||
<Loaders.ArticleHeader height={heightLoader} className="loader" />
|
||||
</StyledArticleHeader>
|
||||
@ -45,4 +55,11 @@ ArticleHeader.propTypes = {
|
||||
|
||||
ArticleHeader.displayName = "Header";
|
||||
|
||||
export default React.memo(ArticleHeader);
|
||||
export default inject(({ common }) => {
|
||||
const { isLoaded, setIsLoadedArticleHeader } = common;
|
||||
|
||||
return {
|
||||
isLoaded,
|
||||
setIsLoadedArticleHeader,
|
||||
};
|
||||
})(observer(ArticleHeader));
|
||||
|
@ -0,0 +1,145 @@
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
width: 100%;
|
||||
padding: ${(props) => (props.isPersonal ? "0px 16px 12px" : "12px 16px")};
|
||||
${(props) =>
|
||||
props.isPersonal &&
|
||||
css`
|
||||
margin-left: -12px;
|
||||
margin-right: 12px;
|
||||
`}
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
border-bottom: ${(props) => props.theme.filesPanels.sharing.borderBottom};
|
||||
`;
|
||||
|
||||
StyledHeader.defaultProps = { theme: Base };
|
||||
|
||||
const StyledExternalLink = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding: ${(props) => (props.isPersonal ? "20px 4px" : "20px 16px")};
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
border-bottom: ${(props) =>
|
||||
props.isPersonal ? "none" : props.theme.filesPanels.sharing.borderBottom};
|
||||
|
||||
.rectangle-loader {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledExternalLink.defaultProps = { theme: Base };
|
||||
|
||||
const StyledInternalLink = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 20px 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
`;
|
||||
|
||||
const StyledOwner = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 8px 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
margin-bottom: 16px;
|
||||
|
||||
.owner-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg:first-child {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledBody = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
div:nth-child(3) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledItem = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 8px 16px;
|
||||
|
||||
.item-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg:first-child {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtons = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 4px;
|
||||
|
||||
svg:first-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export {
|
||||
StyledContainer,
|
||||
StyledHeader,
|
||||
StyledExternalLink,
|
||||
StyledInternalLink,
|
||||
StyledOwner,
|
||||
StyledBody,
|
||||
StyledItem,
|
||||
StyledButtons,
|
||||
};
|
@ -0,0 +1,138 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
StyledContainer,
|
||||
StyledHeader,
|
||||
StyledExternalLink,
|
||||
StyledInternalLink,
|
||||
StyledOwner,
|
||||
StyledBody,
|
||||
StyledItem,
|
||||
} from "./StyledSharingPanel";
|
||||
import RectangleLoader from "../RectangleLoader/RectangleLoader";
|
||||
|
||||
const SharingPanelLoader = ({ id, className, style, ...rest }) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledHeader>
|
||||
<RectangleLoader width={"283px"} height={"29px"} />
|
||||
<RectangleLoader width={"48px"} height={"29px"} />
|
||||
</StyledHeader>
|
||||
|
||||
<StyledExternalLink>
|
||||
<RectangleLoader
|
||||
className="rectangle-loader"
|
||||
width={"146px"}
|
||||
height={"22px"}
|
||||
/>
|
||||
<RectangleLoader
|
||||
className="rectangle-loader"
|
||||
width={"448px"}
|
||||
height={"32px"}
|
||||
/>
|
||||
<RectangleLoader width={"184px"} height={"20px"} />
|
||||
</StyledExternalLink>
|
||||
|
||||
<StyledInternalLink>
|
||||
<RectangleLoader width={"99px"} height={"22px"} />
|
||||
<RectangleLoader width={"30px"} height={"22px"} />
|
||||
</StyledInternalLink>
|
||||
|
||||
<StyledOwner>
|
||||
<div className="owner-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</StyledOwner>
|
||||
|
||||
<StyledBody>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
<StyledItem>
|
||||
<div className="item-info">
|
||||
<RectangleLoader
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"1000px"}
|
||||
/>
|
||||
<RectangleLoader width={"91px"} height={"16px"} />
|
||||
</div>
|
||||
<RectangleLoader width={"45px"} height={"32px"} />
|
||||
</StyledItem>
|
||||
</StyledBody>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
SharingPanelLoader.propTypes = {
|
||||
id: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
||||
SharingPanelLoader.defaultProps = {
|
||||
id: undefined,
|
||||
className: undefined,
|
||||
style: undefined,
|
||||
};
|
||||
|
||||
export default SharingPanelLoader;
|
@ -0,0 +1,66 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import {
|
||||
StyledContainer,
|
||||
StyledHeader,
|
||||
StyledExternalLink,
|
||||
StyledInternalLink,
|
||||
StyledOwner,
|
||||
StyledBody,
|
||||
StyledItem,
|
||||
StyledButtons,
|
||||
} from "./StyledSharingPanel";
|
||||
import RectangleLoader from "../RectangleLoader/RectangleLoader";
|
||||
|
||||
const SharingPanelLoaderModal = ({
|
||||
id,
|
||||
className,
|
||||
style,
|
||||
isShared,
|
||||
...rest
|
||||
}) => {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledHeader isPersonal={true}>
|
||||
<RectangleLoader width={"283px"} height={"16px"} />
|
||||
</StyledHeader>
|
||||
|
||||
<StyledExternalLink isPersonal={true}>
|
||||
<RectangleLoader
|
||||
className="rectangle-loader"
|
||||
width={"146px"}
|
||||
height={"22px"}
|
||||
/>
|
||||
{isShared && (
|
||||
<>
|
||||
<RectangleLoader
|
||||
className="rectangle-loader"
|
||||
width={"368px"}
|
||||
height={"32px"}
|
||||
/>
|
||||
<RectangleLoader width={"184px"} height={"20px"} />
|
||||
</>
|
||||
)}
|
||||
</StyledExternalLink>
|
||||
<StyledButtons>
|
||||
<RectangleLoader width={"100%"} height={"40px"} />
|
||||
<RectangleLoader width={"100%"} height={"40px"} />
|
||||
</StyledButtons>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
SharingPanelLoaderModal.propTypes = {
|
||||
id: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
||||
SharingPanelLoaderModal.defaultProps = {
|
||||
id: undefined,
|
||||
className: undefined,
|
||||
style: undefined,
|
||||
};
|
||||
|
||||
export default SharingPanelLoaderModal;
|
@ -22,6 +22,8 @@ import Tiles from "./TilesLoader";
|
||||
import DialogLoader from "./DialogLoader";
|
||||
import DialogAsideLoader from "./DialogAsideLoader";
|
||||
import ListLoader from "./ListLoader";
|
||||
import SharingPanelLoader from "./SharingPanelLoader";
|
||||
import SharingPanelLoaderModal from "./SharingPanelLoader/modal";
|
||||
|
||||
export default {
|
||||
Rectangle,
|
||||
@ -48,4 +50,6 @@ export default {
|
||||
ArticleGroup,
|
||||
ListLoader,
|
||||
NewTreeFolders,
|
||||
SharingPanelLoader,
|
||||
SharingPanelLoaderModal,
|
||||
};
|
||||
|
@ -250,8 +250,13 @@ class SettingsStore {
|
||||
this.isLoaded = isLoaded;
|
||||
};
|
||||
|
||||
setCultures = (cultures) => {
|
||||
this.cultures = cultures;
|
||||
};
|
||||
|
||||
getPortalCultures = async () => {
|
||||
this.cultures = await api.settings.getPortalCultures();
|
||||
const cultures = await api.settings.getPortalCultures();
|
||||
this.setCultures(cultures);
|
||||
};
|
||||
|
||||
setIsEncryptionSupport = (isEncryptionSupport) => {
|
||||
|
@ -13,21 +13,33 @@ import {
|
||||
StyledAccessRightItemContent,
|
||||
StyledAccessRightItemTitleAndBadge,
|
||||
} from "./styled-accessright.js";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const AccessRightSelect = ({ options, onSelect, selectedOption, ...props }) => {
|
||||
const AccessRightSelect = ({
|
||||
options,
|
||||
onSelect,
|
||||
advancedOptions,
|
||||
selectedOption,
|
||||
...props
|
||||
}) => {
|
||||
const [currentItem, setCurrentItem] = useState(selectedOption);
|
||||
|
||||
function onSelectCurrentItem(e) {
|
||||
const key = e.currentTarget.dataset.key;
|
||||
const key = +e.currentTarget.dataset.key;
|
||||
const item = options.find((el) => {
|
||||
return el.key === key;
|
||||
});
|
||||
|
||||
if (item) {
|
||||
setCurrentItem(item);
|
||||
onSelect && onSelect(item);
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
setCurrentItem(selectedOption);
|
||||
}, [selectedOption]);
|
||||
|
||||
const formatToAccessRightItem = (data) => {
|
||||
return (
|
||||
<>
|
||||
@ -67,12 +79,15 @@ const AccessRightSelect = ({ options, onSelect, selectedOption, ...props }) => {
|
||||
|
||||
return (
|
||||
<StyledAccessRightWrapper>
|
||||
<StyledAccessRightIcon src={currentItem?.icon} />
|
||||
<ReactSVG className="access-right__icon" src={currentItem?.icon} />
|
||||
<ComboBox
|
||||
advancedOptions={formatToAccessRightItem(options)}
|
||||
advancedOptions={
|
||||
!!advancedOptions ? advancedOptions : formatToAccessRightItem(options)
|
||||
}
|
||||
onSelect={onSelectCurrentItem}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
opened
|
||||
opened={false}
|
||||
noBorder
|
||||
options={[]}
|
||||
scaled={false}
|
||||
@ -92,8 +107,10 @@ AccessRightSelect.propTypes = {
|
||||
options: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
/** Will be triggered whenever an AccessRightSelect is selected option */
|
||||
onSelect: PropTypes.func,
|
||||
/** List of advanced options */
|
||||
advancedOptions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
||||
/** The option that is selected by default */
|
||||
selectedOption: PropTypes.object,
|
||||
};
|
||||
|
||||
export default AccessRightSelect;
|
||||
export default React.memo(AccessRightSelect);
|
||||
|
@ -3,14 +3,28 @@ import Base from "../themes/base";
|
||||
|
||||
const StyledAccessRightWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.access-right__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
path {
|
||||
fill: ${(props) => props.theme.dropDownItem.icon.color};
|
||||
}
|
||||
}
|
||||
|
||||
.combo-button {
|
||||
padding-left: 4px;
|
||||
}
|
||||
`;
|
||||
StyledAccessRightWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const StyledAccessRightIcon = styled.img`
|
||||
margin-right: 4.18px;
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
const StyledAccessRightItem = styled.div`
|
||||
width: 424px;
|
||||
width: auto;
|
||||
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
@ -56,7 +56,7 @@ class Backdrop extends React.Component {
|
||||
|
||||
modifyClassName = () => {
|
||||
const { className } = this.props;
|
||||
let modifiedClass = "backdrop-active";
|
||||
let modifiedClass = "backdrop-active not-selectable";
|
||||
|
||||
if (className) {
|
||||
if (typeof className !== "string") {
|
||||
|
@ -223,7 +223,6 @@ const StyledButton = styled(ButtonWrapper).attrs((props) => ({
|
||||
|
||||
.icon {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -114,13 +114,14 @@ class DropDown extends React.PureComponent {
|
||||
|
||||
const rects = this.dropDownRef.current.getBoundingClientRect();
|
||||
const parentRects = forwardedRef?.current?.getBoundingClientRect();
|
||||
|
||||
const container = DomHelpers.getViewport();
|
||||
|
||||
const dimensions = parentRects
|
||||
? {
|
||||
toTopCorner: parentRects.top,
|
||||
parentHeight: parentRects.height,
|
||||
containerHeight: parentRects.top,
|
||||
containerHeight: !parentRects.top,
|
||||
}
|
||||
: {
|
||||
toTopCorner: rects.top,
|
||||
@ -352,6 +353,7 @@ DropDownContainer.propTypes = {
|
||||
isDefaultMode: PropTypes.bool,
|
||||
/** Needed to open correctly people and group selector when the section width is small */
|
||||
smallSectionWidth: PropTypes.bool,
|
||||
/** It is necessary when we explicitly set the direction, disables check position */
|
||||
fixedDirection: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,6 @@ const MainButtonMobile = (props) => {
|
||||
};
|
||||
|
||||
const onMainButtonClick = (e) => {
|
||||
if (isOpen && ref.current.contains(e.target)) return;
|
||||
toggle(!isOpen);
|
||||
};
|
||||
|
||||
@ -191,8 +190,8 @@ const MainButtonMobile = (props) => {
|
||||
/>
|
||||
))}
|
||||
</StyledProgressContainer>
|
||||
<StyledButtonOptions isOpenButton={isOpenButton}>
|
||||
{isOpenButton && buttonOptions
|
||||
<StyledButtonOptions>
|
||||
{buttonOptions
|
||||
? buttonOptions.map((option) =>
|
||||
option.isSeparator ? (
|
||||
<div key={option.key} className="separator-wrapper">
|
||||
@ -213,20 +212,6 @@ const MainButtonMobile = (props) => {
|
||||
)
|
||||
: ""}
|
||||
</StyledButtonOptions>
|
||||
{withButton && (
|
||||
<StyledButtonWrapper
|
||||
isUploading={isUploading}
|
||||
isOpenButton={isOpenButton}
|
||||
>
|
||||
<Button
|
||||
label={title}
|
||||
className="action-mobile-button"
|
||||
primary
|
||||
size="medium"
|
||||
onClick={onUploadClick}
|
||||
/>
|
||||
</StyledButtonWrapper>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -250,6 +235,7 @@ const MainButtonMobile = (props) => {
|
||||
directionY="top"
|
||||
directionX="right"
|
||||
isMobile={isMobile || isTablet}
|
||||
fixedDirection={true}
|
||||
heightProp={height}
|
||||
sectionWidth={sectionWidth}
|
||||
isDefaultMode={false}
|
||||
|
@ -134,7 +134,6 @@ const StyledDropDownItem = styled(DropDownItem)`
|
||||
`;
|
||||
|
||||
const StyledButtonOptions = styled.div`
|
||||
display: ${(props) => !props.isOpenButton && "none"};
|
||||
padding: 16px 0;
|
||||
background-color: ${(props) =>
|
||||
props.theme.mainButtonMobile.buttonOptions.backgroundColor};
|
||||
|
@ -81,6 +81,10 @@ class ModalDialog extends React.Component {
|
||||
componentDidMount() {
|
||||
window.addEventListener("resize", this.throttledResize);
|
||||
window.addEventListener("keyup", this.onKeyPress);
|
||||
|
||||
window.onpopstate = () => {
|
||||
this.props.onClose();
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -163,17 +167,23 @@ class ModalDialog extends React.Component {
|
||||
<Loaders.DialogLoader bodyHeight={modalLoaderBodyHeight} />
|
||||
) : (
|
||||
<>
|
||||
<StyledHeader>
|
||||
<Heading className="heading" size="medium" truncate={true}>
|
||||
{header ? header.props.children : null}
|
||||
</Heading>
|
||||
{!withoutCloseButton && (
|
||||
<CloseButton
|
||||
className="modal-dialog-button_close"
|
||||
onClick={onClose}
|
||||
></CloseButton>
|
||||
)}
|
||||
</StyledHeader>
|
||||
{header && (
|
||||
<StyledHeader>
|
||||
<Heading
|
||||
className="heading"
|
||||
size="medium"
|
||||
truncate={true}
|
||||
>
|
||||
{header ? header.props.children : null}
|
||||
</Heading>
|
||||
{!withoutCloseButton && (
|
||||
<CloseButton
|
||||
className="modal-dialog-button_close"
|
||||
onClick={onClose}
|
||||
></CloseButton>
|
||||
)}
|
||||
</StyledHeader>
|
||||
)}
|
||||
<BodyBox paddingProp={modalBodyPadding}>
|
||||
{body ? body.props.children : null}
|
||||
</BodyBox>
|
||||
|
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_20597_65864)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.84646 0.979492L5.22299 14.5025L7.15485 15.0201L10.7783 1.49713L8.84646 0.979492ZM2.41419 7.99916L5.20702 5.20614L3.79276 3.79197L0.292868 7.2921C-0.0976332 7.68263 -0.0976212 8.31578 0.292895 8.7063L3.79278 12.2062L5.20699 10.7919L2.41419 7.99916ZM13.5857 8.00004L10.7928 5.20714L12.207 3.79292L15.707 7.29293C15.8945 7.48047 15.9999 7.73482 15.9999 8.00004C15.9999 8.26526 15.8945 8.51961 15.707 8.70715L12.2065 12.2076L10.7923 10.7934L13.5857 8.00004Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20597_65864">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 777 B |
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.85498 16L1.15188 16C0.518827 16 0.00382324 15.485 0.00378789 14.8519L0.00378713 6.14776C0.00378708 5.51468 0.518826 4.99964 1.15187 4.99964L4.01036 4.99964L4.01036 9.96112C4.01036 11.1721 4.75801 11.9963 5.96898 11.9963L11.0031 11.9963L11.0031 14.8519C11.0031 15.485 10.4881 16 9.85498 16ZM14.8703 11.0013L6.12976 11.0013C5.50682 11.0013 4.99997 10.4945 5 9.87155L5 1.12969C5 0.506788 5.50679 9.17346e-07 6.12973 8.62887e-07L14.8703 9.87639e-08C15.4932 4.43048e-08 16 0.506787 16 1.12973L16 9.87155C16 10.4945 15.4932 11.0013 14.8703 11.0013Z" fill="#A3A9AE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.14502 -1.07443e-06L14.8481 -2.59613e-06C15.4812 -2.70681e-06 15.9962 0.515037 15.9962 1.14808L15.9962 9.85224C15.9962 10.4853 15.4812 11.0004 14.8481 11.0004L11.9896 11.0004L11.9896 6.03888C11.9896 4.82791 11.242 4.00369 10.031 4.00369L4.99694 4.00369L4.99694 1.14809C4.99693 0.515038 5.51194 -9.63738e-07 6.14502 -1.07443e-06ZM1.12973 4.99872L9.87024 4.99872C10.4932 4.99872 11 5.50551 11 6.12845L11 14.8703C11 15.4932 10.4932 16 9.87028 16L1.12973 16C0.50679 16 3.70837e-05 15.4932 2.6e-06 14.8703L1.07154e-06 6.12845C9.62618e-07 5.50551 0.506823 4.99872 1.12973 4.99872Z" fill="#A3A9AE"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 716 B After Width: | Height: | Size: 747 B |
@ -12,8 +12,9 @@ import {
|
||||
StyledSubmenuItems,
|
||||
StyledSubmenuItemText,
|
||||
} from "./styled-submenu";
|
||||
import LoaderSubmenu from "./loader";
|
||||
|
||||
const Submenu = ({ data, startSelect = 0, onSelect, ...rest }) => {
|
||||
const Submenu = ({ data, startSelect = 0, onSelect, isLoading, ...rest }) => {
|
||||
if (!data) return null;
|
||||
|
||||
const [currentItem, setCurrentItem] = useState(
|
||||
@ -74,29 +75,40 @@ const Submenu = ({ data, startSelect = 0, onSelect, ...rest }) => {
|
||||
|
||||
return (
|
||||
<StyledSubmenu {...rest}>
|
||||
<StyledSubmenuItems ref={submenuItemsRef} role="list">
|
||||
{data.map((d) => {
|
||||
const isActive = d.id === currentItem.id;
|
||||
{isLoading ? (
|
||||
<LoaderSubmenu />
|
||||
) : (
|
||||
<>
|
||||
<StyledSubmenuItems ref={submenuItemsRef} role="list">
|
||||
{data.map((d) => {
|
||||
const isActive = d.id === currentItem.id;
|
||||
|
||||
return (
|
||||
<StyledSubmenuItem key={d.id} id={d.id} onClick={selectSubmenuItem}>
|
||||
<StyledSubmenuItemText>
|
||||
<Text
|
||||
color={isActive ? "#316DAA" : "#657077"}
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
truncate={false}
|
||||
return (
|
||||
<StyledSubmenuItem
|
||||
key={d.id}
|
||||
id={d.id}
|
||||
onClick={selectSubmenuItem}
|
||||
>
|
||||
{d.name}
|
||||
</Text>
|
||||
</StyledSubmenuItemText>
|
||||
<StyledSubmenuItemLabel color={isActive ? "#316DAA" : "none"} />
|
||||
</StyledSubmenuItem>
|
||||
);
|
||||
})}
|
||||
</StyledSubmenuItems>
|
||||
<StyledSubmenuBottomLine />
|
||||
|
||||
<StyledSubmenuItemText>
|
||||
<Text
|
||||
color={isActive ? "#316DAA" : "#657077"}
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
truncate={false}
|
||||
>
|
||||
{d.name}
|
||||
</Text>
|
||||
</StyledSubmenuItemText>
|
||||
<StyledSubmenuItemLabel
|
||||
color={isActive ? "#316DAA" : "none"}
|
||||
/>
|
||||
</StyledSubmenuItem>
|
||||
);
|
||||
})}
|
||||
</StyledSubmenuItems>
|
||||
<StyledSubmenuBottomLine />
|
||||
</>
|
||||
)}
|
||||
<StyledSubmenuContentWrapper>
|
||||
{currentItem.content}
|
||||
</StyledSubmenuContentWrapper>
|
||||
@ -108,6 +120,7 @@ Submenu.propTypes = {
|
||||
data: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
|
||||
startSelect: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
|
||||
onSelect: PropTypes.func,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Submenu;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import styled, { css } from "styled-components";
|
||||
import Loaders from "@appserver/common/components/Loaders";
|
||||
import { isTablet } from "react-device-detect";
|
||||
|
@ -2325,6 +2325,17 @@ const Base = {
|
||||
fill: gray,
|
||||
loadingFill: grayMid,
|
||||
|
||||
borderBottom: "1px solid #eceef1",
|
||||
borderTop: "1px solid #eceef1",
|
||||
externalLinkBackground: "#f8f9f9",
|
||||
externalLinkSvg: "#333333",
|
||||
|
||||
internalLinkBorder: "1px dashed #333333",
|
||||
|
||||
itemBorder: "1px dashed #333333",
|
||||
|
||||
itemOwnerColor: "rgb(163, 169, 174)",
|
||||
|
||||
dropdownColor: black,
|
||||
|
||||
loader: {
|
||||
|
@ -2335,6 +2335,17 @@ const Dark = {
|
||||
fill: grayMaxLight,
|
||||
loadingFill: grayMaxLight,
|
||||
|
||||
borderBottom: "1px solid #474747",
|
||||
borderTop: "1px solid #474747",
|
||||
externalLinkBackground: "#292929",
|
||||
externalLinkSvg: "#858585",
|
||||
|
||||
internalLinkBorder: "1px dashed #eeeeee",
|
||||
|
||||
itemBorder: "1px dashed #333333",
|
||||
|
||||
itemOwnerColor: "#858585",
|
||||
|
||||
dropdownColor: grayMaxLight,
|
||||
|
||||
loader: {
|
||||
|
@ -13,17 +13,17 @@ const ToggleIcon = ({ isChecked, isLoading }) => {
|
||||
isChecked ? "checked" : "notChecked",
|
||||
isLoading ? "isLoading" : "",
|
||||
]}
|
||||
width="30"
|
||||
height="18"
|
||||
viewBox="0 0 30 18"
|
||||
width="28"
|
||||
height="16"
|
||||
viewBox="0 0 28 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<motion.rect x="1" y="1" width="28" height="16" rx="8" />
|
||||
<motion.rect width="28" height="16" rx="8" />
|
||||
<motion.circle
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
cy="9"
|
||||
cy="8"
|
||||
variants={{
|
||||
isLoading: {
|
||||
r: [5, 6, 6],
|
||||
@ -35,8 +35,8 @@ const ToggleIcon = ({ isChecked, isLoading }) => {
|
||||
},
|
||||
},
|
||||
},
|
||||
checked: { cx: 21, r: 6 },
|
||||
notChecked: { cx: 9, r: 6 },
|
||||
checked: { cx: 20, r: 6 },
|
||||
notChecked: { cx: 8, r: 6 },
|
||||
}}
|
||||
/>
|
||||
</motion.svg>
|
||||
|
@ -68,8 +68,6 @@ const ToggleButtonContainer = styled.label`
|
||||
}
|
||||
|
||||
.toggle-button-text {
|
||||
margin-top: 2px;
|
||||
|
||||
color: ${(props) =>
|
||||
props.isDisabled
|
||||
? props.theme.text.disableColor
|
||||
|
@ -46,6 +46,7 @@ const ViewSelector = ({
|
||||
firstItem={indx === 0}
|
||||
lastItem={indx === lastIndx}
|
||||
key={value}
|
||||
name={`view-selector-name_${value}`}
|
||||
className="view-selector-icon"
|
||||
data-view={value}
|
||||
title={
|
||||
|
@ -42,6 +42,7 @@ const tests = isTranslation
|
||||
"./tests/context-menu_tests.js",
|
||||
"./tests/filter_tests.js",
|
||||
"./tests/catalog_tests.js",
|
||||
"./tests/duplicate-id_tests.js",
|
||||
];
|
||||
|
||||
const reportDir = isTranslation
|
||||
|
10
products/ASC.Files/Client/public/images/code.react.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_20597_65864)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.84646 0.979492L5.22299 14.5025L7.15485 15.0201L10.7783 1.49713L8.84646 0.979492ZM2.41419 7.99916L5.20702 5.20614L3.79276 3.79197L0.292868 7.2921C-0.0976332 7.68263 -0.0976212 8.31578 0.292895 8.7063L3.79278 12.2062L5.20699 10.7919L2.41419 7.99916ZM13.5857 8.00004L10.7928 5.20714L12.207 3.79292L15.707 7.29293C15.8945 7.48047 15.9999 7.73482 15.9999 8.00004C15.9999 8.26526 15.8945 8.51961 15.707 8.70715L12.2065 12.2076L10.7923 10.7934L13.5857 8.00004Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20597_65864">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 777 B |
3
products/ASC.Files/Client/public/images/copy.react.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.14502 -1.07443e-06L14.8481 -2.59613e-06C15.4812 -2.70681e-06 15.9962 0.515037 15.9962 1.14808L15.9962 9.85224C15.9962 10.4853 15.4812 11.0004 14.8481 11.0004L11.9896 11.0004L11.9896 6.03888C11.9896 4.82791 11.242 4.00369 10.031 4.00369L4.99694 4.00369L4.99694 1.14809C4.99693 0.515038 5.51194 -9.63738e-07 6.14502 -1.07443e-06ZM1.12973 4.99872L9.87024 4.99872C10.4932 4.99872 11 5.50551 11 6.12845L11 14.8703C11 15.4932 10.4932 16 9.87028 16L1.12973 16C0.50679 16 3.70837e-05 15.4932 2.6e-06 14.8703L1.07154e-06 6.12845C9.62618e-07 5.50551 0.506823 4.99872 1.12973 4.99872Z" fill="#A3A9AE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 747 B |
@ -21,8 +21,15 @@ export default function withFileActions(WrappedFileItem) {
|
||||
id !== -1 && onSelectItem({ id, isFolder });
|
||||
};
|
||||
|
||||
onFileContextClick = () => {
|
||||
const { onSelectItem } = this.props;
|
||||
const { id, isFolder } = this.props.item;
|
||||
|
||||
id !== -1 && onSelectItem({ id, isFolder }, true);
|
||||
};
|
||||
|
||||
onHideContextMenu = () => {
|
||||
//this.props.setBufferSelection(null);
|
||||
this.props.setBufferSelection(null);
|
||||
};
|
||||
|
||||
onDropZoneUpload = (files, uploadToFolder) => {
|
||||
@ -181,7 +188,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
return (
|
||||
<WrappedFileItem
|
||||
onContentFileSelect={this.onContentFileSelect}
|
||||
fileContextClick={this.fileContextClick}
|
||||
fileContextClick={this.onFileContextClick}
|
||||
onDrop={this.onDrop}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onFilesClick={this.onFilesClick}
|
||||
|
@ -11,6 +11,16 @@ export const StyledIcon = styled(IconButton)`
|
||||
${commonIconsStyles}
|
||||
`;
|
||||
|
||||
const StyledEditIcon = styled(IconButton)`
|
||||
${commonIconsStyles}
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.filesSection.rowView.editingIconColor};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -129,7 +139,7 @@ const Badges = ({
|
||||
/>
|
||||
)}
|
||||
{isEditing && (
|
||||
<StyledIcon
|
||||
<StyledEditIcon
|
||||
iconName={iconEdit}
|
||||
className="badge icons-group is-editing tablet-badge tablet-edit"
|
||||
size={sizeBadge}
|
||||
|
@ -111,7 +111,7 @@ class AddGroupsPanelComponent extends React.Component {
|
||||
const selectedOptions = [];
|
||||
shareDataItems.forEach((item) => {
|
||||
const { sharedTo } = item;
|
||||
if (!sharedTo.groups && !sharedTo.shareLink) {
|
||||
if (item?.isGroup) {
|
||||
selectedOptions.push({ id: sharedTo.id, key: sharedTo.id });
|
||||
}
|
||||
});
|
||||
|
@ -121,8 +121,11 @@ class AddUsersPanelComponent extends React.Component {
|
||||
const selectedOptions = [];
|
||||
shareDataItems.forEach((item) => {
|
||||
const { sharedTo } = item;
|
||||
if (sharedTo.groups) {
|
||||
const groups = sharedTo.groups.map((group) => group.id);
|
||||
|
||||
if (item.isUser) {
|
||||
const groups = sharedTo?.groups
|
||||
? sharedTo.groups.map((group) => group.id)
|
||||
: [];
|
||||
selectedOptions.push({ key: sharedTo.id, id: sharedTo.id, groups });
|
||||
}
|
||||
});
|
||||
@ -145,6 +148,7 @@ class AddUsersPanelComponent extends React.Component {
|
||||
: null;
|
||||
|
||||
//console.log("AddUsersPanel render");
|
||||
|
||||
return (
|
||||
<StyledAddUsersPanelPanel visible={visible}>
|
||||
<Backdrop
|
||||
|
@ -8,8 +8,9 @@ import toastr from "@appserver/components/toast/toastr";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import i18n from "./i18n";
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import StyledBody from "./StyledEmbeddingPanel";
|
||||
|
||||
const EmbeddingBody = ({ embeddingLink, t, theme }) => {
|
||||
const EmbeddingBody = ({ embeddingLink, t, theme, isPersonal }) => {
|
||||
const [size, setSize] = useState("auto");
|
||||
const [widthValue, setWidthValue] = useState("100%");
|
||||
const [heightValue, setHeightValue] = useState("100%");
|
||||
@ -61,68 +62,76 @@ const EmbeddingBody = ({ embeddingLink, t, theme }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="embedding-panel_body">
|
||||
<Text className="embedding-panel_text">{t("Common:Size")}:</Text>
|
||||
<div className="embedding-panel_links-container">
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className="embedding-panel_link"
|
||||
onClick={onSelectSizeMiddle}
|
||||
>
|
||||
600 x 800 px
|
||||
</Link>
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className="embedding-panel_link"
|
||||
onClick={onSelectSizeSmall}
|
||||
>
|
||||
400 x 600 px
|
||||
</Link>
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className="embedding-panel_link"
|
||||
onClick={onSelectSizeAuto}
|
||||
>
|
||||
{t("Auto")}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="embedding-panel_inputs-container">
|
||||
<div>
|
||||
<Text className="embedding-panel_text">{t("Width")}:</Text>
|
||||
<TextInput
|
||||
className="embedding-panel_input"
|
||||
value={widthValue}
|
||||
onChange={onChangeWidth}
|
||||
/>
|
||||
<StyledBody isPersonal={isPersonal}>
|
||||
<div className="embedding-panel_body">
|
||||
<Text className="embedding-panel_text">{t("Common:Size")}:</Text>
|
||||
<div className="embedding-panel_links-container">
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className={`embedding-panel_link ${
|
||||
size === "600x800" ? "embedding-panel_active-link" : ""
|
||||
}`}
|
||||
onClick={onSelectSizeMiddle}
|
||||
>
|
||||
600 x 800 px
|
||||
</Link>
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className={`embedding-panel_link ${
|
||||
size === "400x600" ? "embedding-panel_active-link" : ""
|
||||
}`}
|
||||
onClick={onSelectSizeSmall}
|
||||
>
|
||||
400 x 600 px
|
||||
</Link>
|
||||
<Link
|
||||
isHovered
|
||||
type="action"
|
||||
className={`embedding-panel_link ${
|
||||
size === "auto" ? "embedding-panel_active-link" : ""
|
||||
}`}
|
||||
onClick={onSelectSizeAuto}
|
||||
>
|
||||
{t("Auto")}
|
||||
</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="embedding-panel_text">{t("Height")}:</Text>
|
||||
<TextInput
|
||||
className="embedding-panel_input"
|
||||
value={heightValue}
|
||||
onChange={onChangeHeight}
|
||||
<div className="embedding-panel_inputs-container">
|
||||
<div>
|
||||
<Text className="embedding-panel_text">{t("Width")}:</Text>
|
||||
<TextInput
|
||||
className="embedding-panel_input"
|
||||
value={widthValue}
|
||||
onChange={onChangeWidth}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="embedding-panel_text">{t("Height")}:</Text>
|
||||
<TextInput
|
||||
className="embedding-panel_input"
|
||||
value={heightValue}
|
||||
onChange={onChangeHeight}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="embedding-panel_code-container">
|
||||
<Text className="embedding-panel_text">{t("EmbedCode")}:</Text>
|
||||
<IconButton
|
||||
className="embedding-panel_copy-icon"
|
||||
size="16"
|
||||
iconName="/static/images/copy.react.svg"
|
||||
// color={theme.filesPanels.embedding.iconColor}
|
||||
onClick={onCopyLink}
|
||||
/>
|
||||
<Textarea
|
||||
color={theme.filesPanels.embedding.textAreaColor}
|
||||
isReadOnly
|
||||
value={link}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="embedding-panel_code-container">
|
||||
<Text className="embedding-panel_text">{t("EmbedCode")}:</Text>
|
||||
<IconButton
|
||||
className="embedding-panel_copy-icon"
|
||||
size="16"
|
||||
iconName="/static/images/copy.react.svg"
|
||||
// color={theme.filesPanels.embedding.iconColor}
|
||||
onClick={onCopyLink}
|
||||
/>
|
||||
<Textarea
|
||||
color={theme.filesPanels.embedding.textAreaColor}
|
||||
isReadOnly
|
||||
value={link}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</StyledBody>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
const StyledBody = styled.div`
|
||||
.embedding-panel_body {
|
||||
padding: ${(props) => (props.isPersonal ? "0 4px 4px" : "0 16px")};
|
||||
}
|
||||
|
||||
.embedding-panel_links-container {
|
||||
display: flex;
|
||||
.embedding-panel_link {
|
||||
margin-right: 8px;
|
||||
|
||||
border: 1px solid #eceef1;
|
||||
border-radius: 16px;
|
||||
line-height: 20px;
|
||||
padding: 3px 15px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.embedding-panel_active-link {
|
||||
background: #265a8f;
|
||||
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_inputs-container {
|
||||
display: flex;
|
||||
margin-top: 16px;
|
||||
|
||||
.embedding-panel_input {
|
||||
margin-right: 8px;
|
||||
width: 94px;
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_code-container {
|
||||
margin-top: 16px;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.embedding-panel_text {
|
||||
padding: 0px 0 4px 0;
|
||||
}
|
||||
|
||||
.embedding-panel_copy-icon {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
margin: 8px;
|
||||
right: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledBody;
|
@ -7,12 +7,9 @@ import Aside from "@appserver/components/aside";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import { withTranslation, I18nextProvider } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
import {
|
||||
StyledEmbeddingPanel,
|
||||
StyledContent,
|
||||
StyledHeaderContent,
|
||||
StyledBody,
|
||||
} from "../StyledPanels";
|
||||
import { StyledEmbeddingPanel, StyledContent } from "../StyledPanels";
|
||||
|
||||
import { StyledHeaderContent } from "../SharingPanel/StyledSharingPanel";
|
||||
|
||||
import EmbeddingBody from "./EmbeddingBody";
|
||||
|
||||
@ -25,7 +22,7 @@ class EmbeddingPanelComponent extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { visible, t, theme } = this.props;
|
||||
const { visible, t, theme, embeddingLink } = this.props;
|
||||
const zIndex = 310;
|
||||
|
||||
//console.log("EmbeddingPanel render");
|
||||
@ -39,7 +36,7 @@ class EmbeddingPanelComponent extends React.Component {
|
||||
/>
|
||||
<Aside className="header_aside-panel">
|
||||
<StyledContent>
|
||||
<StyledHeaderContent>
|
||||
<StyledHeaderContent isEmbedding={true}>
|
||||
<IconButton
|
||||
size="16"
|
||||
iconName="/static/images/arrow.path.react.svg"
|
||||
@ -54,9 +51,8 @@ class EmbeddingPanelComponent extends React.Component {
|
||||
{t("EmbeddingDocument")}
|
||||
</Heading>
|
||||
</StyledHeaderContent>
|
||||
<StyledBody>
|
||||
<EmbeddingBody theme={theme} />
|
||||
</StyledBody>
|
||||
|
||||
<EmbeddingBody embeddingLink={embeddingLink} theme={theme} />
|
||||
</StyledContent>
|
||||
</Aside>
|
||||
</StyledEmbeddingPanel>
|
||||
|
@ -2,138 +2,276 @@ import React from "react";
|
||||
import ComboBox from "@appserver/components/combobox";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import AccessRightSelect from "@appserver/components/access-right-select";
|
||||
import { getAccessIcon } from "../../../helpers/files-helpers";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const {
|
||||
FullAccess,
|
||||
CustomFilter,
|
||||
Review,
|
||||
FormFilling,
|
||||
Comment,
|
||||
ReadOnly,
|
||||
DenyAccess,
|
||||
} = ShareAccessRights;
|
||||
|
||||
const AccessComboBox = (props) => {
|
||||
const {
|
||||
access,
|
||||
accessOptions,
|
||||
directionY,
|
||||
directionX,
|
||||
isDisabled,
|
||||
itemId,
|
||||
onAccessChange,
|
||||
t,
|
||||
theme,
|
||||
arrowIconColor,
|
||||
disableLink,
|
||||
fixedDirection,
|
||||
canDelete,
|
||||
onRemoveUserClick,
|
||||
isExternalLink,
|
||||
isDefaultMode,
|
||||
} = props;
|
||||
const {
|
||||
FullAccess,
|
||||
CustomFilter,
|
||||
Review,
|
||||
FormFilling,
|
||||
Comment,
|
||||
ReadOnly,
|
||||
DenyAccess,
|
||||
} = ShareAccessRights;
|
||||
|
||||
const advancedOptions = (
|
||||
<>
|
||||
{accessOptions.includes("FullAccess") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("Common:FullAccess")}
|
||||
icon="/static/images/access.edit.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={FullAccess}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
const [isLoading, setIsLoading] = React.useState(true);
|
||||
const [availableOptions, setAvailableOptions] = React.useState([]);
|
||||
const [selectedOption, setSelectedOption] = React.useState(null);
|
||||
|
||||
{accessOptions.includes("FilterEditing") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("CustomFilter")}
|
||||
icon="/static/images/custom.filter.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={CustomFilter}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
const ref = React.useRef(null);
|
||||
|
||||
{accessOptions.includes("Review") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("Common:Review")}
|
||||
icon="/static/images/access.review.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={Review}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
const onSelect = React.useCallback(
|
||||
(e) => {
|
||||
const access = +e.target.dataset.access;
|
||||
|
||||
{accessOptions.includes("FormFilling") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("FormFilling")}
|
||||
icon="/static/images/access.form.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={FormFilling}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
if (access) {
|
||||
const item = availableOptions.find((option) => {
|
||||
return option.dataAccess === access;
|
||||
});
|
||||
|
||||
{accessOptions.includes("Comment") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("Comment")}
|
||||
icon="/static/images/access.comment.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={Comment}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
setSelectedOption(item);
|
||||
|
||||
{accessOptions.includes("ReadOnly") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("ReadOnly")}
|
||||
icon="/static/images/eye.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={ReadOnly}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
{accessOptions.includes("DenyAccess") && (
|
||||
<DropDownItem
|
||||
theme={theme}
|
||||
label={t("DenyAccess")}
|
||||
icon="/static/images/access.none.react.svg"
|
||||
data-id={itemId}
|
||||
data-access={DenyAccess}
|
||||
onClick={onAccessChange}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
onAccessChange && onAccessChange(e);
|
||||
} else {
|
||||
onRemoveUserClick && onRemoveUserClick(e);
|
||||
}
|
||||
},
|
||||
[availableOptions, onAccessChange, onRemoveUserClick]
|
||||
);
|
||||
|
||||
const accessRights = disableLink ? ReadOnly : access;
|
||||
const accessIconUrl = getAccessIcon(accessRights);
|
||||
const selectedOption = arrowIconColor
|
||||
? { key: 0, arrowIconColor }
|
||||
: { key: 0 };
|
||||
React.useEffect(() => {
|
||||
const accessRights = disableLink ? ReadOnly : access;
|
||||
|
||||
return (
|
||||
const newAvailableOptions = [];
|
||||
accessOptions.forEach((option) => {
|
||||
switch (option) {
|
||||
case "FullAccess":
|
||||
const accessItem = {
|
||||
key: FullAccess,
|
||||
title: t("Common:FullAccess"),
|
||||
label: t("Common:FullAccess"),
|
||||
icon: "/static/images/access.edit.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: FullAccess,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(accessItem);
|
||||
|
||||
if (accessRights === FullAccess) {
|
||||
setSelectedOption(accessItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "FilterEditing":
|
||||
const filterItem = {
|
||||
key: CustomFilter,
|
||||
title: t("CustomFilter"),
|
||||
label: t("CustomFilter"),
|
||||
icon: "/static/images/custom.filter.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: CustomFilter,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(filterItem);
|
||||
|
||||
if (accessRights === CustomFilter) {
|
||||
setSelectedOption(filterItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Review":
|
||||
const reviewItem = {
|
||||
key: Review,
|
||||
title: t("Common:Review"),
|
||||
label: t("Common:Review"),
|
||||
icon: "/static/images/access.review.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: Review,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(reviewItem);
|
||||
|
||||
if (accessRights === Review) {
|
||||
setSelectedOption(reviewItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "FormFilling":
|
||||
const formItem = {
|
||||
key: FormFilling,
|
||||
title: t("FormFilling"),
|
||||
label: t("FormFilling"),
|
||||
icon: "/static/images/access.form.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: FormFilling,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(formItem);
|
||||
|
||||
if (accessRights === FormFilling) {
|
||||
setSelectedOption(formItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Comment":
|
||||
const commentItem = {
|
||||
key: Comment,
|
||||
title: t("Comment"),
|
||||
label: t("Comment"),
|
||||
icon: "/static/images/access.comment.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: Comment,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(commentItem);
|
||||
|
||||
if (accessRights === Comment) {
|
||||
setSelectedOption(commentItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "ReadOnly":
|
||||
const readItem = {
|
||||
key: ReadOnly,
|
||||
title: t("ReadOnly"),
|
||||
label: t("ReadOnly"),
|
||||
icon: "/static/images/eye.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: ReadOnly,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(readItem);
|
||||
|
||||
if (accessRights === ReadOnly) {
|
||||
setSelectedOption(readItem);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "DenyAccess":
|
||||
const denyItem = {
|
||||
key: DenyAccess,
|
||||
title: t("DenyAccess"),
|
||||
label: t("DenyAccess"),
|
||||
icon: "/static/images/access.none.react.svg",
|
||||
itemId: itemId,
|
||||
dataAccess: DenyAccess,
|
||||
};
|
||||
|
||||
newAvailableOptions.push(denyItem);
|
||||
|
||||
if (accessRights === DenyAccess) {
|
||||
setSelectedOption(denyItem);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (canDelete) {
|
||||
newAvailableOptions.push({ key: "separator", isSeparator: true });
|
||||
newAvailableOptions.push({
|
||||
key: "delete",
|
||||
title: t("Common:Delete"),
|
||||
label: t("Common:Delete"),
|
||||
icon: "/static/images/delete.react.svg",
|
||||
dataFor: itemId,
|
||||
onClick: onRemoveUserClick,
|
||||
});
|
||||
}
|
||||
|
||||
setAvailableOptions(newAvailableOptions);
|
||||
if (newAvailableOptions.length > 0) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [
|
||||
access,
|
||||
disableLink,
|
||||
accessOptions,
|
||||
onRemoveUserClick,
|
||||
itemId,
|
||||
canDelete,
|
||||
]);
|
||||
|
||||
const renderAdvancedOption = React.useCallback(() => {
|
||||
return (
|
||||
<>
|
||||
{availableOptions?.map((option) => (
|
||||
<DropDownItem
|
||||
key={option.key}
|
||||
label={option.label}
|
||||
icon={option.icon}
|
||||
data-id={option.itemId}
|
||||
data-access={option.dataAccess}
|
||||
data-for={option.dataFor}
|
||||
onClick={onSelect}
|
||||
isSeparator={option.isSeparator}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}, [availableOptions, onSelect]);
|
||||
|
||||
const advancedOptions = renderAdvancedOption();
|
||||
|
||||
return isLoading ? (
|
||||
<> </>
|
||||
) : isExternalLink ? (
|
||||
<AccessRightSelect
|
||||
options={[]}
|
||||
selectedOption={selectedOption}
|
||||
advancedOptions={advancedOptions}
|
||||
/>
|
||||
) : (
|
||||
<ComboBox
|
||||
theme={theme}
|
||||
advancedOptions={advancedOptions}
|
||||
options={[]}
|
||||
selectedOption={selectedOption}
|
||||
selectedOption={{}}
|
||||
size="content"
|
||||
className="panel_combo-box"
|
||||
scaled={false}
|
||||
directionX={directionX}
|
||||
directionY={directionY}
|
||||
disableIconClick={false}
|
||||
isDisabled={isDisabled}
|
||||
isDefaultMode={false}
|
||||
isDefaultMode={isDefaultMode}
|
||||
ref={ref}
|
||||
forwardRef={ref}
|
||||
fixedDirection={fixedDirection}
|
||||
>
|
||||
<ReactSVG src={accessIconUrl} className="sharing-access-combo-box-icon" />
|
||||
<ReactSVG
|
||||
src={selectedOption.icon}
|
||||
className="sharing-access-combo-box-icon"
|
||||
/>
|
||||
</ComboBox>
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessComboBox;
|
||||
export default React.memo(AccessComboBox);
|
||||
|
@ -0,0 +1,290 @@
|
||||
import React from "react";
|
||||
|
||||
import { VariableSizeList as List } from "react-window";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
import CustomScrollbarsVirtualList from "@appserver/components/scrollbar/custom-scrollbars-virtual-list";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
|
||||
import ExternalLink from "./ExternalLink";
|
||||
import InternalLink from "./InternalLink";
|
||||
import Item from "./Item";
|
||||
|
||||
import { StyledBodyContent } from "./StyledSharingPanel";
|
||||
|
||||
const Row = React.memo(({ data, index, style }) => {
|
||||
const {
|
||||
isMyId,
|
||||
externalAccessOptions,
|
||||
onChangeItemAccess,
|
||||
canShareOwnerChange,
|
||||
onShowChangeOwnerPanel,
|
||||
onRemoveUserClick,
|
||||
t,
|
||||
items,
|
||||
selection,
|
||||
onShowEmbeddingPanel,
|
||||
externalLinkOpen,
|
||||
onToggleExternalLinkOpen,
|
||||
} = data;
|
||||
|
||||
if (items === undefined) return;
|
||||
|
||||
if (!!items[index]?.sharedTo?.shareLink) {
|
||||
return (
|
||||
<ExternalLink
|
||||
t={t}
|
||||
isPersonal={false}
|
||||
selection={selection}
|
||||
externalItem={items[index]}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
onChangeItemAccess={onChangeItemAccess}
|
||||
onShowEmbeddingPanel={onShowEmbeddingPanel}
|
||||
isOpen={externalLinkOpen}
|
||||
onToggleLink={onToggleExternalLinkOpen}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!!items[index]?.internalLink) {
|
||||
return (
|
||||
<InternalLink
|
||||
t={t}
|
||||
internalLink={items[index]?.internalLink}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Item
|
||||
t={t}
|
||||
item={items[index]}
|
||||
isMyId={isMyId}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
onChangeItemAccess={onChangeItemAccess}
|
||||
canShareOwnerChange={canShareOwnerChange(items[index])}
|
||||
onShowChangeOwnerPanel={onShowChangeOwnerPanel}
|
||||
onRemoveUserClick={onRemoveUserClick}
|
||||
isSeparator={items[index].isSeparator}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const Body = ({
|
||||
t,
|
||||
selection,
|
||||
externalItem,
|
||||
externalAccessOptions,
|
||||
onChangeItemAccess,
|
||||
onShowEmbeddingPanel,
|
||||
onToggleLink,
|
||||
internalLink,
|
||||
owner = {},
|
||||
isMyId,
|
||||
onShowChangeOwnerPanel,
|
||||
onRemoveUserClick,
|
||||
canShareOwnerChange,
|
||||
shareGroups = [],
|
||||
shareUsers = [],
|
||||
isPersonal,
|
||||
isShared,
|
||||
}) => {
|
||||
const [externalLinkVisible, setExternalLinkVisible] = React.useState(false);
|
||||
const [externalLinkOpen, setExternalLinkOpen] = React.useState(isShared);
|
||||
const [itemList, setItemList] = React.useState([]);
|
||||
const [listData, setListData] = React.useState({});
|
||||
|
||||
const bodyRef = React.useRef();
|
||||
const listRef = React.useRef();
|
||||
|
||||
const onToggleExternalLinkOpen = React.useCallback(() => {
|
||||
setExternalLinkOpen((oldState) => !oldState);
|
||||
onToggleLink && onToggleLink(externalItem);
|
||||
}, [externalItem, onToggleLink]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setExternalLinkVisible(
|
||||
selection?.length === 1 && !!externalItem?.sharedTo?.shareLink
|
||||
);
|
||||
setExternalLinkOpen(externalItem?.access !== ShareAccessRights.DenyAccess);
|
||||
}, [externalItem, selection]);
|
||||
|
||||
const getItemSize = React.useCallback(
|
||||
(index) => {
|
||||
if (itemList.length === 0) return;
|
||||
if (itemList[index].isSeparator) return 16;
|
||||
if (itemList[index]?.internalLink) return 62;
|
||||
if (!!itemList[index]?.sharedTo.shareLink) {
|
||||
return externalLinkOpen ? 145 : 63;
|
||||
}
|
||||
return 48;
|
||||
},
|
||||
[itemList, externalLinkOpen]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isPersonal) {
|
||||
const items = [];
|
||||
|
||||
if (!!owner) {
|
||||
items.push(owner);
|
||||
items.push({ key: "separator-1", isSeparator: true });
|
||||
}
|
||||
|
||||
if (shareGroups.length > 0) {
|
||||
items.push(...shareGroups);
|
||||
items.push({ key: "separator-2", isSeparator: true });
|
||||
}
|
||||
|
||||
if (shareUsers.length > 0) {
|
||||
items.push(...shareUsers);
|
||||
}
|
||||
|
||||
const newListData = {
|
||||
height: bodyRef?.current?.offsetHeight,
|
||||
width: "auto",
|
||||
data: {
|
||||
items: items,
|
||||
isMyId: isMyId,
|
||||
externalAccessOptions: externalAccessOptions,
|
||||
onChangeItemAccess: onChangeItemAccess,
|
||||
canShareOwnerChange: canShareOwnerChange,
|
||||
onShowChangeOwnerPanel: onShowChangeOwnerPanel,
|
||||
onRemoveUserClick: onRemoveUserClick,
|
||||
t: t,
|
||||
},
|
||||
};
|
||||
|
||||
if (isMobileOnly) {
|
||||
if (!!internalLink) {
|
||||
items.unshift({ internalLink: internalLink });
|
||||
}
|
||||
if (selection?.length === 1 && !!externalItem?.sharedTo?.shareLink) {
|
||||
items.unshift(externalItem);
|
||||
}
|
||||
|
||||
newListData.data.items = items;
|
||||
newListData.data.selection = selection;
|
||||
newListData.data.onShowEmbeddingPanel = onShowEmbeddingPanel;
|
||||
newListData.data.externalLinkOpen = externalLinkOpen;
|
||||
newListData.data.onToggleExternalLinkOpen = onToggleExternalLinkOpen;
|
||||
}
|
||||
|
||||
setItemList(items);
|
||||
setListData(newListData);
|
||||
}
|
||||
}, [
|
||||
isPersonal,
|
||||
bodyRef.current,
|
||||
owner,
|
||||
shareGroups,
|
||||
shareUsers,
|
||||
isMyId,
|
||||
externalAccessOptions,
|
||||
onChangeItemAccess,
|
||||
canShareOwnerChange,
|
||||
onShowChangeOwnerPanel,
|
||||
onRemoveUserClick,
|
||||
t,
|
||||
externalItem,
|
||||
internalLink,
|
||||
selection,
|
||||
onShowEmbeddingPanel,
|
||||
externalLinkOpen,
|
||||
onToggleExternalLinkOpen,
|
||||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isPersonal) {
|
||||
listRef?.current?.resetAfterIndex(0);
|
||||
}
|
||||
}, [externalLinkOpen, isPersonal]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isPersonal ? (
|
||||
<ExternalLink
|
||||
t={t}
|
||||
isPersonal={isPersonal}
|
||||
selection={selection}
|
||||
externalItem={externalItem}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
onChangeItemAccess={onChangeItemAccess}
|
||||
onShowEmbeddingPanel={onShowEmbeddingPanel}
|
||||
isOpen={externalLinkOpen}
|
||||
onToggleLink={onToggleExternalLinkOpen}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{!isMobileOnly ? (
|
||||
<StyledBodyContent
|
||||
externalLinkOpen={externalLinkOpen}
|
||||
externalLinkVisible={externalLinkVisible}
|
||||
>
|
||||
{externalLinkVisible && (
|
||||
<ExternalLink
|
||||
t={t}
|
||||
isPersonal={isPersonal}
|
||||
selection={selection}
|
||||
externalItem={externalItem}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
onChangeItemAccess={onChangeItemAccess}
|
||||
onShowEmbeddingPanel={onShowEmbeddingPanel}
|
||||
isOpen={externalLinkOpen}
|
||||
onToggleLink={onToggleExternalLinkOpen}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!!internalLink && (
|
||||
<InternalLink t={t} internalLink={internalLink} />
|
||||
)}
|
||||
|
||||
<div className="body-scroll-content-sharing-panel" ref={bodyRef}>
|
||||
{listData?.height && listData?.data?.items?.length > 0 && (
|
||||
<List
|
||||
height={listData.height}
|
||||
width={listData.width}
|
||||
itemCount={itemList.length}
|
||||
itemSize={getItemSize}
|
||||
itemData={listData.data}
|
||||
outerElementType={CustomScrollbarsVirtualList}
|
||||
>
|
||||
{Row}
|
||||
</List>
|
||||
)}
|
||||
</div>
|
||||
</StyledBodyContent>
|
||||
) : (
|
||||
<>
|
||||
<StyledBodyContent>
|
||||
<div
|
||||
className="body-scroll-content-sharing-panel"
|
||||
ref={bodyRef}
|
||||
>
|
||||
{listData?.height && listData?.data?.items?.length > 0 && (
|
||||
<List
|
||||
height={listData.height}
|
||||
width={listData.width}
|
||||
itemCount={itemList.length}
|
||||
itemSize={getItemSize}
|
||||
itemData={listData.data}
|
||||
outerElementType={CustomScrollbarsVirtualList}
|
||||
ref={listRef}
|
||||
>
|
||||
{Row}
|
||||
</List>
|
||||
)}
|
||||
</div>
|
||||
</StyledBodyContent>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Body);
|
@ -0,0 +1,202 @@
|
||||
import React from "react";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
import { objectToGetParams } from "@appserver/common/utils";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import ToggleButton from "@appserver/components/toggle-button";
|
||||
import InputBlock from "@appserver/components/input-block";
|
||||
import Button from "@appserver/components/button";
|
||||
|
||||
import AccessComboBox from "./AccessComboBox";
|
||||
|
||||
import ShareIcon from "../../../../../../../public/images/share.react.svg";
|
||||
import CodeIcon from "../../../../../../../public/images/code.react.svg";
|
||||
|
||||
import { StyledExternalLink } from "./StyledSharingPanel";
|
||||
import Text from "@appserver/components/text";
|
||||
import DropDownContainer from "@appserver/components/drop-down";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
const ExternalLink = ({
|
||||
t,
|
||||
selection,
|
||||
externalItem,
|
||||
externalAccessOptions,
|
||||
onToggleLink,
|
||||
onShowEmbeddingPanel,
|
||||
isOpen,
|
||||
onChangeItemAccess,
|
||||
style,
|
||||
isPersonal,
|
||||
}) => {
|
||||
const [shareLink, setShareLink] = React.useState("");
|
||||
const [shareActionOpen, setShareActionOpen] = React.useState(false);
|
||||
|
||||
const ref = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
setShareLink(externalItem.sharedTo.shareLink);
|
||||
}, [externalItem]);
|
||||
|
||||
const onToggleShareAction = React.useCallback(() => {
|
||||
setShareActionOpen((val) => !val);
|
||||
}, [ref.current]);
|
||||
|
||||
const closeShareAction = React.useCallback(
|
||||
(e) => {
|
||||
if (ref.current.contains(e.target)) return;
|
||||
setShareActionOpen((val) => !val);
|
||||
},
|
||||
[ref.current]
|
||||
);
|
||||
|
||||
const onCopyLinkAction = React.useCallback(() => {
|
||||
toastr.success(t("Translations:LinkCopySuccess"));
|
||||
copy(shareLink);
|
||||
}, [shareLink]);
|
||||
|
||||
const onShowEmbeddingPanelAction = React.useCallback(() => {
|
||||
onShowEmbeddingPanel && onShowEmbeddingPanel();
|
||||
}, [onShowEmbeddingPanel]);
|
||||
|
||||
const onShareEmail = React.useCallback(() => {
|
||||
const itemName = selection.title ? selection.title : selection[0].title;
|
||||
const subject = t("ShareEmailSubject", { itemName });
|
||||
const body = t("ShareEmailBody", { itemName, shareLink });
|
||||
|
||||
const mailtoLink =
|
||||
"mailto:" +
|
||||
objectToGetParams({
|
||||
subject,
|
||||
body,
|
||||
});
|
||||
window.open(mailtoLink, "_self");
|
||||
|
||||
onToggleShareAction();
|
||||
}, [onToggleShareAction, selection, t, shareLink]);
|
||||
|
||||
// const onShareFacebook = () => {
|
||||
// const facebookLink =
|
||||
// "https://www.facebook.com/sharer/sharer.php" +
|
||||
// objectToGetParams({
|
||||
// u: shareLink,
|
||||
// t: selection.title ? selection.title : selection[0].title,
|
||||
// });
|
||||
|
||||
// window.open(facebookLink);
|
||||
// };
|
||||
|
||||
const onShareTwitter = React.useCallback(() => {
|
||||
const twitterLink =
|
||||
"https://twitter.com/intent/tweet" +
|
||||
objectToGetParams({
|
||||
text: shareLink,
|
||||
});
|
||||
|
||||
window.open(twitterLink, "", "width=1000,height=670");
|
||||
onToggleShareAction();
|
||||
}, [onToggleShareAction, shareLink]);
|
||||
|
||||
const options = [
|
||||
{
|
||||
key: "linkItem_0",
|
||||
label: `${t("ShareVia")} e-mail`,
|
||||
onClick: onShareEmail,
|
||||
},
|
||||
// {
|
||||
// key: "linkItem_1",
|
||||
// label: `${t("ShareVia")} Facebook`,
|
||||
// onClick: this.onShareFacebook,
|
||||
// },
|
||||
{
|
||||
key: "linkItem_2",
|
||||
label: `${t("ShareVia")} Twitter`,
|
||||
onClick: onShareTwitter,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<StyledExternalLink isPersonal={isPersonal} isOpen={isOpen} style={style}>
|
||||
<div className="external-link__base-line">
|
||||
<Text className="external-link__text" noSelect={true} truncate={true}>
|
||||
{t("ExternalLink")}
|
||||
</Text>
|
||||
<ToggleButton
|
||||
className="external-link__toggler"
|
||||
isChecked={isOpen}
|
||||
onChange={onToggleLink}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isOpen && (
|
||||
<>
|
||||
<div className="external-link__checked">
|
||||
<InputBlock
|
||||
className="external-link__input-link"
|
||||
scale={true}
|
||||
isReadOnly={true}
|
||||
placeholder={shareLink}
|
||||
isDisabled={true}
|
||||
>
|
||||
<div ref={ref} className="external-link__buttons">
|
||||
<CodeIcon
|
||||
className="external-link__code-icon"
|
||||
onClick={onShowEmbeddingPanelAction}
|
||||
/>
|
||||
<ShareIcon
|
||||
className="external-link__share-icon"
|
||||
onClick={onToggleShareAction}
|
||||
/>
|
||||
<DropDownContainer
|
||||
className="external-link__share-dropdown"
|
||||
open={shareActionOpen}
|
||||
clickOutsideAction={closeShareAction}
|
||||
withBackdrop={false}
|
||||
isDefaultMode={false}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<DropDownItem
|
||||
key={option.key}
|
||||
label={option.label}
|
||||
onClick={option.onClick}
|
||||
/>
|
||||
))}
|
||||
</DropDownContainer>
|
||||
</div>
|
||||
</InputBlock>
|
||||
|
||||
<Button
|
||||
className={"external-link__copy"}
|
||||
label={t("Translations:Copy")}
|
||||
size={"small"}
|
||||
onClick={onCopyLinkAction}
|
||||
/>
|
||||
</div>
|
||||
<div className="external-link__access-rights">
|
||||
<Text className="external-link__access-rights_text">
|
||||
Access rights:
|
||||
</Text>
|
||||
<AccessComboBox
|
||||
t={t}
|
||||
access={externalItem?.access}
|
||||
directionX="right"
|
||||
directionY="bottom"
|
||||
accessOptions={externalAccessOptions}
|
||||
onAccessChange={onChangeItemAccess}
|
||||
itemId={externalItem?.sharedTo?.id}
|
||||
isDisabled={false}
|
||||
disableLink={false}
|
||||
isExternalLink={true}
|
||||
isDefaultMode={false}
|
||||
fixedDirection={true}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</StyledExternalLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(ExternalLink);
|
@ -0,0 +1,49 @@
|
||||
import React from "react";
|
||||
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import Button from "@appserver/components/button";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
|
||||
import { StyledFooterContent } from "./StyledSharingPanel";
|
||||
|
||||
const Footer = ({
|
||||
t,
|
||||
isPersonal,
|
||||
message,
|
||||
onChangeMessage,
|
||||
isNotifyUsers,
|
||||
onNotifyUsersChange,
|
||||
onSaveClick,
|
||||
}) => {
|
||||
return (
|
||||
<StyledFooterContent>
|
||||
{isNotifyUsers && (
|
||||
<Textarea
|
||||
className="sharing_panel-notification"
|
||||
placeholder={t("AddShareMessage")}
|
||||
onChange={onChangeMessage}
|
||||
value={message}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isPersonal && (
|
||||
<Checkbox
|
||||
isChecked={isNotifyUsers}
|
||||
label={t("Notify users")}
|
||||
onChange={onNotifyUsersChange}
|
||||
className="sharing_panel-checkbox"
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
className="sharing_panel-button"
|
||||
label={t("Common:SaveButton")}
|
||||
scale={true}
|
||||
size={"normal"}
|
||||
primary
|
||||
onClick={onSaveClick}
|
||||
/>
|
||||
</StyledFooterContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Footer);
|
@ -0,0 +1,109 @@
|
||||
import React from "react";
|
||||
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Heading from "@appserver/components/heading";
|
||||
import DropDown from "@appserver/components/drop-down";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
import { StyledHeaderContent } from "./StyledSharingPanel";
|
||||
|
||||
const Header = ({
|
||||
t,
|
||||
isPersonal,
|
||||
isEncrypted,
|
||||
uploadPanelVisible,
|
||||
onShowUsersPanel,
|
||||
onShowGroupsPanel,
|
||||
onClose,
|
||||
label,
|
||||
}) => {
|
||||
const [showActionPanel, setShowActionPanel] = React.useState(false);
|
||||
|
||||
const ref = React.useRef(null);
|
||||
|
||||
const onPlusClick = React.useCallback(() => {
|
||||
setShowActionPanel((val) => !val);
|
||||
}, []);
|
||||
|
||||
const onCloseActionPanel = React.useCallback(
|
||||
(e) => {
|
||||
if (ref.current.contains(e.target)) return;
|
||||
setShowActionPanel((val) => !val);
|
||||
},
|
||||
[ref.current]
|
||||
);
|
||||
|
||||
const onShowUsersPanelAction = React.useCallback(() => {
|
||||
setShowActionPanel(false);
|
||||
onShowUsersPanel && onShowUsersPanel();
|
||||
}, [onShowUsersPanel]);
|
||||
|
||||
const onShowGroupsPanelAction = React.useCallback(() => {
|
||||
setShowActionPanel(false);
|
||||
onShowGroupsPanel && onShowGroupsPanel();
|
||||
}, [onShowGroupsPanel]);
|
||||
|
||||
return (
|
||||
<StyledHeaderContent
|
||||
isPersonal={isPersonal}
|
||||
className="sharing_panel-header-container"
|
||||
>
|
||||
<div className="sharing_panel-header-info">
|
||||
{uploadPanelVisible && (
|
||||
<IconButton
|
||||
size="15px"
|
||||
iconName="/static/images/arrow.path.react.svg"
|
||||
className="sharing_panel-arrow"
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
<Heading
|
||||
className="sharing_panel-header"
|
||||
size="medium"
|
||||
truncate={!isPersonal}
|
||||
style={{ fontWeight: 700 }}
|
||||
>
|
||||
{uploadPanelVisible && label && isPersonal
|
||||
? label
|
||||
: t("SharingSettingsTitle")}
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
{!isPersonal && (
|
||||
<div className="sharing_panel-icons-container">
|
||||
<div ref={ref} className="sharing_panel-drop-down-wrapper">
|
||||
<IconButton
|
||||
size="15"
|
||||
iconName="/static/images/actions.header.touch.react.svg"
|
||||
className="sharing_panel-plus-icon"
|
||||
onClick={onPlusClick}
|
||||
/>
|
||||
|
||||
<DropDown
|
||||
forwardedRef={ref}
|
||||
directionX="right"
|
||||
className="sharing_panel-drop-down"
|
||||
open={showActionPanel}
|
||||
manualY="30px"
|
||||
clickOutsideAction={onCloseActionPanel}
|
||||
>
|
||||
<DropDownItem
|
||||
label={t("LinkText")}
|
||||
onClick={onShowUsersPanelAction}
|
||||
/>
|
||||
|
||||
{!isEncrypted && (
|
||||
<DropDownItem
|
||||
label={t("AddGroupsForSharingButton")}
|
||||
onClick={onShowGroupsPanelAction}
|
||||
/>
|
||||
)}
|
||||
</DropDown>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</StyledHeaderContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Header);
|
@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import Text from "@appserver/components/text";
|
||||
|
||||
import { StyledInternalLink } from "./StyledSharingPanel";
|
||||
|
||||
const InternalLink = ({ t, internalLink, style }) => {
|
||||
const onCopyInternalLinkAction = React.useCallback(() => {
|
||||
copy(internalLink);
|
||||
toastr.success(t("Translations:LinkCopySuccess"));
|
||||
}, [internalLink]);
|
||||
|
||||
return (
|
||||
<StyledInternalLink style={style}>
|
||||
<Text className={"internal-link__link-text"}>{t("InternalLink")}</Text>
|
||||
<Text
|
||||
className={"internal-link__copy-text"}
|
||||
onClick={onCopyInternalLinkAction}
|
||||
>
|
||||
{t("Translations:Copy")}
|
||||
</Text>
|
||||
</StyledInternalLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(InternalLink);
|
@ -0,0 +1,86 @@
|
||||
import React from "react";
|
||||
|
||||
import Avatar from "@appserver/components/avatar";
|
||||
import Text from "@appserver/components/text";
|
||||
import AccessComboBox from "./AccessComboBox";
|
||||
import { StyledItem } from "./StyledSharingPanel";
|
||||
|
||||
const Item = ({
|
||||
t,
|
||||
item,
|
||||
canShareOwnerChange,
|
||||
externalAccessOptions,
|
||||
onChangeItemAccess,
|
||||
onShowChangeOwnerPanel,
|
||||
onRemoveUserClick,
|
||||
isMyId,
|
||||
isSeparator,
|
||||
style,
|
||||
}) => {
|
||||
const onShowChangeOwnerPanelAction = React.useCallback(() => {
|
||||
onShowChangeOwnerPanel && onShowChangeOwnerPanel();
|
||||
}, [onShowChangeOwnerPanel]);
|
||||
|
||||
let itemName = "";
|
||||
let avatarUrl = "";
|
||||
|
||||
if (!isSeparator) {
|
||||
itemName =
|
||||
item.sharedTo.id === isMyId
|
||||
? t("Common:MeLabel")
|
||||
: !!item.sharedTo.displayName
|
||||
? item.sharedTo.displayName
|
||||
: !!item.sharedTo.name
|
||||
? item.sharedTo.name
|
||||
: item.sharedTo.label;
|
||||
|
||||
avatarUrl = !!item.avatarSmall ? item.avatarSmall : item.avatarUrl;
|
||||
}
|
||||
|
||||
return isSeparator ? (
|
||||
<StyledItem style={style} isSeparator={isSeparator} />
|
||||
) : (
|
||||
<StyledItem style={style}>
|
||||
<div className="item__info-block">
|
||||
<Avatar
|
||||
className="info-block__avatar"
|
||||
size={"min"}
|
||||
role={"user"}
|
||||
source={avatarUrl}
|
||||
userName={itemName}
|
||||
/>
|
||||
<Text className="info-block__text">{itemName}</Text>
|
||||
</div>
|
||||
{item.isOwner ? (
|
||||
canShareOwnerChange ? (
|
||||
<Text
|
||||
className="item__change-owner"
|
||||
onClick={onShowChangeOwnerPanelAction}
|
||||
>
|
||||
{t("ChangeOwnerPanel:ChangeOwner").replace("()", "")}
|
||||
</Text>
|
||||
) : (
|
||||
<Text className="item__owner">{t("Common:Owner")}</Text>
|
||||
)
|
||||
) : (
|
||||
<AccessComboBox
|
||||
t={t}
|
||||
access={item.access}
|
||||
directionX="right"
|
||||
directionY="bottom"
|
||||
accessOptions={externalAccessOptions}
|
||||
onAccessChange={onChangeItemAccess}
|
||||
itemId={item.sharedTo.id}
|
||||
isDisabled={false}
|
||||
disableLink={false}
|
||||
canDelete={true}
|
||||
onRemoveUserClick={onRemoveUserClick}
|
||||
isDefaultMode={false}
|
||||
fixedDirection={true}
|
||||
/>
|
||||
)}
|
||||
</StyledItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default Item;
|
@ -1,296 +0,0 @@
|
||||
import React from "react";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Link from "@appserver/components/link";
|
||||
import Row from "@appserver/components/row";
|
||||
import Text from "@appserver/components/text";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import copy from "copy-to-clipboard";
|
||||
import LinkRow from "./linkRow";
|
||||
import AccessComboBox from "./AccessComboBox";
|
||||
import { getAccessIcon } from "../../../helpers/files-helpers";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { objectToGetParams } from "@appserver/common/utils";
|
||||
|
||||
class SharingRow extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
access: props.item.access,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { access } = this.props.item;
|
||||
if (this.state.access !== access) {
|
||||
this.setState({ access });
|
||||
}
|
||||
}
|
||||
|
||||
onCopyInternalLink = () => {
|
||||
const { internalLink, t } = this.props;
|
||||
|
||||
copy(internalLink);
|
||||
toastr.success(t("Translations:LinkCopySuccess"));
|
||||
};
|
||||
|
||||
onCopyClick = () => {
|
||||
const { t, item } = this.props;
|
||||
const { shareLink } = item.sharedTo;
|
||||
toastr.success(t("Translations:LinkCopySuccess"));
|
||||
copy(shareLink);
|
||||
};
|
||||
|
||||
onShareEmail = () => {
|
||||
const { selection, item, t } = this.props;
|
||||
const { shareLink } = item.sharedTo;
|
||||
|
||||
const itemName = selection.title ? selection.title : selection[0].title;
|
||||
const subject = t("ShareEmailSubject", { itemName });
|
||||
const body = t("ShareEmailBody", { itemName, shareLink });
|
||||
|
||||
const mailtoLink =
|
||||
"mailto:" +
|
||||
objectToGetParams({
|
||||
subject,
|
||||
body,
|
||||
});
|
||||
|
||||
window.open(mailtoLink, "_self");
|
||||
};
|
||||
|
||||
onShareTwitter = () => {
|
||||
const { item } = this.props;
|
||||
const { shareLink } = item.sharedTo;
|
||||
|
||||
const twitterLink =
|
||||
"https://twitter.com/intent/tweet" +
|
||||
objectToGetParams({
|
||||
text: shareLink,
|
||||
});
|
||||
|
||||
window.open(twitterLink, "", "width=1000,height=670");
|
||||
};
|
||||
|
||||
// onShareFacebook = () => {
|
||||
// const { item, selection } = this.props;
|
||||
// const { shareLink } = item.sharedTo;
|
||||
|
||||
// const facebookLink =
|
||||
// "https://www.facebook.com/sharer/sharer.php" +
|
||||
// objectToGetParams({
|
||||
// u: shareLink,
|
||||
// t: selection.title ? selection.title : selection[0].title,
|
||||
// });
|
||||
|
||||
// window.open(facebookLink);
|
||||
// };
|
||||
|
||||
render() {
|
||||
//console.log("SharingRow render");
|
||||
const {
|
||||
t,
|
||||
selection,
|
||||
item,
|
||||
index,
|
||||
isMyId,
|
||||
accessOptions,
|
||||
onChangeItemAccess,
|
||||
onRemoveUserClick,
|
||||
onShowEmbeddingPanel,
|
||||
onToggleLink,
|
||||
externalLinkData,
|
||||
onShowChangeOwnerPanel,
|
||||
isLoading,
|
||||
internalLink,
|
||||
isPersonal,
|
||||
theme,
|
||||
} = this.props;
|
||||
const { access } = this.state;
|
||||
|
||||
const canShareOwnerChange = this.props.canShareOwnerChange(item);
|
||||
|
||||
const { isOwner, isLocked } = item;
|
||||
const { label, displayName, name, shareLink, id } = item.sharedTo;
|
||||
const userName = name
|
||||
? name === "Everyone"
|
||||
? t("ShareEveryone")
|
||||
: name
|
||||
: "";
|
||||
|
||||
const externalLinkVisible =
|
||||
selection && selection.length === 1 && shareLink;
|
||||
const internalLinkVisible = index === 0 && internalLink;
|
||||
|
||||
const internalLinkData = [
|
||||
{
|
||||
key: "linkItem",
|
||||
label: t("CopyInternalLink"),
|
||||
onClick: this.onCopyInternalLink,
|
||||
},
|
||||
];
|
||||
|
||||
const externalLinkOptions = [
|
||||
{
|
||||
key: "linkItem_2",
|
||||
label: `${t("ShareVia")} e-mail`,
|
||||
onClick: this.onShareEmail,
|
||||
},
|
||||
// {
|
||||
// key: "linkItem_3",
|
||||
// label: `${t("ShareVia")} Facebook`,
|
||||
// onClick: this.onShareFacebook,
|
||||
// },
|
||||
{
|
||||
key: "linkItem_4",
|
||||
label: `${t("ShareVia")} Twitter`,
|
||||
onClick: this.onShareTwitter,
|
||||
},
|
||||
{
|
||||
key: "linkItem_5",
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
key: "linkItem_6",
|
||||
label: t("Embedding"),
|
||||
onClick: () => onShowEmbeddingPanel(shareLink),
|
||||
},
|
||||
];
|
||||
|
||||
const onRemoveUserProp = !isLoading ? { onClick: onRemoveUserClick } : {};
|
||||
const onShowChangeOwnerPanelProp = !isLoading
|
||||
? { onClick: onShowChangeOwnerPanel }
|
||||
: {};
|
||||
|
||||
const accessIconUrl = getAccessIcon(access);
|
||||
|
||||
return (
|
||||
<>
|
||||
{externalLinkVisible && (
|
||||
<LinkRow
|
||||
theme={theme}
|
||||
linkText={t("ExternalLink")}
|
||||
options={externalLinkOptions}
|
||||
externalLinkData={externalLinkData}
|
||||
onToggleLink={onToggleLink}
|
||||
withToggle
|
||||
onCopyLink={this.onCopyClick}
|
||||
{...this.props}
|
||||
/>
|
||||
)}
|
||||
{!isPersonal && (
|
||||
<>
|
||||
{internalLinkVisible && (
|
||||
<LinkRow
|
||||
theme={theme}
|
||||
linkText={t("InternalLink")}
|
||||
options={internalLinkData}
|
||||
{...this.props}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!shareLink && (
|
||||
<Row
|
||||
theme={theme}
|
||||
className="sharing-row"
|
||||
key={`internal-link-key_${id}`}
|
||||
element={
|
||||
isOwner || isLocked ? (
|
||||
<ReactSVG
|
||||
src={accessIconUrl}
|
||||
className="sharing_panel-owner-icon"
|
||||
beforeInjection={(svg) => {
|
||||
svg
|
||||
.querySelector("path")
|
||||
.setAttribute(
|
||||
"fill",
|
||||
isLoading
|
||||
? theme.filesPanels.sharing.loadingFill
|
||||
: theme.filesPanels.sharing.fill
|
||||
);
|
||||
svg.setAttribute(
|
||||
"style",
|
||||
`width:16px;
|
||||
min-width:16px;
|
||||
height:16px;
|
||||
min-height:16px;`
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<AccessComboBox
|
||||
t={t}
|
||||
theme={theme}
|
||||
access={access}
|
||||
directionX="left"
|
||||
onAccessChange={onChangeItemAccess}
|
||||
itemId={id}
|
||||
accessOptions={accessOptions}
|
||||
isDisabled={isLoading}
|
||||
fixedDirection={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
contextButtonSpacerWidth="0px"
|
||||
>
|
||||
<>
|
||||
{!shareLink &&
|
||||
(isOwner && canShareOwnerChange ? (
|
||||
<Link
|
||||
theme={theme}
|
||||
isHovered
|
||||
type="action"
|
||||
{...onShowChangeOwnerPanelProp}
|
||||
>
|
||||
{label ? label : userName ? userName : displayName}
|
||||
</Link>
|
||||
) : (
|
||||
<Text
|
||||
theme={theme}
|
||||
truncate
|
||||
className="sharing_panel-text"
|
||||
>
|
||||
{label ? label : userName ? userName : displayName}
|
||||
</Text>
|
||||
))}
|
||||
{isOwner ? (
|
||||
<Text
|
||||
className="sharing_panel-remove-icon"
|
||||
theme={theme}
|
||||
color={theme.filesPanels.sharing.color}
|
||||
>
|
||||
{t("Common:Owner")}
|
||||
</Text>
|
||||
) : id === isMyId ? (
|
||||
<Text
|
||||
className="sharing_panel-remove-icon"
|
||||
theme={theme}
|
||||
//color="#A3A9AE"
|
||||
>
|
||||
{t("Common:FullAccess")}
|
||||
</Text>
|
||||
) : (
|
||||
!shareLink &&
|
||||
!isLocked && (
|
||||
<IconButton
|
||||
iconName="/static/images/remove.react.svg"
|
||||
theme={theme}
|
||||
id={id}
|
||||
{...onRemoveUserProp}
|
||||
className="sharing_panel-remove-icon"
|
||||
// color={theme.filesPanels.sharing.color}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
</Row>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SharingRow;
|
@ -0,0 +1,375 @@
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
|
||||
const StyledContent = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: ${(props) =>
|
||||
props.isNotifyUsers
|
||||
? "53px calc(100% - 253px) 200px"
|
||||
: "53px calc(100% - 161px) 108px"};
|
||||
`;
|
||||
|
||||
const StyledHeaderContent = styled.div`
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: ${(props) => (props.isPersonal ? "40px" : "53px")};
|
||||
|
||||
border-bottom: ${(props) =>
|
||||
props.isPersonal ? "none" : props.theme.filesPanels.sharing.borderBottom};
|
||||
|
||||
padding: ${(props) => (props.isPersonal ? "0 4px" : "0 16px")};
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
`}
|
||||
|
||||
.sharing_panel-header-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
|
||||
width: calc(100% - 33px);
|
||||
max-width: calc(100% - 33px);
|
||||
|
||||
.sharing_panel-arrow {
|
||||
.icon-button_svg {
|
||||
width: 15px;
|
||||
}
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.isEmbedding &&
|
||||
css`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
margin-bottom: 16px;
|
||||
`}
|
||||
|
||||
.sharing_panel-icons-container {
|
||||
display: flex;
|
||||
margin-left: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledHeaderContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledBodyContent = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
|
||||
.body-scroll-content-sharing-panel {
|
||||
width: 100%;
|
||||
height: ${(props) =>
|
||||
props.externalLinkVisible
|
||||
? !props.externalLinkOpen
|
||||
? "calc(100% - 125px)"
|
||||
: "calc(100% - 207px)"
|
||||
: "calc(100% - 62px)"};
|
||||
max-height: ${(props) =>
|
||||
props.externalLinkVisible
|
||||
? !props.externalLinkOpen
|
||||
? "calc(100% - 125px)"
|
||||
: "calc(100% - 207px)"
|
||||
: "calc(100% - 62px)"};
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
height: 100% !important;
|
||||
max-height: 100% !important;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledExternalLink = styled.div`
|
||||
width: 100%;
|
||||
|
||||
padding: ${(props) =>
|
||||
props.isPersonal
|
||||
? props.isOpen
|
||||
? "8px 4px 4px"
|
||||
: "8px 4px 20px"
|
||||
: "20px 16px"};
|
||||
|
||||
border-bottom: ${(props) =>
|
||||
props.isPersonal ? "none" : props.theme.filesPanels.sharing.borderBottom};
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
|
||||
.external-link__base-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
flex-direction: row;
|
||||
|
||||
.external-link__text {
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.external-link__toggler {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.external-link__checked {
|
||||
margin-top: 16px;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
|
||||
.external-link__input-link {
|
||||
flex-direction: row-reverse;
|
||||
padding-right: 0px;
|
||||
|
||||
.external-link__buttons {
|
||||
position: relative;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding: 4px 16px;
|
||||
|
||||
.external-link__code-icon {
|
||||
margin-right: 12px;
|
||||
|
||||
cursor: pointer;
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.theme.filesPanels.sharing.externalLinkSvg} !important;
|
||||
}
|
||||
}
|
||||
|
||||
.external-link__share-icon {
|
||||
cursor: pointer;
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.theme.filesPanels.sharing.externalLinkSvg} !important;
|
||||
}
|
||||
}
|
||||
|
||||
external-link__share-dropdown {
|
||||
}
|
||||
}
|
||||
|
||||
.append {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.external-link__copy {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.panel_combo-box {
|
||||
.combo-button {
|
||||
min-width: 46px;
|
||||
height: 32px;
|
||||
|
||||
.sharing-access-combo-box-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.dropdown-container {
|
||||
top: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.external-link__access-rights {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
flex-direction: row;
|
||||
|
||||
margin-top: 16px;
|
||||
|
||||
.external-link__access-rights_text {
|
||||
color: #a3a9ae;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledExternalLink.defaultProps = { theme: Base };
|
||||
|
||||
const StyledInternalLink = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 20px 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
.internal-link__link-text {
|
||||
line-height: 22px !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.internal-link__copy-text {
|
||||
line-height: 15px !important;
|
||||
font-weight: 600 !important;
|
||||
|
||||
border-bottom: ${(props) =>
|
||||
props.theme.filesPanels.sharing.internalLinkBorder};
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledInternalLink.defaultProps = { theme: Base };
|
||||
|
||||
const StyledItem = styled.div`
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 8px 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
.item__info-block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
|
||||
.info-block__text {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.item__change-owner {
|
||||
line-height: 15px !important;
|
||||
font-weight: 600 !important;
|
||||
|
||||
border-bottom: ${(props) => props.theme.filesPanels.sharing.itemBorder};
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item__owner {
|
||||
color: ${(props) => props.theme.filesPanels.sharing.itemOwnerColor};
|
||||
}
|
||||
|
||||
.panel_combo-box {
|
||||
.combo-button {
|
||||
min-width: 46px;
|
||||
height: 32px;
|
||||
|
||||
.sharing-access-combo-box-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledItem.defaultProps = { theme: Base };
|
||||
|
||||
const StyledFooterContent = styled.div`
|
||||
width: 100%;
|
||||
|
||||
min-height: 100px;
|
||||
border-top: ${(props) => props.theme.filesPanels.sharing.borderTop};
|
||||
|
||||
position: relative;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
padding: 16px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
|
||||
.sharing_panel-notification {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.sharing_panel-checkbox {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.sharing_panel-button {
|
||||
min-height: 40px;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledFooterContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledModalFooter = styled.div`
|
||||
width: 100%;
|
||||
|
||||
padding: 16px 4px 4px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
height: 40px;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button:first-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export {
|
||||
StyledContent,
|
||||
StyledHeaderContent,
|
||||
StyledBodyContent,
|
||||
StyledExternalLink,
|
||||
StyledInternalLink,
|
||||
StyledItem,
|
||||
StyledFooterContent,
|
||||
StyledModalFooter,
|
||||
};
|
@ -24,7 +24,14 @@ newInstance.use(Backend).init({
|
||||
loadPath: loadLanguagePath(config.homepage),
|
||||
},
|
||||
|
||||
ns: ["SharingPanel", "Common", "Translations"],
|
||||
ns: [
|
||||
"SharingPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"EmbeddingPanel",
|
||||
"Home",
|
||||
"ChangeOwnerPanel",
|
||||
],
|
||||
defaultNS: "SharingPanel",
|
||||
|
||||
react: {
|
||||
|
@ -1,28 +1,14 @@
|
||||
import React from "react";
|
||||
import Backdrop from "@appserver/components/backdrop";
|
||||
import Heading from "@appserver/components/heading";
|
||||
import Aside from "@appserver/components/aside";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import Button from "@appserver/components/button";
|
||||
import DropDown from "@appserver/components/drop-down";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
import Loader from "@appserver/components/loader";
|
||||
import Text from "@appserver/components/text";
|
||||
|
||||
import Aside from "@appserver/components/aside";
|
||||
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import toastr from "studio/toastr";
|
||||
import { ShareAccessRights } from "@appserver/common/constants";
|
||||
import {
|
||||
StyledAsidePanel,
|
||||
StyledContent,
|
||||
StyledFooter,
|
||||
StyledHeaderContent,
|
||||
StyledSharingBody,
|
||||
StyledModalRowContainer,
|
||||
} from "../StyledPanels";
|
||||
import { StyledAsidePanel } from "../StyledPanels";
|
||||
import { AddUsersPanel, AddGroupsPanel, EmbeddingPanel } from "../index";
|
||||
import SharingRow from "./SharingRow";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import config from "../../../../package.json";
|
||||
import i18n from "./i18n";
|
||||
@ -33,13 +19,20 @@ import withLoader from "../../../HOCs/withLoader";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import EmbeddingBody from "../EmbeddingPanel/EmbeddingBody";
|
||||
|
||||
const SharingBodyStyle = { height: `calc(100vh - 156px)` };
|
||||
import { StyledContent, StyledModalFooter } from "./StyledSharingPanel";
|
||||
|
||||
import Header from "./Header";
|
||||
import Body from "./Body";
|
||||
import Footer from "./Footer";
|
||||
import SharingPanelLoader from "@appserver/common/components/Loaders/SharingPanelLoader";
|
||||
import SharingPanelLoaderModal from "@appserver/common/components/Loaders/SharingPanelLoader/modal";
|
||||
|
||||
// const SharingBodyStyle = { height: `calc(100vh - 156px)` };
|
||||
|
||||
class SharingPanelComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showActionPanel: false,
|
||||
isNotifyUsers: false,
|
||||
shareDataItems: [],
|
||||
baseShareData: [],
|
||||
@ -53,24 +46,15 @@ class SharingPanelComponent extends React.Component {
|
||||
showPanel: false,
|
||||
accessOptions: [],
|
||||
filesOwnerId: null,
|
||||
showEmbeddingContent: false,
|
||||
isUpdated: false,
|
||||
isLoading: false,
|
||||
showEmbeddingContent: false,
|
||||
baseExternalAccess: null,
|
||||
};
|
||||
|
||||
this.ref = React.createRef();
|
||||
this.scrollRef = React.createRef();
|
||||
}
|
||||
|
||||
onPlusClick = () =>
|
||||
this.setState({ showActionPanel: !this.state.showActionPanel });
|
||||
|
||||
onCloseActionPanel = (e) => {
|
||||
if (this.ref.current.contains(e.target)) return;
|
||||
this.setState({ showActionPanel: !this.state.showActionPanel });
|
||||
};
|
||||
|
||||
isUpdateAccessInfo = (selectedAccess) => {
|
||||
const { baseExternalAccess, isUpdated } = this.state;
|
||||
|
||||
@ -251,7 +235,29 @@ class SharingPanelComponent extends React.Component {
|
||||
onShowUsersPanel = () =>
|
||||
this.setState({
|
||||
showAddUsersPanel: !this.state.showAddUsersPanel,
|
||||
showActionPanel: false,
|
||||
});
|
||||
|
||||
onShowGroupsPanel = () =>
|
||||
this.setState({
|
||||
showAddGroupsPanel: !this.state.showAddGroupsPanel,
|
||||
});
|
||||
|
||||
onShowChangeOwnerPanel = () => {
|
||||
this.setState({
|
||||
showChangeOwnerPanel: !this.state.showChangeOwnerPanel,
|
||||
});
|
||||
};
|
||||
|
||||
onShowEmbeddingPanel = (link) =>
|
||||
this.setState({
|
||||
showEmbeddingPanel: !this.state.showEmbeddingPanel,
|
||||
shareLink: link,
|
||||
});
|
||||
|
||||
onShowEmbeddingContainer = (link) =>
|
||||
this.setState({
|
||||
showEmbeddingContent: !this.state.showEmbeddingContent,
|
||||
shareLink: link,
|
||||
});
|
||||
|
||||
onChangeItemAccess = (e) => {
|
||||
@ -360,67 +366,49 @@ class SharingPanelComponent extends React.Component {
|
||||
toastr.error(err);
|
||||
this.onClose();
|
||||
})
|
||||
.finally(() =>
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
})
|
||||
);
|
||||
.finally(() => {
|
||||
setTimeout(() => {
|
||||
return this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
|
||||
getInternalLink = () => {
|
||||
const { homepage, selection } = this.props;
|
||||
|
||||
const item = selection[0];
|
||||
const isFile = !!item.fileExst;
|
||||
const isFile = !!item?.fileExst;
|
||||
|
||||
if (selection.length !== 1) return null;
|
||||
|
||||
return isFile
|
||||
? item.canOpenPlayer
|
||||
? `${window.location.href}&preview=${item.id}`
|
||||
? `${window.location.href}&preview=${item?.id}`
|
||||
: item.webUrl
|
||||
: `${window.location.origin + homepage}/filter?folder=${item.id}`;
|
||||
: `${window.location.origin + homepage}/filter?folder=${item?.id}`;
|
||||
};
|
||||
|
||||
onShowEmbeddingPanel = (link) =>
|
||||
this.setState({
|
||||
showEmbeddingPanel: !this.state.showEmbeddingPanel,
|
||||
shareLink: link,
|
||||
});
|
||||
onChangeMessage = (e) => {
|
||||
this.setState({ message: e.target.value });
|
||||
};
|
||||
|
||||
onShowEmbeddingContainer = (link) =>
|
||||
this.setState({
|
||||
showEmbeddingContent: !this.state.showEmbeddingContent,
|
||||
shareLink: link,
|
||||
});
|
||||
|
||||
onShowGroupsPanel = () =>
|
||||
this.setState({
|
||||
showAddGroupsPanel: !this.state.showAddGroupsPanel,
|
||||
showActionPanel: false,
|
||||
});
|
||||
|
||||
onShowChangeOwnerPanel = () =>
|
||||
this.setState({
|
||||
showChangeOwnerPanel: !this.state.showChangeOwnerPanel,
|
||||
showActionPanel: false,
|
||||
});
|
||||
|
||||
onChangeMessage = (e) => this.setState({ message: e.target.value });
|
||||
|
||||
setShareDataItems = (shareDataItems) => this.setState({ shareDataItems });
|
||||
setShareDataItems = (shareDataItems) => {
|
||||
this.setState({ shareDataItems });
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
const {
|
||||
onCancel,
|
||||
setSharingPanelVisible,
|
||||
selectUploadedFile,
|
||||
setIsFolderActions,
|
||||
setSelection,
|
||||
setBufferSelection,
|
||||
} = this.props;
|
||||
|
||||
setSharingPanelVisible(false);
|
||||
|
||||
setSelection([]);
|
||||
|
||||
selectUploadedFile([]);
|
||||
@ -474,8 +462,6 @@ class SharingPanelComponent extends React.Component {
|
||||
//console.log("Sharing panel render");
|
||||
const {
|
||||
t,
|
||||
theme,
|
||||
tReady,
|
||||
isPersonal,
|
||||
isMyId,
|
||||
selection,
|
||||
@ -485,9 +471,10 @@ class SharingPanelComponent extends React.Component {
|
||||
documentTitle,
|
||||
sharingPanelVisible,
|
||||
isPrivacy,
|
||||
theme,
|
||||
isShared,
|
||||
} = this.props;
|
||||
const {
|
||||
showActionPanel,
|
||||
isNotifyUsers,
|
||||
shareDataItems,
|
||||
message,
|
||||
@ -500,262 +487,338 @@ class SharingPanelComponent extends React.Component {
|
||||
accessOptions,
|
||||
externalAccessOptions,
|
||||
showEmbeddingContent,
|
||||
isUpdated,
|
||||
isLoading,
|
||||
} = this.state;
|
||||
|
||||
const visible = sharingPanelVisible;
|
||||
|
||||
const zIndex = 310;
|
||||
const onPlusClickProp = !isLoading ? { onClick: this.onPlusClick } : {};
|
||||
|
||||
const isEncrypted =
|
||||
isPrivacy || (selection.length && selection[0].encrypted);
|
||||
isPrivacy || (selection.length && selection[0]?.encrypted);
|
||||
|
||||
const internalLink =
|
||||
selection.length === 1 && !isEncrypted && this.getInternalLink();
|
||||
|
||||
return isPersonal && !isMobileOnly ? (
|
||||
<ModalDialog
|
||||
isLoading={!tReady}
|
||||
visible={visible}
|
||||
displayType="modal"
|
||||
onClose={this.onClose}
|
||||
>
|
||||
<ModalDialog.Header>{t("SharingSettingsTitle")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<StyledModalRowContainer>
|
||||
{!isLoading ? (
|
||||
shareDataItems.map((item, index) => (
|
||||
<SharingRow
|
||||
t={t}
|
||||
theme={theme}
|
||||
const filteredShareDataItems = [];
|
||||
const externalItem = [];
|
||||
const owner = [];
|
||||
const shareGroups = [];
|
||||
const shareUsers = [];
|
||||
|
||||
shareDataItems.forEach((item) => {
|
||||
if (item?.sharedTo?.shareLink) {
|
||||
return externalItem.push(item);
|
||||
}
|
||||
|
||||
if (item?.isOwner) {
|
||||
item.isUser = true;
|
||||
return owner.push(item);
|
||||
}
|
||||
|
||||
if (
|
||||
item?.sharedTo?.userName ||
|
||||
(item?.sharedTo?.label && item.sharedTo.avatarUrl)
|
||||
) {
|
||||
item.isUser = true;
|
||||
shareUsers.push(item);
|
||||
} else {
|
||||
item.isGroup = true;
|
||||
shareGroups.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
filteredShareDataItems.push(
|
||||
...externalItem,
|
||||
...owner,
|
||||
...shareGroups,
|
||||
...shareUsers
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isPersonal ? (
|
||||
<>
|
||||
{isLoading ? (
|
||||
isMobileOnly ? (
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={true}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
isPersonal={isPersonal}
|
||||
index={index}
|
||||
key={`${item.sharedTo.id}_${index}`}
|
||||
selection={selection}
|
||||
item={item}
|
||||
isMyId={isMyId}
|
||||
accessOptions={accessOptions}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
canShareOwnerChange={canShareOwnerChange}
|
||||
onChangeItemAccess={this.onChangeItemAccess}
|
||||
internalLink={internalLink}
|
||||
onRemoveUserClick={this.onRemoveUserItemClick}
|
||||
onShowEmbeddingPanel={this.onShowEmbeddingContainer}
|
||||
onToggleLink={this.onToggleLink}
|
||||
onShowChangeOwnerPanel={this.onShowChangeOwnerPanel}
|
||||
isLoading={isLoading}
|
||||
documentTitle={documentTitle}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Loaders.Rectangle
|
||||
height="47px"
|
||||
animate={0}
|
||||
foregroundColor="#f8f9f9"
|
||||
backgroundColor="#f8f9f9"
|
||||
backgroundOpacity={1}
|
||||
foregroundOpacity={1}
|
||||
/>
|
||||
)}
|
||||
{showEmbeddingContent && (
|
||||
<EmbeddingBody embeddingLink={shareLink} />
|
||||
)}
|
||||
</StyledModalRowContainer>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
className="sharing_panel-button"
|
||||
label={t("Common:SaveButton")}
|
||||
size="normal"
|
||||
primary
|
||||
onClick={this.onSaveClick}
|
||||
isDisabled={isLoading || !isUpdated}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
) : (
|
||||
<StyledAsidePanel visible={visible}>
|
||||
<Backdrop
|
||||
onClick={this.onClose}
|
||||
visible={visible}
|
||||
zIndex={zIndex}
|
||||
isAside={true}
|
||||
/>
|
||||
<Aside className="header_aside-panel" visible={visible}>
|
||||
<StyledContent isDisabled={isLoading}>
|
||||
<StyledHeaderContent className="sharing_panel-header-container">
|
||||
{uploadPanelVisible && (
|
||||
<IconButton
|
||||
size="16"
|
||||
iconName="/static/images/arrow.path.react.svg"
|
||||
onClick={this.onClose}
|
||||
color="A3A9AE"
|
||||
/>
|
||||
)}
|
||||
<Heading className="sharing_panel-header" size="medium" truncate>
|
||||
{t("SharingSettingsTitle")}
|
||||
</Heading>
|
||||
{!isPersonal && (
|
||||
<div className="sharing_panel-icons-container">
|
||||
<div
|
||||
ref={this.ref}
|
||||
className="sharing_panel-drop-down-wrapper"
|
||||
modalBodyPadding="12px 0 0"
|
||||
>
|
||||
<ModalDialog.Body>
|
||||
<SharingPanelLoaderModal isShared={isShared} />
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
) : (
|
||||
<>
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={true}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
width={"400px"}
|
||||
isPersonal={isPersonal}
|
||||
modalBodyPadding="12px 0 0"
|
||||
>
|
||||
<IconButton
|
||||
size="17"
|
||||
iconName="/static/images/actions.header.touch.react.svg"
|
||||
className="sharing_panel-plus-icon"
|
||||
{...onPlusClickProp}
|
||||
// color="A3A9AE"
|
||||
isDisabled={isLoading}
|
||||
<ModalDialog.Body>
|
||||
<SharingPanelLoaderModal isShared={isShared} />
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
</>
|
||||
)
|
||||
) : isMobileOnly ? (
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
modalBodyPadding="12px 0 0"
|
||||
isPersonal={isPersonal}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Header
|
||||
t={t}
|
||||
uploadPanelVisible={showEmbeddingContent}
|
||||
isPersonal={isPersonal}
|
||||
isEncrypted={isEncrypted}
|
||||
onClose={this.onShowEmbeddingContainer}
|
||||
onShowUsersPanel={this.onShowUsersPanel}
|
||||
onShowGroupsPanel={this.onShowGroupsPanel}
|
||||
label={t("EmbeddingPanel:EmbeddingDocument")}
|
||||
/>
|
||||
</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
{showEmbeddingContent ? (
|
||||
<EmbeddingBody
|
||||
isPersonal={isPersonal}
|
||||
theme={theme}
|
||||
embeddingLink={externalItem[0].sharedTo.shareLink}
|
||||
/>
|
||||
) : (
|
||||
<Body
|
||||
isShared={isShared}
|
||||
t={t}
|
||||
isPersonal={isPersonal}
|
||||
selection={selection}
|
||||
externalItem={externalItem[0]}
|
||||
onToggleLink={this.onToggleLink}
|
||||
onShowEmbeddingPanel={this.onShowEmbeddingContainer}
|
||||
onChangeItemAccess={this.onChangeItemAccess}
|
||||
accessOptions={accessOptions}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
/>
|
||||
)}
|
||||
</ModalDialog.Body>
|
||||
|
||||
<DropDown
|
||||
forwardedRef={this.ref}
|
||||
directionX="right"
|
||||
className="sharing_panel-drop-down"
|
||||
open={showActionPanel}
|
||||
manualY="30px"
|
||||
clickOutsideAction={this.onCloseActionPanel}
|
||||
>
|
||||
<DropDownItem
|
||||
label={t("LinkText")}
|
||||
onClick={this.onShowUsersPanel}
|
||||
{!showEmbeddingContent && (
|
||||
<ModalDialog.Footer>
|
||||
<StyledModalFooter>
|
||||
<Button
|
||||
size={"normal"}
|
||||
label={t("Common:SaveButton")}
|
||||
primary
|
||||
onClick={this.onSaveClick}
|
||||
scale
|
||||
/>
|
||||
{!isEncrypted && (
|
||||
<DropDownItem
|
||||
label={t("AddGroupsForSharingButton")}
|
||||
onClick={this.onShowGroupsPanel}
|
||||
/>
|
||||
)}
|
||||
</DropDown>
|
||||
</div>
|
||||
<Button
|
||||
size={"normal"}
|
||||
label={t("Common:CancelButton")}
|
||||
scale
|
||||
onClick={this.onClose}
|
||||
/>
|
||||
</StyledModalFooter>
|
||||
</ModalDialog.Footer>
|
||||
)}
|
||||
</ModalDialog>
|
||||
) : (
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
width={"400px"}
|
||||
modalBodyPadding="12px 0 0"
|
||||
isPersonal={isPersonal}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Header
|
||||
t={t}
|
||||
uploadPanelVisible={showEmbeddingContent}
|
||||
isPersonal={isPersonal}
|
||||
isEncrypted={isEncrypted}
|
||||
onClose={this.onShowEmbeddingContainer}
|
||||
onShowUsersPanel={this.onShowUsersPanel}
|
||||
onShowGroupsPanel={this.onShowGroupsPanel}
|
||||
label={t("EmbeddingPanel:EmbeddingDocument")}
|
||||
/>
|
||||
</ModalDialog.Header>
|
||||
|
||||
{/*<IconButton
|
||||
size="16"
|
||||
iconName="images/key.react.svg"
|
||||
onClick={this.onKeyClick}
|
||||
/>*/}
|
||||
</div>
|
||||
)}
|
||||
</StyledHeaderContent>
|
||||
<StyledSharingBody
|
||||
ref={this.scrollRef}
|
||||
stype="mediumBlack"
|
||||
style={SharingBodyStyle}
|
||||
<ModalDialog.Body>
|
||||
{showEmbeddingContent ? (
|
||||
<EmbeddingBody
|
||||
isPersonal={isPersonal}
|
||||
theme={theme}
|
||||
embeddingLink={externalItem[0].sharedTo.shareLink}
|
||||
/>
|
||||
) : (
|
||||
<Body
|
||||
isShared={isShared}
|
||||
t={t}
|
||||
isPersonal={isPersonal}
|
||||
selection={selection}
|
||||
externalItem={externalItem[0]}
|
||||
onToggleLink={this.onToggleLink}
|
||||
onShowEmbeddingPanel={this.onShowEmbeddingContainer}
|
||||
onChangeItemAccess={this.onChangeItemAccess}
|
||||
accessOptions={accessOptions}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
/>
|
||||
)}
|
||||
</ModalDialog.Body>
|
||||
|
||||
{!showEmbeddingContent && (
|
||||
<ModalDialog.Footer>
|
||||
<StyledModalFooter>
|
||||
<Button
|
||||
size={"normal"}
|
||||
label={t("Common:SaveButton")}
|
||||
primary
|
||||
onClick={this.onSaveClick}
|
||||
scale
|
||||
/>
|
||||
<Button
|
||||
size={"normal"}
|
||||
label={t("Common:CancelButton")}
|
||||
scale
|
||||
onClick={this.onClose}
|
||||
/>
|
||||
</StyledModalFooter>
|
||||
</ModalDialog.Footer>
|
||||
)}
|
||||
</ModalDialog>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<StyledAsidePanel visible={visible}>
|
||||
<Backdrop
|
||||
onClick={this.onClose}
|
||||
visible={visible}
|
||||
zIndex={zIndex}
|
||||
isAside={true}
|
||||
/>
|
||||
<Aside
|
||||
className="header_aside-panel"
|
||||
visible={visible}
|
||||
withoutBodyScroll={true}
|
||||
>
|
||||
{!isLoading ? (
|
||||
shareDataItems.map((item, index) => (
|
||||
<SharingRow
|
||||
<StyledContent isNotifyUsers={isNotifyUsers}>
|
||||
<Header
|
||||
t={t}
|
||||
uploadPanelVisible={uploadPanelVisible}
|
||||
isPersonal={isPersonal}
|
||||
isEncrypted={isEncrypted}
|
||||
onClose={this.onClose}
|
||||
onShowUsersPanel={this.onShowUsersPanel}
|
||||
onShowGroupsPanel={this.onShowGroupsPanel}
|
||||
/>
|
||||
|
||||
<Body
|
||||
t={t}
|
||||
theme={theme}
|
||||
isPersonal={isPersonal}
|
||||
index={index}
|
||||
key={`${item.sharedTo.id}_${index}`}
|
||||
selection={selection}
|
||||
item={item}
|
||||
externalItem={externalItem[0]}
|
||||
owner={owner[0]}
|
||||
shareGroups={shareGroups}
|
||||
shareUsers={shareUsers}
|
||||
isMyId={isMyId}
|
||||
onToggleLink={this.onToggleLink}
|
||||
onShowEmbeddingPanel={this.onShowEmbeddingPanel}
|
||||
onChangeItemAccess={this.onChangeItemAccess}
|
||||
accessOptions={accessOptions}
|
||||
externalAccessOptions={externalAccessOptions}
|
||||
canShareOwnerChange={canShareOwnerChange}
|
||||
onChangeItemAccess={this.onChangeItemAccess}
|
||||
internalLink={internalLink}
|
||||
onRemoveUserClick={this.onRemoveUserItemClick}
|
||||
onShowEmbeddingPanel={this.onShowEmbeddingPanel}
|
||||
onToggleLink={this.onToggleLink}
|
||||
onShowChangeOwnerPanel={this.onShowChangeOwnerPanel}
|
||||
isLoading={isLoading}
|
||||
documentTitle={documentTitle}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div key="loader" className="panel-loader-wrapper">
|
||||
<Loader type="oval" size="16px" className="panel-loader" />
|
||||
<Text as="span">{`${t("Common:LoadingProcessing")} ${t(
|
||||
"Common:LoadingDescription"
|
||||
)}`}</Text>
|
||||
</div>
|
||||
)}
|
||||
{isNotifyUsers && (
|
||||
<div className="sharing_panel-text-area">
|
||||
<Textarea
|
||||
placeholder={t("AddShareMessage")}
|
||||
onChange={this.onChangeMessage}
|
||||
value={message}
|
||||
isDisabled={isLoading}
|
||||
|
||||
<Footer
|
||||
t={t}
|
||||
isPersonal={isPersonal}
|
||||
message={message}
|
||||
onChangeMessage={this.onChangeMessage}
|
||||
isNotifyUsers={isNotifyUsers}
|
||||
onNotifyUsersChange={this.onNotifyUsersChange}
|
||||
onSaveClick={this.onSaveClick}
|
||||
/>
|
||||
</div>
|
||||
</StyledContent>
|
||||
) : (
|
||||
<SharingPanelLoader />
|
||||
)}
|
||||
</StyledSharingBody>
|
||||
<StyledFooter>
|
||||
{!isPersonal && (
|
||||
<Checkbox
|
||||
isChecked={isNotifyUsers}
|
||||
label={t("Notify users")}
|
||||
onChange={this.onNotifyUsersChange}
|
||||
className="sharing_panel-checkbox"
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
className="sharing_panel-button"
|
||||
label={t("Common:SaveButton")}
|
||||
size={isMobile ? "normal" : "small"}
|
||||
minwidth="100px"
|
||||
primary
|
||||
onClick={this.onSaveClick}
|
||||
isDisabled={isLoading}
|
||||
</Aside>
|
||||
|
||||
{showAddUsersPanel && (
|
||||
<AddUsersPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowUsersPanel}
|
||||
visible={showAddUsersPanel}
|
||||
shareDataItems={filteredShareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
groupsCaption={groupsCaption}
|
||||
accessOptions={accessOptions}
|
||||
isMultiSelect
|
||||
isEncrypted={isEncrypted}
|
||||
/>
|
||||
</StyledFooter>
|
||||
</StyledContent>
|
||||
</Aside>
|
||||
)}
|
||||
|
||||
{showAddUsersPanel && (
|
||||
<AddUsersPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowUsersPanel}
|
||||
visible={showAddUsersPanel}
|
||||
shareDataItems={shareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
groupsCaption={groupsCaption}
|
||||
accessOptions={accessOptions}
|
||||
isMultiSelect
|
||||
isEncrypted={isEncrypted}
|
||||
/>
|
||||
)}
|
||||
{showAddGroupsPanel && (
|
||||
<AddGroupsPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowGroupsPanel}
|
||||
visible={showAddGroupsPanel}
|
||||
shareDataItems={filteredShareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
accessOptions={accessOptions}
|
||||
isMultiSelect
|
||||
/>
|
||||
)}
|
||||
|
||||
{showAddGroupsPanel && (
|
||||
<AddGroupsPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowGroupsPanel}
|
||||
visible={showAddGroupsPanel}
|
||||
shareDataItems={shareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
accessOptions={accessOptions}
|
||||
isMultiSelect
|
||||
/>
|
||||
)}
|
||||
{showChangeOwnerPanel && (
|
||||
<AddUsersPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowChangeOwnerPanel}
|
||||
visible={showChangeOwnerPanel}
|
||||
shareDataItems={filteredShareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showChangeOwnerPanel && (
|
||||
<AddUsersPanel
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowChangeOwnerPanel}
|
||||
visible={showChangeOwnerPanel}
|
||||
shareDataItems={shareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
/>
|
||||
{showEmbeddingPanel && (
|
||||
<EmbeddingPanel
|
||||
visible={showEmbeddingPanel}
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowEmbeddingPanel}
|
||||
embeddingLink={externalItem[0].sharedTo.shareLink}
|
||||
/>
|
||||
)}
|
||||
</StyledAsidePanel>
|
||||
)}
|
||||
|
||||
{showEmbeddingPanel && (
|
||||
<EmbeddingPanel
|
||||
visible={showEmbeddingPanel}
|
||||
onSharingPanelClose={this.onClose}
|
||||
onClose={this.onShowEmbeddingPanel}
|
||||
embeddingLink={shareLink}
|
||||
/>
|
||||
)}
|
||||
</StyledAsidePanel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -774,6 +837,7 @@ const SharingPanel = inject(
|
||||
) => {
|
||||
const { replaceFileStream, setEncryptionAccess } = auth;
|
||||
const { personal, customNames, isDesktopClient } = auth.settingsStore;
|
||||
const { user } = auth.userStore;
|
||||
|
||||
const { id, access } = selectedFolderStore;
|
||||
|
||||
@ -841,19 +905,32 @@ const SharingPanel = inject(
|
||||
id,
|
||||
setBufferSelection,
|
||||
access,
|
||||
isShared: selection[0].shared,
|
||||
};
|
||||
}
|
||||
)(
|
||||
observer(
|
||||
withTranslation(["SharingPanel", "Common", "Translations"])(
|
||||
withLoader(SharingPanelComponent)(<Loaders.DialogAsideLoader isPanel />)
|
||||
)
|
||||
withTranslation([
|
||||
"SharingPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"Home",
|
||||
"ChangeOwnerPanel",
|
||||
"EmbeddingPanel",
|
||||
])(withLoader(SharingPanelComponent)(<Loaders.DialogAsideLoader isPanel />))
|
||||
)
|
||||
);
|
||||
|
||||
class Panel extends React.Component {
|
||||
static convertSharingUsers = (shareDataItems) => {
|
||||
const t = i18n.getFixedT(null, ["SharingPanel", "Common"]);
|
||||
const t = i18n.getFixedT(null, [
|
||||
"SharingPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"Home",
|
||||
"ChangeOwnerPanel",
|
||||
"EmbeddingPanel",
|
||||
]);
|
||||
const {
|
||||
FullAccess,
|
||||
DenyAccess,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import Scrollbar from "@appserver/components/scrollbar";
|
||||
import { desktop, tablet } from "@appserver/components/utils/device";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { desktop, mobile, tablet } from "@appserver/components/utils/device";
|
||||
import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const PanelStyles = css`
|
||||
@ -37,8 +37,8 @@ const PanelStyles = css`
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 16px 0;
|
||||
width: calc(100% - 32px);
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@ -80,6 +80,7 @@ const StyledAsidePanel = styled.div`
|
||||
padding-top: ${isMobile ? "55px" : "48px"};
|
||||
height: ${isMobile ? "calc(100vh - 55px)" : "calc(100vh - 48px)"};
|
||||
}
|
||||
|
||||
.modal-dialog-aside {
|
||||
padding: 0;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
|
||||
@ -93,18 +94,31 @@ const StyledAsidePanel = styled.div`
|
||||
|
||||
.header_aside-panel {
|
||||
transition: unset;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
|
||||
width: 500px;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "480px")});
|
||||
width: 480px;
|
||||
max-width: 480px;
|
||||
overflow-y: hidden;
|
||||
|
||||
@media (max-width: 550px) {
|
||||
width: 320px;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "320px")});
|
||||
@media (max-width: 500px) {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
.sharing_panel-header-container {
|
||||
padding-right: 0;
|
||||
}
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
`}
|
||||
}
|
||||
${PanelStyles}
|
||||
`;
|
||||
@ -152,13 +166,32 @@ StyledVersionHistoryPanel.defaultProps = { theme: Base };
|
||||
|
||||
const StyledAddUsersPanelPanel = styled.div`
|
||||
.header_aside-panel {
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
|
||||
width: 500px;
|
||||
transition: unset;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "480px")});
|
||||
width: 480px;
|
||||
max-width: 480px;
|
||||
overflow-y: hidden;
|
||||
|
||||
@media (max-width: 550px) {
|
||||
width: 320px;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "320px")});
|
||||
@media (max-width: 500px) {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
`}
|
||||
}
|
||||
${PanelStyles}
|
||||
.combo-button-label {
|
||||
@ -168,13 +201,32 @@ const StyledAddUsersPanelPanel = styled.div`
|
||||
|
||||
const StyledAddGroupsPanel = styled.div`
|
||||
.header_aside-panel {
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
|
||||
width: 500px;
|
||||
transition: unset;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "480px")});
|
||||
width: 480px;
|
||||
max-width: 480px;
|
||||
overflow-y: hidden;
|
||||
|
||||
@media (max-width: 550px) {
|
||||
width: 320px;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "320px")});
|
||||
@media (max-width: 500px) {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
`}
|
||||
}
|
||||
${PanelStyles}
|
||||
.combo-button-label {
|
||||
@ -184,13 +236,32 @@ const StyledAddGroupsPanel = styled.div`
|
||||
|
||||
const StyledEmbeddingPanel = styled.div`
|
||||
.header_aside-panel {
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
|
||||
width: 500px;
|
||||
transition: unset;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "480px")});
|
||||
width: 480px;
|
||||
max-width: 480px;
|
||||
overflow-y: hidden;
|
||||
|
||||
@media (max-width: 550px) {
|
||||
width: 320px;
|
||||
transform: translateX(${(props) => (props.visible ? "0" : "320px")});
|
||||
@media (max-width: 500px) {
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
position: fixed;
|
||||
top: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100vw;
|
||||
height: calc(100vh - 64px);
|
||||
`}
|
||||
}
|
||||
${PanelStyles}
|
||||
`;
|
||||
@ -258,21 +329,6 @@ const StyledHeaderContent = styled.div`
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
|
||||
.sharing_panel-icons-container {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
.sharing_panel-drop-down-wrapper {
|
||||
position: relative;
|
||||
|
||||
.sharing_panel-drop-down {
|
||||
padding: 4px 0;
|
||||
}
|
||||
.sharing_panel-plus-icon {
|
||||
//margin-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload_panel-icons-container {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
@ -307,10 +363,6 @@ const StyledBody = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_body {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.change-owner_body {
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
@ -355,42 +407,6 @@ const StyledBody = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_links-container {
|
||||
display: flex;
|
||||
.embedding-panel_link {
|
||||
margin-right: 8px;
|
||||
height: 32px;
|
||||
background-color: ${(props) =>
|
||||
props.theme.filesPanels.body.backgroundColor};
|
||||
line-height: 30px;
|
||||
padding: 0px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_inputs-container {
|
||||
display: flex;
|
||||
|
||||
.embedding-panel_input {
|
||||
margin-right: 8px;
|
||||
width: 94px;
|
||||
}
|
||||
}
|
||||
|
||||
.embedding-panel_code-container {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.embedding-panel_text {
|
||||
padding: 8px 0 4px 0;
|
||||
}
|
||||
|
||||
.embedding-panel_copy-icon {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
margin: 8px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
.sharing-access-combo-box-icon {
|
||||
path {
|
||||
fill: ${(props) => props.theme.filesPanels.body.fill};
|
||||
@ -542,8 +558,8 @@ const StyledFooter = styled.div`
|
||||
display: flex;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
padding: 16px 0;
|
||||
width: calc(100% - 32px);
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@ -571,7 +587,7 @@ const StyledFooter = styled.div`
|
||||
}
|
||||
|
||||
@media ${desktop} {
|
||||
padding: 10px 0;
|
||||
padding: 16px;
|
||||
min-height: 57px;
|
||||
|
||||
.sharing_panel-checkbox {
|
||||
@ -723,13 +739,14 @@ const StyledModalRowContainer = styled.div`
|
||||
|
||||
.embedding-panel_links-container {
|
||||
display: flex;
|
||||
|
||||
.embedding-panel_link {
|
||||
margin-right: 8px;
|
||||
height: 32px;
|
||||
background-color: ${(props) =>
|
||||
props.theme.filesPanels.modalRow.backgroundColor};
|
||||
|
||||
border: 1px solid #eceef1;
|
||||
border-radius: 16px;
|
||||
line-height: 30px;
|
||||
padding: 0px 8px;
|
||||
padding: 4px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,6 @@ const SimpleFilesRowContent = styled(RowContent)`
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.is-editing {
|
||||
path {
|
||||
fill: ${(props) => props.theme.filesSection.rowView.editingIconColor};
|
||||
}
|
||||
}
|
||||
${(props) =>
|
||||
((props.sectionWidth <= 1024 && props.sectionWidth > 500) || isTablet) &&
|
||||
`
|
||||
|
@ -311,6 +311,8 @@ const FilesTableRow = (props) => {
|
||||
if (showHotkeyBorder) {
|
||||
setHeaderBorder(true);
|
||||
} else {
|
||||
const elem = document.getElementById("table-container_caption-header");
|
||||
if (elem) elem.style.borderColor = "#ECEEF1";
|
||||
setHeaderBorder(false);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ const StyledTile = styled.div`
|
||||
border: ${(props) => props.theme.filesSection.tilesView.tile.border};
|
||||
border-radius: 6px;
|
||||
${(props) => props.showHotkeyBorder && "border-color: #2DA7DB"};
|
||||
${(props) => props.isFolder && "border-top-left-radius: 0px;"}
|
||||
${(props) => props.isFolder && "border-top-left-radius: 6px;"}
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
|
||||
${(props) => props.isFolder && FlexBoxStyles}
|
||||
|
@ -472,7 +472,10 @@ class HotkeyStore {
|
||||
|
||||
get caretIndex() {
|
||||
const { filesList, hotkeyCaret, selection } = this.filesStore;
|
||||
const id = selection.length ? selection[0].id : hotkeyCaret?.id;
|
||||
const id =
|
||||
selection.length && selection.length === 1 && !hotkeyCaret
|
||||
? selection[0].id
|
||||
: hotkeyCaret?.id;
|
||||
const caretIndex = filesList.findIndex((f) => f.id === id);
|
||||
|
||||
if (caretIndex !== -1) return caretIndex;
|
||||
@ -522,7 +525,7 @@ class HotkeyStore {
|
||||
}
|
||||
|
||||
get prevFile() {
|
||||
const { filesList, selection, hotkeyCaret } = this.filesStore;
|
||||
const { filesList } = this.filesStore;
|
||||
|
||||
if (this.caretIndex !== -1) {
|
||||
const prevCaretIndex = this.caretIndex - 1;
|
||||
|
48
products/ASC.Files/Client/tests/duplicate-id_tests.js
Normal file
@ -0,0 +1,48 @@
|
||||
const Endpoints = require("./mocking/endpoints.js");
|
||||
|
||||
const browser = process.env.profile || "chromium";
|
||||
const isModel = !!process.env.MODEL;
|
||||
const deviceType = process.env.DEVICE_TYPE || "desktop";
|
||||
|
||||
const featureName = isModel
|
||||
? `Render test on '${browser}' with '${deviceType}' dimension (model)`
|
||||
: `Render test on '${browser}' with '${deviceType}' dimension`;
|
||||
|
||||
Feature(featureName);
|
||||
|
||||
Before(async ({ I }) => {
|
||||
I.mockEndpoint(Endpoints.self, "self");
|
||||
I.mockEndpoint(Endpoints.settings, "settings");
|
||||
I.mockEndpoint(Endpoints.build, "build");
|
||||
I.mockEndpoint(Endpoints.info, "info");
|
||||
I.mockEndpoint(Endpoints.common, "common");
|
||||
I.mockEndpoint(Endpoints.cultures, "cultures");
|
||||
I.mockEndpoint(Endpoints.root, "one");
|
||||
I.mockEndpoint(Endpoints.my, "duplicate");
|
||||
I.mockEndpoint(Endpoints.fileSettings, "default");
|
||||
I.mockEndpoint(Endpoints.getFolder(1), "1");
|
||||
I.mockEndpoint(Endpoints.capabilities, "capabilities");
|
||||
I.mockEndpoint(Endpoints.thirdparty, "thirdparty");
|
||||
I.mockEndpoint(Endpoints.thumbnails, "thumbnails");
|
||||
});
|
||||
|
||||
Scenario("Duplicate id test", async ({ I }) => {
|
||||
I.amOnPage("/products/files");
|
||||
I.wait(3);
|
||||
|
||||
if (deviceType !== "desktop") {
|
||||
I.click({ react: "SortButton" });
|
||||
I.click({ name: "view-selector-name_tile" });
|
||||
} else {
|
||||
I.click({ name: "view-selector-name_tile" });
|
||||
}
|
||||
|
||||
I.wait(3);
|
||||
I.saveScreenshot("duplicate-id-tile-view.png");
|
||||
if (!isModel) {
|
||||
I.seeVisualDiff("duplicate-id-tile-view.png", {
|
||||
tolerance: 0.16,
|
||||
prepareBaseImage: false,
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,112 @@
|
||||
{
|
||||
"count": 1,
|
||||
"response": {
|
||||
"files": [
|
||||
{
|
||||
"folderId": 1,
|
||||
"version": 1,
|
||||
"versionGroup": 1,
|
||||
"contentLength": "19.01 KB",
|
||||
"pureContentLength": 19464,
|
||||
"fileStatus": 0,
|
||||
"viewUrl": "http://192.168.31.38:8092/products/files/httphandlers/filehandler.ashx?action=download&fileid=20",
|
||||
"webUrl": "http://192.168.31.38:8092/products/files/doceditor?fileid=20&version=1",
|
||||
"fileType": 7,
|
||||
"fileExst": ".docx",
|
||||
"comment": "Uploaded",
|
||||
"thumbnailUrl": "http://192.168.31.38:8092/products/files/httphandlers/filehandler.ashx?action=thumb&fileid=20&version=1",
|
||||
"thumbnailStatus": 1,
|
||||
"canWebRestrictedEditing": false,
|
||||
"canFillForms": true,
|
||||
"id": 20,
|
||||
"rootFolderId": 1,
|
||||
"canShare": true,
|
||||
"canEdit": true,
|
||||
"title": "New document.docx",
|
||||
"access": 0,
|
||||
"shared": false,
|
||||
"created": "2022-04-06T17:34:30.0000000Z",
|
||||
"createdBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
},
|
||||
"updated": "2022-04-06T17:34:30.0000000Z",
|
||||
"rootFolderType": 5,
|
||||
"updatedBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
}
|
||||
}
|
||||
],
|
||||
"folders": [
|
||||
{
|
||||
"parentId": 1,
|
||||
"filesCount": 3,
|
||||
"foldersCount": 0,
|
||||
"new": 0,
|
||||
"id": 20,
|
||||
"rootFolderId": 1,
|
||||
"canShare": true,
|
||||
"canEdit": true,
|
||||
"title": "New folder",
|
||||
"access": 0,
|
||||
"shared": false,
|
||||
"created": "2022-04-13T08:54:10.0000000Z",
|
||||
"createdBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
},
|
||||
"updated": "2022-04-13T08:56:18.0000000Z",
|
||||
"rootFolderType": 5,
|
||||
"updatedBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
}
|
||||
}
|
||||
],
|
||||
"current": {
|
||||
"parentId": 0,
|
||||
"filesCount": 28,
|
||||
"foldersCount": 3,
|
||||
"isShareable": true,
|
||||
"new": 0,
|
||||
"id": 1,
|
||||
"rootFolderId": 1,
|
||||
"canShare": true,
|
||||
"canEdit": true,
|
||||
"title": "My documents",
|
||||
"access": 0,
|
||||
"shared": false,
|
||||
"created": "2022-04-01T12:20:35.0000000Z",
|
||||
"createdBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
},
|
||||
"updated": "2022-04-14T08:22:42.0000000Z",
|
||||
"rootFolderType": 5,
|
||||
"updatedBy": {
|
||||
"id": "6047b48f-7540-11ec-af2b-d45d64a7a0a5",
|
||||
"displayName": "Administrator",
|
||||
"avatarSmall": "/storage/userPhotos/root/6047b48f-7540-11ec-af2b-d45d64a7a0a5_size_32-32.jpeg?_=-1380565972",
|
||||
"profileUrl": "http://192.168.31.38:8092/products/people/view/administrator"
|
||||
}
|
||||
},
|
||||
"pathParts": [1],
|
||||
"startIndex": 0,
|
||||
"count": 25,
|
||||
"total": 28,
|
||||
"new": 0
|
||||
},
|
||||
"status": 0,
|
||||
"statusCode": 200
|
||||
}
|
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 27 KiB |
@ -1,3 +1,10 @@
|
||||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 2.30269C16 1.58472 15.418 1.00269 14.7 1.00269H1.3C0.58203 1.00269 0 1.58472 0 2.30269L0 14.9735C0 16.2368 1.61969 16.7578 2.35619 15.7315L3.20892 14.5432C3.45311 14.2029 3.84628 14.0011 4.26511 14.0011H14.7C15.418 14.0011 16 13.4191 16 12.7011V2.30269Z" fill="#A3A9AE"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_20763_43822)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 2.99976C0 1.89519 0.89543 0.999756 2 0.999756H14C15.1046 0.999756 16 1.89519 16 2.99976V10.9998C16 12.1043 15.1046 12.9998 14 12.9998H5.41421L3.41421 14.9998C2.15428 16.2597 0 15.3673 0 13.5855V2.99976ZM14 2.99976L2 2.99976V13.5855L4 11.5855C4.37507 11.2105 4.88378 10.9998 5.41421 10.9998H14V2.99976Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20763_43822">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 625 B |
@ -1,3 +1,10 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00504 1.99976L10.0042 5.00699L4.00172 11.0111L1.00062 8.00828L7.00504 1.99976ZM11.7793 1.40022L10.684 0.298922C10.2607 -0.126691 9.11354 -0.126691 8.50125 0.48686L7.99954 0.988305L11.0224 4.00377L11.519 3.5032C12.1076 2.9113 12.1076 1.73033 11.7793 1.40022ZM0 11.6677C0.00679371 11.8812 0.120601 12 0.342874 12H3.00156L0.00679371 9.00152L0 11.6677Z" fill="#A3A9AE"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_20768_40080)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.2929 1.29312C11.5119 0.074169 13.4882 0.0741679 14.7071 1.29312C15.9261 2.51207 15.9261 4.48838 14.7071 5.70733L5.70713 14.7073C5.57897 14.8355 5.41839 14.9264 5.24256 14.9704L1.24256 15.9704C0.901782 16.0556 0.541295 15.9557 0.292914 15.7073C0.0445341 15.459 -0.055315 15.0985 0.0298787 14.7577L1.02988 10.7577C1.07384 10.5819 1.16476 10.4213 1.29291 10.2931L10.2929 1.29312ZM13.2929 2.70733C12.855 2.26943 12.145 2.26943 11.7071 2.70733L10.9142 3.50023L12.5 5.08601L13.2929 4.29312C13.7308 3.85522 13.7308 3.14524 13.2929 2.70733ZM11.0858 6.50023L9.50002 4.91444L2.90299 11.5115L2.37439 13.6259L4.48877 13.0973L11.0858 6.50023Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20768_40080">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 522 B After Width: | Height: | Size: 954 B |
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0C0.895431 0 0 0.895431 0 2V14C0 15.1046 0.895431 16 2 16H14C15.1046 16 16 15.1046 16 14V2C16 0.895431 15.1046 0 14 0H2ZM14 2H2V5H14V2ZM2 7H14V10H2V7ZM9 12C8.44772 12 8 12.4477 8 13C8 13.5523 8.44772 14 9 14H13C13.5523 14 14 13.5523 14 13C14 12.4477 13.5523 12 13 12H9Z" fill="#A3A9AE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 1C1.89543 1 1 1.89543 1 3V13C1 14.1046 1.89543 15 3 15H13C14.1046 15 15 14.1046 15 13V3C15 1.89543 14.1046 1 13 1H3ZM3 3L13 3V13H3V3ZM4 6H12V4H4V6ZM4 9H12V7H4V9ZM8 12H12V10H8V12Z" fill="#333333"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 352 B |
@ -1,3 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 8C0 12.4183 3.58172 16 8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8ZM5.29071 12.5949C6.08473 13.0641 7.01092 13.3333 8 13.3333C10.9455 13.3333 13.3333 10.9455 13.3333 8C13.3333 7.01092 13.0641 6.08473 12.5949 5.29071L5.29071 12.5949ZM3.40509 10.7093C2.93591 9.91527 2.66667 8.98908 2.66667 8C2.66667 5.05448 5.05448 2.66667 8 2.66667C8.98908 2.66667 9.91527 2.93591 10.7093 3.40509L3.40509 10.7093Z" fill="#A3A9AE"/>
|
||||
<g clip-path="url(#clip0_20763_37010)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.4769 3.10916C9.13367 1.43923 5.85958 1.65538 3.75736 3.7576C1.65513 5.85983 1.43898 9.13391 3.10891 11.4771L11.4769 3.10916ZM12.8911 4.52337L4.52313 12.8913C6.86633 14.5613 10.1404 14.3451 12.2426 12.2429C14.3449 10.1407 14.561 6.86657 12.8911 4.52337ZM2.34315 2.34339C5.46734 -0.780804 10.5327 -0.780804 13.6569 2.34339C16.781 5.46758 16.781 10.5329 13.6569 13.6571C10.5327 16.7813 5.46734 16.7813 2.34315 13.6571C-0.781049 10.5329 -0.781049 5.46758 2.34315 2.34339Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20763_37010">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 608 B After Width: | Height: | Size: 792 B |
@ -1,3 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7 1.00269C15.418 1.00269 16 1.58472 16 2.30269V11.7011C16 12.4191 15.418 13.0011 14.7 13.0011H4.26511C3.84628 13.0011 3.45311 13.2029 3.20892 13.5432L2.35619 14.7315C1.61969 15.7578 0 15.2368 0 13.9735V2.30269C0 1.58472 0.58203 1.00269 1.3 1.00269H14.7ZM6.28642 9.68714C6.69054 10.1041 7.34657 10.1041 7.75089 9.68714L11.7259 5.82285C11.92 5.6226 12.0291 5.35091 12.0291 5.06775C12.0291 4.78458 11.92 4.51289 11.7259 4.31264C11.3216 3.89564 10.6655 3.89564 10.2614 4.31264L7.20374 7.42846C7.10149 7.53352 6.93582 7.53352 6.83377 7.42846L5.79681 6.34682C5.2987 5.99655 4.73646 5.92982 4.33234 6.34682C3.92803 6.76362 3.92803 7.44023 4.33234 7.85703L6.28642 9.68714Z" fill="#A3A9AE"/>
|
||||
<g clip-path="url(#clip0_20763_43934)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 2.99988L8.75736 2.99988L10.7574 0.999878H2C0.89543 0.999878 0 1.89531 0 2.99988V13.5857C0 15.3675 2.15428 16.2598 3.41421 14.9999L5.41421 12.9999H14C15.1046 12.9999 16 12.1044 16 10.9999V4.24252L14 6.24252V10.9999H5.41421C4.88378 10.9999 4.37507 11.2106 4 11.5857L2 13.5857V2.99988ZM14.7071 2.70698L8.20711 9.20698C7.81658 9.59751 7.18342 9.59751 6.79289 9.20699L3.79289 6.20698L5.2071 4.79277L7.5 7.08566L13.2929 1.29277L14.7071 2.70698Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20763_43934">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 839 B After Width: | Height: | Size: 762 B |
10
public/images/code.react.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_20597_65864)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.84646 0.979492L5.22299 14.5025L7.15485 15.0201L10.7783 1.49713L8.84646 0.979492ZM2.41419 7.99916L5.20702 5.20614L3.79276 3.79197L0.292868 7.2921C-0.0976332 7.68263 -0.0976212 8.31578 0.292895 8.7063L3.79278 12.2062L5.20699 10.7919L2.41419 7.99916ZM13.5857 8.00004L10.7928 5.20714L12.207 3.79292L15.707 7.29293C15.8945 7.48047 15.9999 7.73482 15.9999 8.00004C15.9999 8.26526 15.8945 8.51961 15.707 8.70715L12.2065 12.2076L10.7923 10.7934L13.5857 8.00004Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20597_65864">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 777 B |
@ -1,3 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.14502 -1.07443e-06L14.8481 -2.59613e-06C15.4812 -2.70681e-06 15.9962 0.515037 15.9962 1.14808L15.9962 9.85224C15.9962 10.4853 15.4812 11.0004 14.8481 11.0004L11.9896 11.0004L11.9896 6.03888C11.9896 4.82791 11.242 4.00369 10.031 4.00369L4.99694 4.00369L4.99694 1.14809C4.99693 0.515038 5.51194 -9.63738e-07 6.14502 -1.07443e-06ZM1.12973 4.99872L9.87024 4.99872C10.4932 4.99872 11 5.50551 11 6.12845L11 14.8703C11 15.4932 10.4932 16 9.87028 16L1.12973 16C0.50679 16 3.70837e-05 15.4932 2.6e-06 14.8703L1.07154e-06 6.12845C9.62618e-07 5.50551 0.506823 4.99872 1.12973 4.99872Z" fill="#A3A9AE"/>
|
||||
<g clip-path="url(#clip0_20707_66689)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.00001 -0.000241343C4.89544 -0.000241343 4.00001 0.895189 4.00001 1.99976L6.00001 1.99976L14 1.99976L14 9.99976L14 11.9998C15.1046 11.9998 16 11.1043 16 9.99976L16 1.99976C16 0.895189 15.1046 -0.000241343 14 -0.000241343L6.00001 -0.000241343ZM2.00001 3.99976C0.895436 3.99976 5.59506e-06 4.89519 5.59506e-06 5.99976L5.59506e-06 13.9998C5.59506e-06 15.1043 0.895437 15.9998 2.00001 15.9998L10 15.9998C11.1046 15.9998 12 15.1043 12 13.9998L12 5.99976C12 4.89519 11.1046 3.99976 10 3.99976L2.00001 3.99976ZM2.00001 13.9998L2.00001 5.99976L10 5.99976L10 13.9998L2.00001 13.9998Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_20707_66689">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 747 B After Width: | Height: | Size: 897 B |
@ -1,9 +1,9 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_17158:39464)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.49896 0L8.49896 0C9.32739 0 9.99896 0.671573 9.99896 1.5V2H10L13 2C14.1049 2 15 2.89593 15 4.00022L13 4.00022V4L10 4H8.49896L7.49896 4H6L3 4V4.00022H1C1 2.89593 1.89515 2 3 2L5.99896 2V1.5C5.99896 0.671573 6.67054 0 7.49896 0ZM3 5.00023L3 13.0002C3 14.6571 4.34315 16.0002 6 16.0002H10C11.6569 16.0002 13 14.6571 13 13.0002L13 5.00023H11L11 13.0002C11 13.5525 10.5523 14.0002 10 14.0002L6 14.0002C5.44771 14.0002 5 13.5525 5 13.0002L5 5.00023L3 5.00023ZM7 6L7 14H9V6H7Z" fill="#333333"/>
|
||||
<g clip-path="url(#clip0_20763_37019)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.49896 0H8.49896C9.32739 0 9.99896 0.671573 9.99896 1.5V2H10H13C14.1049 2 15 2.89593 15 4.00022H13V4H10H8.49896H7.49896H6H3V4.00022H1C1 2.89593 1.89515 2 3 2H5.99896V1.5C5.99896 0.671573 6.67054 0 7.49896 0ZM3 5.00023V13.0002C3 14.6571 4.34315 16.0002 6 16.0002H10C11.6569 16.0002 13 14.6571 13 13.0002V5.00023H11V13.0002C11 13.5525 10.5523 14.0002 10 14.0002H6C5.44771 14.0002 5 13.5525 5 13.0002V5.00023H3ZM7 6V14H9V6H7Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_17158:39464">
|
||||
<clipPath id="clip0_20763_37019">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
|
Before Width: | Height: | Size: 793 B After Width: | Height: | Size: 745 B |
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.49952 10.4663C3.47193 9.6138 2.66403 8.61284 2.21523 8C2.66402 7.38716 3.47193 6.3862 4.49952 5.53367C5.58351 4.63435 6.79128 4 8.00001 4C9.20874 4 10.4165 4.63435 11.5005 5.53367C12.5281 6.3862 13.336 7.38716 13.7848 8C13.336 8.61284 12.5281 9.6138 11.5005 10.4663C10.4165 11.3656 9.20874 12 8.00001 12C6.79128 12 5.58351 11.3656 4.49952 10.4663ZM8.00001 2C6.1116 2 4.45712 2.97015 3.22251 3.99443C1.97234 5.03163 1.02832 6.22746 0.542514 6.8996C0.0652547 7.55992 0.0652569 8.44008 0.542514 9.1004C1.02832 9.77254 1.97234 10.9684 3.22251 12.0056C4.45713 13.0298 6.1116 14 8.00001 14C9.88842 14 11.5429 13.0298 12.7775 12.0056C14.0277 10.9684 14.9717 9.77254 15.4575 9.1004C15.9348 8.44008 15.9348 7.55992 15.4575 6.8996C14.9717 6.22746 14.0277 5.03163 12.7775 3.99443C11.5429 2.97015 9.88842 2 8.00001 2ZM8.00001 6C6.89544 6 6.00001 6.89543 6.00001 8C6.00001 9.10457 6.89544 10 8.00001 10C9.10458 10 10 9.10457 10 8C10 6.89543 9.10458 6 8.00001 6Z" fill="#A3A9AE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.5005 10.4663C3.47291 9.6138 2.665 8.61284 2.21621 8C2.665 7.38716 3.47291 6.3862 4.5005 5.53367C5.58449 4.63435 6.79226 4 8.00099 4C9.20972 4 10.4175 4.63435 11.5015 5.53367C12.5291 6.3862 13.337 7.38716 13.7858 8C13.337 8.61284 12.5291 9.6138 11.5015 10.4663C10.4175 11.3656 9.20972 12 8.00099 12C6.79226 12 5.58449 11.3656 4.5005 10.4663ZM8.00099 2C6.11258 2 4.4581 2.97015 3.22349 3.99443C1.97331 5.03163 1.0293 6.22746 0.54349 6.8996C0.0662313 7.55992 0.0662334 8.44008 0.543491 9.1004C1.0293 9.77254 1.97331 10.9684 3.22349 12.0056C4.4581 13.0298 6.11258 14 8.00099 14C9.8894 14 11.5439 13.0298 12.7785 12.0056C14.0287 10.9684 14.9727 9.77254 15.4585 9.1004C15.9357 8.44008 15.9357 7.55992 15.4585 6.8996C14.9727 6.22746 14.0287 5.03163 12.7785 3.99443C11.5439 2.97015 9.8894 2 8.00099 2ZM8.00099 6C6.89642 6 6.00099 6.89543 6.00099 8C6.00099 9.10457 6.89642 10 8.00099 10C9.10556 10 10.001 9.10457 10.001 8C10.001 6.89543 9.10556 6 8.00099 6Z" fill="#333333"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 15C0 15.5523 0.447715 16 1 16H15C15.5523 16 16 15.5523 16 15V14.7143C16 14.162 15.5523 13.7143 15 13.7143H1C0.447715 13.7143 0 14.162 0 14.7143V15ZM0 8.14286C0 8.69514 0.447715 9.14286 1 9.14286H15C15.5523 9.14286 16 8.69514 16 8.14286V7.85714C16 7.30486 15.5523 6.85714 15 6.85714H1C0.447715 6.85714 0 7.30486 0 7.85714V8.14286ZM1 2.28571C0.447715 2.28571 0 1.838 0 1.28571V1C0 0.447716 0.447715 0 1 0H15C15.5523 0 16 0.447716 16 1V1.28571C16 1.838 15.5523 2.28571 15 2.28571H1Z" fill="#A3A9AE"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 2.5C2 2.22386 1.77614 2 1.5 2H0.5C0.223858 2 0 2.22386 0 2.5V3.5C0 3.77614 0.223858 4 0.5 4H1.5C1.77614 4 2 3.77614 2 3.5V2.5ZM16 2.5C16 2.22386 15.7761 2 15.5 2H4.5C4.22386 2 4 2.22386 4 2.5V3.5C4 3.77614 4.22386 4 4.5 4L15.5 4C15.7761 4 16 3.77614 16 3.5V2.5ZM2 7.5C2 7.22386 1.77614 7 1.5 7H0.5C0.223858 7 0 7.22386 0 7.5V8.5C0 8.77614 0.223858 9 0.5 9H1.5C1.77614 9 2 8.77614 2 8.5V7.5ZM16 7.5C16 7.22386 15.7761 7 15.5 7H4.5C4.22386 7 4 7.22386 4 7.5V8.5C4 8.77614 4.22386 9 4.5 9H15.5C15.7761 9 16 8.77614 16 8.5V7.5ZM0 12.5C0 12.2239 0.223858 12 0.5 12H1.5C1.77614 12 2 12.2239 2 12.5V13.5C2 13.7761 1.77614 14 1.5 14H0.5C0.223858 14 0 13.7761 0 13.5V12.5ZM4 12.5C4 12.2239 4.22386 12 4.5 12L15.5 12C15.7761 12 16 12.2239 16 12.5V13.5C16 13.7761 15.7761 14 15.5 14L4.5 14C4.22386 14 4 13.7761 4 13.5V12.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 653 B After Width: | Height: | Size: 984 B |
@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 0C0.447715 0 0 0.447715 0 0.999999V5.85714C0 6.40943 0.447715 6.85714 1 6.85714H5.85714C6.40943 6.85714 6.85714 6.40943 6.85714 5.85714V1C6.85714 0.447715 6.40943 0 5.85714 0H1ZM1 9.14286C0.447715 9.14286 0 9.59057 0 10.1429V15C0 15.5523 0.447715 16 1 16H5.85714C6.40943 16 6.85714 15.5523 6.85714 15V10.1429C6.85714 9.59057 6.40943 9.14286 5.85714 9.14286H1ZM9.14286 0.999999C9.14286 0.447715 9.59057 0 10.1429 0H15C15.5523 0 16 0.447715 16 1V5.85714C16 6.40943 15.5523 6.85714 15 6.85714H10.1429C9.59057 6.85714 9.14286 6.40943 9.14286 5.85714V0.999999ZM10.1429 9.14286C9.59057 9.14286 9.14286 9.59057 9.14286 10.1429V15C9.14286 15.5523 9.59057 16 10.1429 16H15C15.5523 16 16 15.5523 16 15V10.1429C16 9.59057 15.5523 9.14286 15 9.14286H10.1429Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 1C1.44772 1 1 1.44772 1 2V6C1 6.55228 1.44772 7 2 7H6C6.55228 7 7 6.55228 7 6V2C7 1.44772 6.55228 1 6 1H2ZM3.5 5C3.22386 5 3 4.77614 3 4.5V3.5C3 3.22386 3.22386 3 3.5 3H4.5C4.77614 3 5 3.22386 5 3.5V4.5C5 4.77614 4.77614 5 4.5 5H3.5ZM2 9C1.44772 9 1 9.44771 1 10V14C1 14.5523 1.44772 15 2 15H6C6.55228 15 7 14.5523 7 14V10C7 9.44771 6.55228 9 6 9H2ZM3.5 13C3.22386 13 3 12.7761 3 12.5V11.5C3 11.2239 3.22386 11 3.5 11H4.5C4.77614 11 5 11.2239 5 11.5V12.5C5 12.7761 4.77614 13 4.5 13H3.5ZM9 2C9 1.44772 9.44771 1 10 1H14C14.5523 1 15 1.44772 15 2V6C15 6.55228 14.5523 7 14 7H10C9.44771 7 9 6.55228 9 6V2ZM11.5 3C11.2239 3 11 3.22386 11 3.5V4.5C11 4.77614 11.2239 5 11.5 5H12.5C12.7761 5 13 4.77614 13 4.5V3.5C13 3.22386 12.7761 3 12.5 3H11.5ZM10 9C9.44771 9 9 9.44771 9 10V14C9 14.5523 9.44771 15 10 15H14C14.5523 15 15 14.5523 15 14V10C15 9.44771 14.5523 9 14 9H10ZM11.5 13C11.2239 13 11 12.7761 11 12.5V11.5C11 11.2239 11.2239 11 11.5 11H12.5C12.7761 11 13 11.2239 13 11.5V12.5C13 12.7761 12.7761 13 12.5 13H11.5Z" fill="#A3A9AE"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 918 B After Width: | Height: | Size: 1.2 KiB |
101
web/ASC.Web.Client/src/HOCs/withLoading.js
Normal file
@ -0,0 +1,101 @@
|
||||
import React from "react";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
|
||||
const withLoading = (WrappedComponent) => {
|
||||
const withLoading = (props) => {
|
||||
const {
|
||||
isLoadedArticleBody,
|
||||
isLoadedArticleHeader,
|
||||
isLoadedSectionHeader,
|
||||
isLoadedSubmenu,
|
||||
isLoadedLngTZSettings,
|
||||
isLoadedPortalRenaming,
|
||||
isLoadedCustomization,
|
||||
isLoadedCustomizationNavbar,
|
||||
isLoadedWelcomePageSettings,
|
||||
} = props;
|
||||
|
||||
const pathname = location.pathname;
|
||||
const index = pathname.lastIndexOf("/");
|
||||
const setting = pathname.slice(index + 1);
|
||||
|
||||
const viewMobile = isSmallTablet() || isMobileOnly;
|
||||
|
||||
const isLoadedCustomizationSettings =
|
||||
isLoadedCustomization &&
|
||||
isLoadedLngTZSettings &&
|
||||
isLoadedWelcomePageSettings &&
|
||||
isLoadedPortalRenaming &&
|
||||
isLoadedArticleBody &&
|
||||
isLoadedArticleHeader &&
|
||||
isLoadedSectionHeader &&
|
||||
isLoadedSubmenu;
|
||||
|
||||
const isLoadedCustomizationNavbarSettings =
|
||||
isLoadedCustomizationNavbar &&
|
||||
isLoadedArticleBody &&
|
||||
isLoadedArticleHeader &&
|
||||
isLoadedSectionHeader &&
|
||||
isLoadedSubmenu;
|
||||
|
||||
const isLoadedCustomizationSettingLngTZSettings =
|
||||
isLoadedArticleBody &&
|
||||
isLoadedArticleHeader &&
|
||||
isLoadedSectionHeader &&
|
||||
isLoadedLngTZSettings;
|
||||
|
||||
const isLoadedCustomizationSettingWelcomePageSettings =
|
||||
isLoadedArticleBody &&
|
||||
isLoadedArticleHeader &&
|
||||
isLoadedSectionHeader &&
|
||||
isLoadedWelcomePageSettings;
|
||||
|
||||
const isLoadedCustomizationSettingPortalRenaming =
|
||||
isLoadedArticleBody &&
|
||||
isLoadedArticleHeader &&
|
||||
isLoadedSectionHeader &&
|
||||
isLoadedPortalRenaming;
|
||||
|
||||
const isLoadedPage =
|
||||
setting === "language-and-time-zone"
|
||||
? isLoadedCustomizationSettingLngTZSettings
|
||||
: setting === "welcome-page-settings"
|
||||
? isLoadedCustomizationSettingWelcomePageSettings
|
||||
: setting === "portal-renaming"
|
||||
? isLoadedCustomizationSettingPortalRenaming
|
||||
: viewMobile
|
||||
? isLoadedCustomizationNavbarSettings
|
||||
: isLoadedCustomizationSettings;
|
||||
|
||||
return <WrappedComponent {...props} isLoadedPage={isLoadedPage} />;
|
||||
};
|
||||
|
||||
return inject(({ common }) => {
|
||||
const {
|
||||
isLoadedArticleBody,
|
||||
isLoadedArticleHeader,
|
||||
isLoadedSectionHeader,
|
||||
isLoadedSubmenu,
|
||||
isLoadedLngTZSettings,
|
||||
isLoadedPortalRenaming,
|
||||
isLoadedCustomization,
|
||||
isLoadedCustomizationNavbar,
|
||||
isLoadedWelcomePageSettings,
|
||||
} = common;
|
||||
|
||||
return {
|
||||
isLoadedArticleBody,
|
||||
isLoadedArticleHeader,
|
||||
isLoadedSectionHeader,
|
||||
isLoadedSubmenu,
|
||||
isLoadedLngTZSettings,
|
||||
isLoadedPortalRenaming,
|
||||
isLoadedCustomization,
|
||||
isLoadedCustomizationNavbar,
|
||||
isLoadedWelcomePageSettings,
|
||||
};
|
||||
})(observer(withLoading));
|
||||
};
|
||||
export default withLoading;
|
@ -535,11 +535,13 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
component={ComingSoonRoute}
|
||||
/>
|
||||
<PrivateRoute path={PAYMENTS_URL} component={PaymentsRoute} />
|
||||
<PrivateRoute
|
||||
restricted
|
||||
path={SETTINGS_URL}
|
||||
component={SettingsRoute}
|
||||
/>
|
||||
{!personal && (
|
||||
<PrivateRoute
|
||||
restricted
|
||||
path={SETTINGS_URL}
|
||||
component={SettingsRoute}
|
||||
/>
|
||||
)}
|
||||
<PrivateRoute
|
||||
exact
|
||||
allowForMe
|
||||
|
@ -121,14 +121,15 @@ const HeaderNav = ({
|
||||
settingsModule && useCallback(() => history.push(settingsUrl), []);
|
||||
|
||||
const getCurrentUserActions = useCallback(() => {
|
||||
const settings = settingsModule
|
||||
? {
|
||||
key: "SettingsBtn",
|
||||
label: t("Common:Settings"),
|
||||
onClick: onSettingsClick,
|
||||
url: settingsUrl,
|
||||
}
|
||||
: null;
|
||||
const settings =
|
||||
settingsModule && !isPersonal
|
||||
? {
|
||||
key: "SettingsBtn",
|
||||
label: t("Common:Settings"),
|
||||
onClick: onSettingsClick,
|
||||
url: settingsUrl,
|
||||
}
|
||||
: null;
|
||||
|
||||
const actions = [
|
||||
{
|
||||
|
@ -243,32 +243,35 @@ const HeaderComponent = ({
|
||||
/>
|
||||
)}
|
||||
</LinkWithoutRedirect>
|
||||
{isNavAvailable && isDesktopView && !isPersonal && (
|
||||
<StyledNavigationIconsWrapper>
|
||||
{mainModules.map((item) => {
|
||||
return (
|
||||
<React.Fragment key={item.id}>
|
||||
{item.iconUrl &&
|
||||
!item.separator &&
|
||||
item.id !== "settings" && (
|
||||
<HeaderNavigationIcon
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
data-id={item.id}
|
||||
data-link={item.link}
|
||||
active={item.id == currentProductId}
|
||||
iconUrl={item.iconUrl}
|
||||
badgeNumber={item.notifications}
|
||||
onItemClick={onItemClick}
|
||||
onBadgeClick={onBadgeClick}
|
||||
url={item.link}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</StyledNavigationIconsWrapper>
|
||||
)}
|
||||
{isNavAvailable &&
|
||||
isDesktopView &&
|
||||
!isPersonal &&
|
||||
currentProductId !== "home" && (
|
||||
<StyledNavigationIconsWrapper>
|
||||
{mainModules.map((item) => {
|
||||
return (
|
||||
<React.Fragment key={item.id}>
|
||||
{item.iconUrl &&
|
||||
!item.separator &&
|
||||
item.id !== "settings" && (
|
||||
<HeaderNavigationIcon
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
data-id={item.id}
|
||||
data-link={item.link}
|
||||
active={item.id == currentProductId}
|
||||
iconUrl={item.iconUrl}
|
||||
badgeNumber={item.notifications}
|
||||
onItemClick={onItemClick}
|
||||
onBadgeClick={onBadgeClick}
|
||||
url={item.link}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</StyledNavigationIconsWrapper>
|
||||
)}
|
||||
</Header>
|
||||
|
||||
{isNavAvailable && !isDesktopView && (
|
||||
|
@ -96,8 +96,6 @@ const commonStyle = css`
|
||||
font-family: "Open Sans", sans-serif, Arial;
|
||||
font-style: normal;
|
||||
color: ${(props) => props.theme.menuContainer.color};
|
||||
margin-left: 60px;
|
||||
margin-top: -3px;
|
||||
max-width: 300px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@ -114,6 +112,10 @@ export const StyledProfileMenu = styled(DropDownItem)`
|
||||
`;
|
||||
|
||||
export const MenuContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
height: 76px;
|
||||
background: ${(props) => props.theme.menuContainer.background};
|
||||
@ -121,15 +123,15 @@ export const MenuContainer = styled.div`
|
||||
padding: 16px;
|
||||
cursor: default;
|
||||
box-sizing: border-box;
|
||||
|
||||
.avatar {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
`;
|
||||
|
||||
MenuContainer.defaultProps = { theme: Base };
|
||||
|
||||
export const AvatarContainer = styled.div`
|
||||
display: inline-block;
|
||||
float: left;
|
||||
`;
|
||||
|
||||
export const MainLabelContainer = styled.div`
|
||||
font-size: 16px;
|
||||
line-height: 28px;
|
||||
@ -178,19 +180,20 @@ class ProfileMenu extends React.Component {
|
||||
>
|
||||
<StyledProfileMenu>
|
||||
<MenuContainer>
|
||||
<AvatarContainer>
|
||||
<Avatar
|
||||
size="medium"
|
||||
role={avatarRole}
|
||||
source={avatarSource}
|
||||
userName={displayName}
|
||||
/>
|
||||
</AvatarContainer>
|
||||
<MainLabelContainer>{displayName}</MainLabelContainer>
|
||||
<LabelContainer>{email}</LabelContainer>
|
||||
<StyledControlContainer onClick={clickOutsideAction}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
<Avatar
|
||||
className="avatar"
|
||||
size="medium"
|
||||
role={avatarRole}
|
||||
source={avatarSource}
|
||||
userName={displayName}
|
||||
/>
|
||||
<div>
|
||||
<MainLabelContainer>{displayName}</MainLabelContainer>
|
||||
<LabelContainer>{email}</LabelContainer>
|
||||
<StyledControlContainer onClick={clickOutsideAction}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
</div>
|
||||
</MenuContainer>
|
||||
</StyledProfileMenu>
|
||||
{children}
|
||||
|
@ -28,26 +28,13 @@ const HomeContainer = styled.div`
|
||||
align-items: center;
|
||||
|
||||
.home-modules {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 26px ${isMobileOnly ? "31px" : "45px"};
|
||||
|
||||
${(isTablet || isMobile) &&
|
||||
css`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
`}
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: ${isMobileOnly ? "31px" : "45px"};
|
||||
|
||||
.home-module {
|
||||
z-index: 42;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.home-error-text {
|
||||
|
@ -9,6 +9,7 @@ import { isArrayEqual } from "@appserver/components/utils/array";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
import { isMobile } from "@appserver/components/utils/device";
|
||||
import withLoading from "../../../../../../HOCs/withLoading";
|
||||
|
||||
import {
|
||||
//getKeyByLink,
|
||||
@ -19,6 +20,7 @@ import {
|
||||
} from "../../../utils";
|
||||
|
||||
import CatalogItem from "@appserver/components/catalog-item";
|
||||
import LoaderArticleBody from "./loaderArticleBody";
|
||||
|
||||
class ArticleBodyContent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -57,6 +59,12 @@ class ArticleBodyContent extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { isLoaded, tReady, setIsLoadedArticleBody } = this.props;
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) setIsLoadedArticleBody(isLoadedSetting);
|
||||
|
||||
if (!isArrayEqual(prevState.selectedKeys, this.state.selectedKeys)) {
|
||||
const { selectedKeys } = this.state;
|
||||
|
||||
@ -145,14 +153,26 @@ class ArticleBodyContent extends React.Component {
|
||||
|
||||
render() {
|
||||
const items = this.catalogItems();
|
||||
const { isLoadedPage } = this.props;
|
||||
const commonSettings = location.pathname.includes("common");
|
||||
|
||||
return <>{items}</>;
|
||||
const showLoader = commonSettings ? !isLoadedPage : false;
|
||||
|
||||
return showLoader ? <LoaderArticleBody /> : <>{items}</>;
|
||||
}
|
||||
}
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
export default inject(({ auth, common }) => {
|
||||
const { isLoaded, setIsLoadedArticleBody } = common;
|
||||
|
||||
return {
|
||||
showText: auth.settingsStore.showText,
|
||||
toggleArticleOpen: auth.settingsStore.toggleArticleOpen,
|
||||
isLoaded,
|
||||
setIsLoadedArticleBody,
|
||||
};
|
||||
})(withRouter(withTranslation("Settings")(observer(ArticleBodyContent))));
|
||||
})(
|
||||
withLoading(
|
||||
withRouter(withTranslation("Settings")(observer(ArticleBodyContent)))
|
||||
)
|
||||
);
|
||||
|
@ -15,7 +15,6 @@ const StyledLoader = styled.div`
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
padding: 0px 20px 0px;
|
||||
margin-top: -7px;
|
||||
|
||||
.loader {
|
||||
width: 216px;
|
@ -7,8 +7,9 @@ import Headline from "@appserver/common/components/Headline";
|
||||
import IconButton from "@appserver/components/icon-button";
|
||||
import GroupButtonsMenu from "@appserver/components/group-buttons-menu";
|
||||
import DropDownItem from "@appserver/components/drop-down-item";
|
||||
|
||||
import LoaderSectionHeader from "../loaderSectionHeader";
|
||||
import { tablet, desktop } from "@appserver/components/utils/device";
|
||||
import withLoading from "../../../../../../HOCs/withLoading";
|
||||
|
||||
import {
|
||||
getKeyByLink,
|
||||
@ -132,6 +133,12 @@ class SectionHeaderContent extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { isLoaded, tReady, setIsLoadedSectionHeader } = this.props;
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) setIsLoadedSectionHeader(isLoadedSetting);
|
||||
|
||||
const arrayOfParams = this.getArrayOfParams();
|
||||
|
||||
const key = getKeyByLink(arrayOfParams, settingsTree);
|
||||
@ -214,6 +221,7 @@ class SectionHeaderContent extends React.Component {
|
||||
isHeaderChecked,
|
||||
isHeaderVisible,
|
||||
selection,
|
||||
isLoadedPage,
|
||||
} = this.props;
|
||||
const { header, isCategoryOrHeader } = this.state;
|
||||
const arrayOfParams = this.getArrayOfParams();
|
||||
@ -241,6 +249,8 @@ class SectionHeaderContent extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
const commonSettings = location.pathname.includes("common");
|
||||
const showLoader = commonSettings ? !isLoadedPage : false;
|
||||
return (
|
||||
<StyledContainer isHeaderVisible={isHeaderVisible}>
|
||||
{isHeaderVisible ? (
|
||||
@ -257,6 +267,8 @@ class SectionHeaderContent extends React.Component {
|
||||
selected={menuItems[0].label}
|
||||
/>
|
||||
</div>
|
||||
) : showLoader ? (
|
||||
<LoaderSectionHeader />
|
||||
) : (
|
||||
<HeaderContainer>
|
||||
{!isCategoryOrHeader && arrayOfParams[0] && (
|
||||
@ -289,7 +301,7 @@ class SectionHeaderContent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default inject(({ auth, setup }) => {
|
||||
export default inject(({ auth, setup, common }) => {
|
||||
const { customNames } = auth.settingsStore;
|
||||
const { addUsers, removeAdmins } = setup.headerAction;
|
||||
const { toggleSelector } = setup;
|
||||
@ -304,7 +316,7 @@ export default inject(({ auth, setup }) => {
|
||||
selection,
|
||||
} = setup.selectionStore;
|
||||
const { admins, selectorIsOpen } = setup.security.accessRight;
|
||||
|
||||
const { isLoaded, setIsLoadedSectionHeader } = common;
|
||||
return {
|
||||
addUsers,
|
||||
removeAdmins,
|
||||
@ -320,9 +332,13 @@ export default inject(({ auth, setup }) => {
|
||||
toggleSelector,
|
||||
selectorIsOpen,
|
||||
selection,
|
||||
isLoaded,
|
||||
setIsLoadedSectionHeader,
|
||||
};
|
||||
})(
|
||||
withRouter(
|
||||
withTranslation(["Settings", "Common"])(observer(SectionHeaderContent))
|
||||
withLoading(
|
||||
withRouter(
|
||||
withTranslation(["Settings", "Common"])(observer(SectionHeaderContent))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -4,11 +4,11 @@ import { ArticleHeaderContent, ArticleBodyContent } from "./Article";
|
||||
import { SectionHeaderContent, SectionPagingContent } from "./Section";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Section from "@appserver/common/components/Section";
|
||||
import LoaderSectionHeader from "./Section/loaderSectionHeader";
|
||||
|
||||
const ArticleSettings = React.memo(() => {
|
||||
import withLoading from "../../../../HOCs/withLoading";
|
||||
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
|
||||
const ArticleSettings = React.memo(({ isLoadedPage }) => {
|
||||
return (
|
||||
<Article>
|
||||
<Article isLoadedPage={isLoadedPage}>
|
||||
<Article.Header>
|
||||
<ArticleHeaderContent />
|
||||
</Article.Header>
|
||||
@ -26,6 +26,7 @@ const Layout = ({
|
||||
language,
|
||||
children,
|
||||
addUsers,
|
||||
isLoadedPage,
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
currentProductId !== "settings" && setCurrentProductId("settings");
|
||||
@ -33,7 +34,7 @@ const Layout = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<ArticleSettings />
|
||||
<ArticleSettings isLoadedPage={isLoadedPage} />
|
||||
<Section withBodyScroll={true}>
|
||||
<Section.SectionHeader>
|
||||
<SectionHeaderContent />
|
||||
@ -53,9 +54,10 @@ const Layout = ({
|
||||
export default inject(({ auth, setup }) => {
|
||||
const { language, settingsStore } = auth;
|
||||
const { addUsers } = setup.headerAction;
|
||||
|
||||
return {
|
||||
language,
|
||||
setCurrentProductId: settingsStore.setCurrentProductId,
|
||||
addUsers,
|
||||
};
|
||||
})(observer(Layout));
|
||||
})(withLoading(observer(Layout)));
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import Text from "@appserver/components/text";
|
||||
@ -11,9 +11,8 @@ import withCultureNames from "@appserver/common/hoc/withCultureNames";
|
||||
import history from "@appserver/common/history";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import LoaderCustomizationNavbar from "./sub-components/loaderCustomizationNavbar";
|
||||
|
||||
import { StyledArrowRightIcon } from "../common/settingsCustomization/StyledSettings";
|
||||
|
||||
import { withRouter } from "react-router";
|
||||
const StyledComponent = styled.div`
|
||||
padding-top: 13px;
|
||||
|
||||
@ -47,15 +46,28 @@ const StyledComponent = styled.div`
|
||||
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const CustomizationNavbar = ({ t, theme, helpUrlCommonSettings }) => {
|
||||
const CustomizationNavbar = ({
|
||||
t,
|
||||
theme,
|
||||
helpUrlCommonSettings,
|
||||
isLoaded,
|
||||
tReady,
|
||||
setIsLoadedCustomizationNavbar,
|
||||
isLoadedPage,
|
||||
}) => {
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
useEffect(() => {
|
||||
if (isLoadedSetting) setIsLoadedCustomizationNavbar(isLoadedSetting);
|
||||
}, [isLoadedSetting]);
|
||||
|
||||
const onClickLink = (e) => {
|
||||
e.preventDefault();
|
||||
history.push(e.target.pathname);
|
||||
};
|
||||
|
||||
//return <LoaderCustomizationNavbar />;
|
||||
|
||||
return (
|
||||
return !isLoadedPage ? (
|
||||
<LoaderCustomizationNavbar />
|
||||
) : (
|
||||
<StyledComponent>
|
||||
<div className="category-item-wrapper">
|
||||
<div className="category-item-heading">
|
||||
@ -128,14 +140,19 @@ const CustomizationNavbar = ({ t, theme, helpUrlCommonSettings }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
export default inject(({ auth, common }) => {
|
||||
const { helpUrlCommonSettings, theme } = auth.settingsStore;
|
||||
const { isLoaded, setIsLoadedCustomizationNavbar } = common;
|
||||
return {
|
||||
theme,
|
||||
helpUrlCommonSettings,
|
||||
isLoaded,
|
||||
setIsLoadedCustomizationNavbar,
|
||||
};
|
||||
})(
|
||||
withCultureNames(
|
||||
observer(withTranslation(["Settings", "Common"])(CustomizationNavbar))
|
||||
withRouter(
|
||||
withCultureNames(
|
||||
observer(withTranslation(["Settings", "Common"])(CustomizationNavbar))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -11,6 +11,8 @@ import CustomizationNavbar from "./customization-navbar";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
import { setDocumentTitle } from "../../../../../helpers/utils";
|
||||
import LoaderDescriptionCustomization from "./sub-components/loaderDescriptionCustomization";
|
||||
import { withRouter } from "react-router";
|
||||
import withLoading from "../../../../../HOCs/withLoading";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
width: 100%;
|
||||
@ -65,9 +67,24 @@ const StyledComponent = styled.div`
|
||||
|
||||
StyledComponent.defaultProps = { theme: Base };
|
||||
|
||||
const Customization = ({ t, setIsLoadingArticleSettings }) => {
|
||||
const Customization = (props) => {
|
||||
const { t, isLoaded, tReady, setIsLoadedCustomization, isLoadedPage } = props;
|
||||
const [mobileView, setMobileView] = useState(true);
|
||||
const [isLoadingCustomization, setIsLoadingCustomization] = useState(false);
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Customization"));
|
||||
window.addEventListener("resize", checkInnerWidth);
|
||||
|
||||
return () => window.removeEventListener("resize", checkInnerWidth);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoadedSetting) {
|
||||
setIsLoadedCustomization(isLoadedSetting);
|
||||
}
|
||||
}, [isLoadedSetting]);
|
||||
|
||||
const checkInnerWidth = () => {
|
||||
if (isSmallTablet()) {
|
||||
@ -77,47 +94,35 @@ const Customization = ({ t, setIsLoadingArticleSettings }) => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Customization"));
|
||||
//TODO: Add method to get the portal name
|
||||
setIsLoadingArticleSettings(true);
|
||||
setTimeout(() => {
|
||||
setIsLoadingCustomization(false);
|
||||
setIsLoadingArticleSettings(isLoadingCustomization);
|
||||
}, 3000);
|
||||
|
||||
window.addEventListener("resize", checkInnerWidth);
|
||||
return () => window.removeEventListener("resize", checkInnerWidth);
|
||||
}, []);
|
||||
|
||||
const isMobile = !!(isSmallTablet() && mobileView);
|
||||
|
||||
return isMobile ? (
|
||||
<CustomizationNavbar />
|
||||
<CustomizationNavbar isLoadedPage={isLoadedPage} />
|
||||
) : (
|
||||
<StyledComponent>
|
||||
<div className="category-description">{`${t(
|
||||
"Settings:CustomizationDescription"
|
||||
)}`}</div>
|
||||
{/* <LoaderDescriptionCustomization /> */}
|
||||
<LanguageAndTimeZone
|
||||
isLoadingCustomization={isLoadingCustomization}
|
||||
isMobileView={isMobile}
|
||||
/>
|
||||
{!isLoadedPage ? (
|
||||
<LoaderDescriptionCustomization />
|
||||
) : (
|
||||
<div className="category-description">{`${t(
|
||||
"Settings:CustomizationDescription"
|
||||
)}`}</div>
|
||||
)}
|
||||
<LanguageAndTimeZone isMobileView={isMobile} />
|
||||
<WelcomePageSettings isMobileView={isMobile} />
|
||||
<PortalRenaming isMobileView={isMobile} />
|
||||
</StyledComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ setup }) => {
|
||||
const { setIsLoadingArticleSettings } = setup;
|
||||
export default inject(({ common }) => {
|
||||
const { isLoaded, setIsLoadedCustomization } = common;
|
||||
|
||||
return {
|
||||
setIsLoadingArticleSettings,
|
||||
isLoaded,
|
||||
setIsLoadedCustomization,
|
||||
};
|
||||
})(
|
||||
withCultureNames(
|
||||
withTranslation(["Settings", "Common"])(observer(Customization))
|
||||
withLoading(
|
||||
withRouter(withTranslation(["Settings", "Common"])(observer(Customization)))
|
||||
)
|
||||
);
|
||||
|
@ -5,15 +5,35 @@ import { withTranslation } from "react-i18next";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import config from "../../../../../../package.json";
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import Customization from "./customization";
|
||||
import WhiteLabel from "./whitelabel";
|
||||
import LoaderSubmenu from "./sub-components/loaderSubmenu";
|
||||
import withLoading from "../../../../../HOCs/withLoading";
|
||||
|
||||
const SubmenuCommon = (props) => {
|
||||
const { t, history } = props;
|
||||
const {
|
||||
t,
|
||||
history,
|
||||
isLoaded,
|
||||
tReady,
|
||||
setIsLoadedSubmenu,
|
||||
isLoadedPage,
|
||||
} = props;
|
||||
const [currentTab, setCurrentTab] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
useEffect(() => {
|
||||
const path = location.pathname;
|
||||
const currentTab = data.findIndex((item) => path.includes(item.id));
|
||||
if (currentTab !== -1) {
|
||||
setCurrentTab(currentTab);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoadedSetting) setIsLoadedSubmenu(isLoadedSetting);
|
||||
}, [isLoadedSetting]);
|
||||
|
||||
const data = [
|
||||
{
|
||||
@ -28,15 +48,6 @@ const SubmenuCommon = (props) => {
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const path = location.pathname;
|
||||
const currentTab = data.findIndex((item) => path.includes(item.id));
|
||||
if (currentTab !== -1) {
|
||||
setCurrentTab(currentTab);
|
||||
}
|
||||
//setIsLoading(true);
|
||||
}, []);
|
||||
|
||||
const onSelect = (e) => {
|
||||
history.push(
|
||||
combineUrl(
|
||||
@ -46,16 +57,23 @@ const SubmenuCommon = (props) => {
|
||||
)
|
||||
);
|
||||
};
|
||||
//TODO: isLoading
|
||||
return isLoading ? (
|
||||
<LoaderSubmenu />
|
||||
) : (
|
||||
|
||||
return (
|
||||
<Submenu
|
||||
data={data}
|
||||
startSelect={currentTab}
|
||||
onSelect={(e) => onSelect(e)}
|
||||
isLoading={!isLoadedPage}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation("Settings")(withRouter(SubmenuCommon));
|
||||
export default inject(({ common }) => {
|
||||
const { isLoaded, setIsLoadedSubmenu } = common;
|
||||
return {
|
||||
isLoaded,
|
||||
setIsLoadedSubmenu,
|
||||
};
|
||||
})(
|
||||
withLoading(withRouter(withTranslation("Settings")(observer(SubmenuCommon))))
|
||||
);
|
||||
|
@ -37,23 +37,11 @@ const StyledSettingsComponent = styled.div`
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.field-container-flex {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: inherit;
|
||||
grid-gap: inherit;
|
||||
}
|
||||
|
||||
.field-title {
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.errorText {
|
||||
position: absolute;
|
||||
font-size: 10px;
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import FieldContainer from "@appserver/components/field-container";
|
||||
import ToggleButton from "@appserver/components/toggle-button";
|
||||
import ComboBox from "@appserver/components/combobox";
|
||||
import Loader from "@appserver/components/loader";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import SaveCancelButtons from "@appserver/components/save-cancel-buttons";
|
||||
@ -11,8 +9,6 @@ import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
|
||||
import { setDocumentTitle } from "../../../../../../helpers/utils";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { LANGUAGE } from "@appserver/common/constants";
|
||||
import { convertLanguage } from "@appserver/common/utils";
|
||||
import withCultureNames from "@appserver/common/hoc/withCultureNames";
|
||||
import { LanguageTimeSettingsTooltip } from "../sub-components/common-tooltips";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import { AppServerConfig } from "@appserver/common/constants";
|
||||
@ -23,12 +19,21 @@ import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import checkScrollSettingsBlock from "../utils";
|
||||
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import LoaderCustomization from "../sub-components/loaderCustomization";
|
||||
import withLoading from "../../../../../../HOCs/withLoading";
|
||||
|
||||
const mapTimezonesToArray = (timezones) => {
|
||||
return timezones.map((timezone) => {
|
||||
return { key: timezone.id, label: timezone.displayName };
|
||||
});
|
||||
};
|
||||
|
||||
const mapCulturesToArray = (cultures, i18n) => {
|
||||
const t = i18n.getFixedT(null, "Common");
|
||||
return cultures.map((culture) => {
|
||||
return { key: culture, label: t(`Culture_${culture}`) };
|
||||
});
|
||||
};
|
||||
|
||||
const findSelectedItemByKey = (items, selectedItemKey) => {
|
||||
return items.find((item) => item.key === selectedItemKey);
|
||||
};
|
||||
@ -44,25 +49,7 @@ class LanguageAndTimeZone extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const {
|
||||
portalLanguage,
|
||||
portalTimeZoneId,
|
||||
rawTimezones,
|
||||
cultureNames,
|
||||
/*organizationName,*/
|
||||
t,
|
||||
//i18n,
|
||||
} = props;
|
||||
|
||||
const timezones = mapTimezonesToArray(rawTimezones);
|
||||
const language = findSelectedItemByKey(
|
||||
cultureNames,
|
||||
convertLanguage(portalLanguage || cultureNames[0])
|
||||
);
|
||||
const timezone = findSelectedItemByKey(
|
||||
timezones,
|
||||
portalTimeZoneId || timezones[0]
|
||||
);
|
||||
const { t } = props;
|
||||
|
||||
languageFromSessionStorage = getFromSessionStorage("language");
|
||||
languageDefaultFromSessionStorage = getFromSessionStorage(
|
||||
@ -76,13 +63,11 @@ class LanguageAndTimeZone extends React.Component {
|
||||
setDocumentTitle(t("StudioTimeLanguageSettings"));
|
||||
|
||||
this.state = {
|
||||
isLoadedData: false,
|
||||
isLoading: false,
|
||||
timezones,
|
||||
timezone: timezoneFromSessionStorage || timezone,
|
||||
timezoneDefault: timezoneDefaultFromSessionStorage || timezone,
|
||||
language: languageFromSessionStorage || language,
|
||||
languageDefault: languageDefaultFromSessionStorage || language,
|
||||
timezone: timezoneFromSessionStorage || "",
|
||||
timezoneDefault: timezoneDefaultFromSessionStorage || "",
|
||||
language: languageFromSessionStorage || "",
|
||||
languageDefault: languageDefaultFromSessionStorage || "",
|
||||
hasChanged: false,
|
||||
showReminder: false,
|
||||
hasScroll: false,
|
||||
@ -90,67 +75,85 @@ class LanguageAndTimeZone extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { languageDefault, timezoneDefault } = this.state;
|
||||
|
||||
const {
|
||||
cultureNames,
|
||||
portalLanguage,
|
||||
i18n,
|
||||
language,
|
||||
rawTimezones,
|
||||
portalTimeZoneId,
|
||||
getPortalTimezones,
|
||||
isLoaded,
|
||||
cultures,
|
||||
portalLanguage,
|
||||
tReady,
|
||||
setIsLoadedLngTZSettings,
|
||||
} = this.props;
|
||||
const { timezones, isLoadedData } = this.state;
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) {
|
||||
setIsLoadedLngTZSettings(isLoadedSetting);
|
||||
}
|
||||
|
||||
window.addEventListener("resize", this.checkInnerWidth);
|
||||
|
||||
if (!timezones.length) {
|
||||
getPortalTimezones().then(() => {
|
||||
const timezones = mapTimezonesToArray(this.props.rawTimezones);
|
||||
if (
|
||||
rawTimezones.length > 0 &&
|
||||
isLoaded === true &&
|
||||
tReady === true &&
|
||||
this.state.timezone === ""
|
||||
) {
|
||||
const timezones = mapTimezonesToArray(rawTimezones);
|
||||
|
||||
const language =
|
||||
languageFromSessionStorage ||
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) ||
|
||||
cultureNames[0];
|
||||
const timezone =
|
||||
timezoneFromSessionStorage ||
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) ||
|
||||
timezones[0];
|
||||
const timezone =
|
||||
timezoneFromSessionStorage ||
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) ||
|
||||
rawTimezones[0];
|
||||
|
||||
const languageDefault =
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) ||
|
||||
cultureNames[0];
|
||||
const timezoneDefault =
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
|
||||
const timezoneDefault =
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
|
||||
|
||||
this.setState({
|
||||
language,
|
||||
timezones,
|
||||
timezone,
|
||||
languageDefault,
|
||||
timezoneDefault,
|
||||
});
|
||||
|
||||
if (!timezoneDefault) {
|
||||
this.setState({
|
||||
timezoneDefault: timezone,
|
||||
});
|
||||
}
|
||||
if (!languageDefault) {
|
||||
this.setState({
|
||||
languageDefault: language,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
timezone,
|
||||
timezoneDefault,
|
||||
});
|
||||
}
|
||||
if (timezones.length && !isLoadedData) {
|
||||
this.setState({ isLoadedData: true });
|
||||
|
||||
if (
|
||||
cultures.length > 0 &&
|
||||
isLoaded === true &&
|
||||
tReady === true &&
|
||||
this.state.language === ""
|
||||
) {
|
||||
const cultureNames = mapCulturesToArray(cultures, i18n);
|
||||
|
||||
const language =
|
||||
languageFromSessionStorage ||
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) ||
|
||||
cultureNames[0];
|
||||
|
||||
const languageDefault =
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) || cultureNames[0];
|
||||
|
||||
this.setState({
|
||||
language,
|
||||
languageDefault,
|
||||
});
|
||||
}
|
||||
|
||||
if (!languageDefault) {
|
||||
this.setState({
|
||||
languageDefault: language,
|
||||
});
|
||||
}
|
||||
|
||||
if (timezoneDefault && languageDefault) {
|
||||
this.checkChanges();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const {
|
||||
timezones,
|
||||
timezoneDefault,
|
||||
languageDefault,
|
||||
hasScroll,
|
||||
} = this.state;
|
||||
const { timezoneDefault, languageDefault, hasScroll } = this.state;
|
||||
|
||||
const {
|
||||
i18n,
|
||||
@ -158,8 +161,66 @@ class LanguageAndTimeZone extends React.Component {
|
||||
nameSchemaId,
|
||||
getCurrentCustomSchema,
|
||||
cultureNames,
|
||||
rawTimezones,
|
||||
portalTimeZoneId,
|
||||
isLoaded,
|
||||
cultures,
|
||||
portalLanguage,
|
||||
tReady,
|
||||
setIsLoadedLngTZSettings,
|
||||
} = this.props;
|
||||
|
||||
if (isLoaded !== prevProps.isLoaded || tReady !== prevProps.tReady) {
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) {
|
||||
setIsLoadedLngTZSettings(isLoadedSetting);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
rawTimezones.length > 0 &&
|
||||
isLoaded === true &&
|
||||
tReady === true &&
|
||||
this.state.timezone === ""
|
||||
) {
|
||||
const timezones = mapTimezonesToArray(rawTimezones);
|
||||
|
||||
const timezone =
|
||||
timezoneFromSessionStorage ||
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) ||
|
||||
rawTimezones[0];
|
||||
|
||||
const timezoneDefault =
|
||||
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
|
||||
|
||||
this.setState({
|
||||
timezone,
|
||||
timezoneDefault,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
cultures.length > 0 &&
|
||||
isLoaded === true &&
|
||||
tReady === true &&
|
||||
this.state.language === ""
|
||||
) {
|
||||
const cultureNames = mapCulturesToArray(cultures, i18n);
|
||||
const language =
|
||||
languageFromSessionStorage ||
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) ||
|
||||
cultureNames[0];
|
||||
|
||||
const languageDefault =
|
||||
findSelectedItemByKey(cultureNames, portalLanguage) || cultureNames[0];
|
||||
|
||||
this.setState({
|
||||
language,
|
||||
languageDefault,
|
||||
});
|
||||
}
|
||||
|
||||
const checkScroll = checkScrollSettingsBlock();
|
||||
|
||||
window.addEventListener("resize", checkScroll);
|
||||
@ -180,9 +241,6 @@ class LanguageAndTimeZone extends React.Component {
|
||||
settingsMobile.style.display = "none";
|
||||
}
|
||||
|
||||
if (timezones.length && !prevState.isLoadedData) {
|
||||
this.setState({ isLoadedData: true });
|
||||
}
|
||||
if (language !== prevProps.language) {
|
||||
i18n
|
||||
.changeLanguage(language)
|
||||
@ -332,21 +390,24 @@ class LanguageAndTimeZone extends React.Component {
|
||||
const {
|
||||
t,
|
||||
theme,
|
||||
cultureNames,
|
||||
isMobileView,
|
||||
isLoadingCustomization,
|
||||
rawTimezones,
|
||||
cultures,
|
||||
i18n,
|
||||
isLoadedPage,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
isLoadedData,
|
||||
language,
|
||||
isLoading,
|
||||
timezones,
|
||||
timezone,
|
||||
showReminder,
|
||||
hasScroll,
|
||||
} = this.state;
|
||||
|
||||
const timezones = mapTimezonesToArray(rawTimezones);
|
||||
const cultureNames = mapCulturesToArray(cultures, i18n);
|
||||
|
||||
const tooltipLanguageTimeSettings = (
|
||||
<LanguageTimeSettingsTooltip theme={theme} t={t} />
|
||||
);
|
||||
@ -371,13 +432,6 @@ class LanguageAndTimeZone extends React.Component {
|
||||
className="dropdown-item-width"
|
||||
/>
|
||||
</FieldContainer>
|
||||
<div className="field-container-flex">
|
||||
<div className="field-title">{`${t("Automatic time zone")}`}</div>
|
||||
<ToggleButton
|
||||
className="toggle"
|
||||
onChange={() => toastr.info(<>Not implemented</>)}
|
||||
/>
|
||||
</div>
|
||||
<FieldContainer
|
||||
id="fieldContainerTimezone"
|
||||
labelText={`${t("TimeZone")}:`}
|
||||
@ -399,9 +453,8 @@ class LanguageAndTimeZone extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
//return <LoaderCustomization lngTZSettings={true} />;
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
return !isLoadedPage ? (
|
||||
<LoaderCustomization lngTZSettings={true} />
|
||||
) : (
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
@ -440,24 +493,23 @@ class LanguageAndTimeZone extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default inject(({ auth, setup }) => {
|
||||
export default inject(({ auth, setup, common }) => {
|
||||
const {
|
||||
culture,
|
||||
timezone,
|
||||
timezones,
|
||||
//cultures,
|
||||
nameSchemaId,
|
||||
organizationName,
|
||||
greetingSettings,
|
||||
//getPortalCultures,
|
||||
getPortalTimezones,
|
||||
getCurrentCustomSchema,
|
||||
cultures,
|
||||
} = auth.settingsStore;
|
||||
|
||||
const { user } = auth.userStore;
|
||||
|
||||
const { setLanguageAndTime } = setup;
|
||||
|
||||
const { isLoaded, setIsLoadedLngTZSettings } = common;
|
||||
return {
|
||||
theme: auth.settingsStore.theme,
|
||||
user,
|
||||
@ -465,17 +517,18 @@ export default inject(({ auth, setup }) => {
|
||||
portalTimeZoneId: timezone,
|
||||
language: culture,
|
||||
rawTimezones: timezones,
|
||||
//rawCultures: cultures,
|
||||
greetingSettings,
|
||||
nameSchemaId,
|
||||
organizationName,
|
||||
//getPortalCultures,
|
||||
setLanguageAndTime,
|
||||
getCurrentCustomSchema,
|
||||
getPortalTimezones,
|
||||
isLoaded,
|
||||
setIsLoadedLngTZSettings,
|
||||
cultures,
|
||||
};
|
||||
})(
|
||||
withCultureNames(
|
||||
withLoading(
|
||||
withTranslation(["Settings", "Common"])(observer(LanguageAndTimeZone))
|
||||
)
|
||||
);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Loader from "@appserver/components/loader";
|
||||
import toastr from "@appserver/components/toast/toastr";
|
||||
import HelpButton from "@appserver/components/help-button";
|
||||
import FieldContainer from "@appserver/components/field-container";
|
||||
@ -19,10 +18,18 @@ import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
|
||||
import { setDocumentTitle } from "../../../../../../helpers/utils";
|
||||
import LoaderCustomization from "../sub-components/loaderCustomization";
|
||||
import withLoading from "../../../../../../HOCs/withLoading";
|
||||
const PortalRenaming = (props) => {
|
||||
const {
|
||||
t,
|
||||
setPortalRename,
|
||||
isMobileView,
|
||||
tReady,
|
||||
isLoaded,
|
||||
setIsLoadedPortalRenaming,
|
||||
isLoadedPage,
|
||||
} = props;
|
||||
|
||||
const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
// TODO: Change false
|
||||
const [isLoadedData, setIsLoadedData] = useState(true);
|
||||
const [isLoadingPortalNameSave, setIsLoadingPortalNameSave] = useState(false);
|
||||
|
||||
const portalNameFromSessionStorage = getFromSessionStorage("portalName");
|
||||
@ -46,6 +53,8 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
const lengthNameError =
|
||||
"The account name must be between 6 and 50 characters long";
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("PortalRenaming"));
|
||||
|
||||
@ -77,6 +86,10 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoadedSetting) setIsLoadedPortalRenaming(isLoadedSetting);
|
||||
}, [isLoadedSetting]);
|
||||
|
||||
//TODO: Need a method to get the portal name
|
||||
const onSavePortalRename = () => {
|
||||
setIsLoadingPortalNameSave(true);
|
||||
@ -187,9 +200,8 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
</div>
|
||||
);
|
||||
|
||||
//return <LoaderCustomization portalRenaming={true} />;
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
return !isLoadedPage ? (
|
||||
<LoaderCustomization portalRenaming={true} />
|
||||
) : (
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
@ -225,12 +237,16 @@ const PortalRenaming = ({ t, setPortalRename, isMobileView }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth, setup }) => {
|
||||
export default inject(({ auth, setup, common }) => {
|
||||
const { theme } = auth.settingsStore;
|
||||
const { setPortalRename } = setup;
|
||||
|
||||
const { isLoaded, setIsLoadedPortalRenaming } = common;
|
||||
return {
|
||||
theme,
|
||||
setPortalRename,
|
||||
isLoaded,
|
||||
setIsLoadedPortalRenaming,
|
||||
};
|
||||
})(withTranslation(["Settings", "Common"])(observer(PortalRenaming)));
|
||||
})(
|
||||
withLoading(withTranslation(["Settings", "Common"])(observer(PortalRenaming)))
|
||||
);
|
||||
|
@ -20,6 +20,7 @@ import { isSmallTablet } from "@appserver/components/utils/device";
|
||||
import checkScrollSettingsBlock from "../utils";
|
||||
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
|
||||
import LoaderCustomization from "../sub-components/loaderCustomization";
|
||||
import withLoading from "../../../../../../HOCs/withLoading";
|
||||
|
||||
let greetingTitleFromSessionStorage = "";
|
||||
let greetingTitleDefaultFromSessionStorage = "";
|
||||
@ -45,7 +46,6 @@ class WelcomePageSettings extends React.Component {
|
||||
setDocumentTitle(t("CustomTitlesWelcome"));
|
||||
|
||||
this.state = {
|
||||
isLoadedData: false,
|
||||
isLoading: false,
|
||||
greetingTitle: greetingTitleFromSessionStorage || greetingSettings,
|
||||
greetingTitleDefault:
|
||||
@ -60,16 +60,27 @@ class WelcomePageSettings extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { isLoaded, setIsLoadedWelcomePageSettings, tReady } = this.props;
|
||||
window.addEventListener("resize", this.checkInnerWidth);
|
||||
showLoader();
|
||||
this.setState({
|
||||
isLoadedData: true,
|
||||
});
|
||||
hideLoader();
|
||||
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) setIsLoadedWelcomePageSettings(isLoadedSetting);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { isLoaded, setIsLoadedWelcomePageSettings, tReady } = this.props;
|
||||
|
||||
const { hasScroll } = this.state;
|
||||
|
||||
if (isLoaded !== prevProps.isLoaded || tReady !== prevProps.tReady) {
|
||||
const isLoadedSetting = isLoaded && tReady;
|
||||
|
||||
if (isLoadedSetting) {
|
||||
setIsLoadedWelcomePageSettings(isLoadedSetting);
|
||||
}
|
||||
}
|
||||
|
||||
const checkScroll = checkScrollSettingsBlock();
|
||||
|
||||
window.addEventListener("resize", checkScroll);
|
||||
@ -90,12 +101,6 @@ class WelcomePageSettings extends React.Component {
|
||||
settingsMobile.style.display = "none";
|
||||
}
|
||||
|
||||
if (prevState.isLoadedData !== true) {
|
||||
this.setState({
|
||||
isLoadedData: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.greetingTitleDefault) {
|
||||
this.checkChanges();
|
||||
}
|
||||
@ -217,9 +222,8 @@ class WelcomePageSettings extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, isMobileView } = this.props;
|
||||
const { t, isMobileView, isLoadedPage } = this.props;
|
||||
const {
|
||||
isLoadedData,
|
||||
greetingTitle,
|
||||
isLoadingGreetingSave,
|
||||
isLoadingGreetingRestore,
|
||||
@ -250,9 +254,8 @@ class WelcomePageSettings extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
// return <LoaderCustomization welcomePage={true} />;
|
||||
return !isLoadedData ? (
|
||||
<Loader className="pageLoader" type="rombs" size="40px" />
|
||||
return !isLoadedPage ? (
|
||||
<LoaderCustomization welcomePage={true} />
|
||||
) : (
|
||||
<StyledSettingsComponent
|
||||
hasScroll={hasScroll}
|
||||
@ -293,14 +296,21 @@ class WelcomePageSettings extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default inject(({ auth, setup }) => {
|
||||
export default inject(({ auth, setup, common }) => {
|
||||
const { greetingSettings, organizationName, theme } = auth.settingsStore;
|
||||
const { setGreetingTitle, restoreGreetingTitle } = setup;
|
||||
const { isLoaded, setIsLoadedWelcomePageSettings } = common;
|
||||
return {
|
||||
theme,
|
||||
greetingSettings,
|
||||
organizationName,
|
||||
setGreetingTitle,
|
||||
restoreGreetingTitle,
|
||||
isLoaded,
|
||||
setIsLoadedWelcomePageSettings,
|
||||
};
|
||||
})(withTranslation(["Settings", "Common"])(observer(WelcomePageSettings)));
|
||||
})(
|
||||
withLoading(
|
||||
withTranslation(["Settings", "Common"])(observer(WelcomePageSettings))
|
||||
)
|
||||
);
|
||||
|
@ -127,7 +127,6 @@ const LoaderCustomization = ({
|
||||
<Loaders.Rectangle height="32px" className="combo-box" />
|
||||
{lngTZSettings && (
|
||||
<>
|
||||
<Loaders.Rectangle height="20px" className="field-container" />
|
||||
<Loaders.Rectangle height="20px" className="title-long" />
|
||||
<Loaders.Rectangle height="32px" className="combo-box" />
|
||||
</>
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { lazy, Suspense } from "react";
|
||||
import React, { lazy, Suspense, useEffect } from "react";
|
||||
import { Route, Switch, Redirect } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import Layout from "./Layout";
|
||||
import { combineUrl } from "@appserver/common/utils";
|
||||
import AppServerConfig from "@appserver/common/constants/AppServerConfig";
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
const SecuritySettings = lazy(() => import("./categories/security/index.js"));
|
||||
const Admins = lazy(() => import("./categories/security/access-rights/admins"));
|
||||
const TfaPage = lazy(() => import("./categories/security/access-portal/tfa"));
|
||||
@ -105,7 +105,13 @@ const DATA_MANAGEMENT_URL = combineUrl(
|
||||
|
||||
const ERROR_404_URL = combineUrl(AppServerConfig.proxyURL, "/error/404");
|
||||
|
||||
const Settings = () => {
|
||||
const Settings = (props) => {
|
||||
const { loadBaseInfo } = props;
|
||||
|
||||
useEffect(() => {
|
||||
loadBaseInfo();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout key="1">
|
||||
<Suspense fallback={null}>
|
||||
@ -159,4 +165,10 @@ const Settings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withRouter(Settings);
|
||||
export default inject(({ common }) => {
|
||||
return {
|
||||
loadBaseInfo: async () => {
|
||||
await common.initSettings();
|
||||
},
|
||||
};
|
||||
})(withRouter(observer(Settings)));
|
||||
|
95
web/ASC.Web.Client/src/store/CommonStore.js
Normal file
@ -0,0 +1,95 @@
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
|
||||
import authStore from "@appserver/common/store/AuthStore";
|
||||
|
||||
class CommonStore {
|
||||
isInit = false;
|
||||
isLoaded = false;
|
||||
isLoadedArticleBody = false;
|
||||
isLoadedArticleHeader = false;
|
||||
isLoadedSectionHeader = false;
|
||||
isLoadedSubmenu = false;
|
||||
isLoadedLngTZSettings = false;
|
||||
isLoadedPortalRenaming = false;
|
||||
isLoadedCustomization = false;
|
||||
isLoadedCustomizationNavbar = false;
|
||||
isLoadedWelcomePageSettings = false;
|
||||
|
||||
constructor() {
|
||||
this.authStore = authStore;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
initSettings = async () => {
|
||||
if (this.isInit) return;
|
||||
this.isInit = true;
|
||||
|
||||
const requests = [];
|
||||
requests.push(
|
||||
authStore.settingsStore.getPortalTimezones(),
|
||||
authStore.settingsStore.getPortalCultures()
|
||||
);
|
||||
|
||||
return Promise.all(requests).finally(() => this.setIsLoaded(true));
|
||||
};
|
||||
|
||||
setIsLoadedArticleBody = (isLoadedArticleBody) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedArticleBody = isLoadedArticleBody;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedArticleHeader = (isLoadedArticleHeader) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedArticleHeader = isLoadedArticleHeader;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedSectionHeader = (isLoadedSectionHeader) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedSectionHeader = isLoadedSectionHeader;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedSubmenu = (isLoadedSubmenu) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedSubmenu = isLoadedSubmenu;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedLngTZSettings = (isLoadedLngTZSettings) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedLngTZSettings = isLoadedLngTZSettings;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedWelcomePageSettings = (isLoadedWelcomePageSettings) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedWelcomePageSettings = isLoadedWelcomePageSettings;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedPortalRenaming = (isLoadedPortalRenaming) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedPortalRenaming = isLoadedPortalRenaming;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedCustomization = (isLoadedCustomization) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedCustomization = isLoadedCustomization;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoadedCustomizationNavbar = (isLoadedCustomizationNavbar) => {
|
||||
runInAction(() => {
|
||||
this.isLoadedCustomizationNavbar = isLoadedCustomizationNavbar;
|
||||
});
|
||||
};
|
||||
|
||||
setIsLoaded = (isLoaded) => {
|
||||
this.isLoaded = isLoaded;
|
||||
};
|
||||
}
|
||||
|
||||
export default CommonStore;
|
@ -10,9 +10,6 @@ import config from "../../package.json";
|
||||
class SettingsSetupStore {
|
||||
selectionStore = null;
|
||||
authStore = null;
|
||||
|
||||
isLoadingArticleSettings = false;
|
||||
|
||||
isInit = false;
|
||||
|
||||
common = {
|
||||
@ -334,8 +331,10 @@ class SettingsSetupStore {
|
||||
return api.settings.sendOwnerChange(id);
|
||||
};
|
||||
|
||||
setIsLoadingArticleSettings = (isLoading) => {
|
||||
this.isLoadingArticleSettings = isLoading;
|
||||
getCommonThirdPartyList = async () => {
|
||||
const res = await api.settings.getCommonThirdPartyList();
|
||||
|
||||
this.setCommonThirdPartyList(res);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,14 @@ import WizardStore from "./WizardStore";
|
||||
import SettingsSetupStore from "./SettingsSetupStore";
|
||||
import ConfirmStore from "./ConfirmStore";
|
||||
import BackupStore from "./BackupStore";
|
||||
import CommonStore from "./CommonStore";
|
||||
|
||||
const paymentStore = new PaymentStore();
|
||||
const wizardStore = new WizardStore();
|
||||
const setupStore = new SettingsSetupStore();
|
||||
const confirmStore = new ConfirmStore();
|
||||
const backupStore = new BackupStore();
|
||||
const commonStore = new CommonStore();
|
||||
|
||||
const store = {
|
||||
auth: authStore,
|
||||
@ -18,6 +20,7 @@ const store = {
|
||||
setup: setupStore,
|
||||
confirm: confirmStore,
|
||||
backup: backupStore,
|
||||
common: commonStore,
|
||||
};
|
||||
|
||||
export default store;
|
||||
|