Merge branch 'feature/virtual-rooms-1.2' of github.com:ONLYOFFICE/AppServer into feature/virtual-rooms-1.2

This commit is contained in:
Viktor Fomin 2022-04-19 13:41:21 +03:00
commit ebff3a8f80
95 changed files with 1112 additions and 631 deletions

View File

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

View File

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

View File

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

View File

@ -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) => {

View File

@ -156,8 +156,7 @@ const StyledButton = styled(ButtonWrapper).attrs((props) => ({
: props.theme.button.border.base};
${(props) => props.scale && `width: 100%;`};
min-width: ${(props) =>
props.minwidth ? props.minwidth : props.theme.button.minWidth[props.size]};
min-width: ${(props) => props.minwidth && props.minwidth};
padding: ${(props) => `${props.theme.button.padding[props.size]}`};
@ -214,6 +213,8 @@ const StyledButton = styled(ButtonWrapper).attrs((props) => ({
}
.button-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import StyledButton from "./styled-selector-add-button";
import IconButton from "../icon-button";
const SelectorAddButton = (props) => {
const { isDisabled, title, className, id, style } = props;
const { isDisabled, title, className, id, style, iconName } = props;
const onClick = (e) => {
!isDisabled && props.onClick && props.onClick(e);
@ -22,7 +22,7 @@ const SelectorAddButton = (props) => {
>
<IconButton
size={14}
iconName="/static/images/actions.header.touch.react.svg"
iconName={iconName}
isFill={true}
isDisabled={isDisabled}
isClickable={!isDisabled}
@ -44,10 +44,13 @@ SelectorAddButton.propTypes = {
id: PropTypes.string,
/** Accepts css style */
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
/** Specifies the icon name */
iconName: PropTypes.string,
};
SelectorAddButton.defaultProps = {
isDisabled: false,
iconName: "/static/images/actions.header.touch.react.svg",
};
export default SelectorAddButton;

View File

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

View File

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

View File

@ -168,7 +168,7 @@ class TabContainer extends Component {
selected={activeTab === index}
isDisabled={isDisabled}
>
<Text className="title_style" fontSize="13px">
<Text fontWeight={600} className="title_style" fontSize="13px">
{item.title}
</Text>
</Label>

View File

@ -127,14 +127,6 @@ const Base = {
medium: "0 32px",
},
minWidth: {
extraSmall: "none",
small: "100px",
normalDesktop: "100px",
normalTouchscreen: "100px",
medium: "100px",
},
color: {
base: black,
baseHover: black,
@ -2442,6 +2434,13 @@ const Base = {
border: `1px solid ${grayMid}`,
borderBottom: `1px solid ${grayLightMid}`,
tile: {
background: globalColors.lightHover,
itemBackground: white,
itemBorder: grayMid,
itemActiveBorder: blueMain,
},
fill: gray,
hoverFill: grayMain,
},

View File

@ -127,14 +127,6 @@ const Dark = {
medium: "0 32px",
},
minWidth: {
extraSmall: "none",
small: "100px",
normalDesktop: "100px",
normalTouchscreen: "100px",
medium: "100px",
},
color: {
base: "#CCCCCC",
baseHover: "#FAFAFA",
@ -2453,6 +2445,13 @@ const Dark = {
border: "1px solid #474747",
borderBottom: "1px solid #474747",
tile: {
background: globalColors.black,
itemBackground: "#242424",
itemBorder: gray,
itemActiveBorder: "#eeeeee",
},
fill: "#858585",
hoverFill: "#eeeeee",
},

View File

@ -19,5 +19,6 @@
"StoringFileVersion": "Storing file versions",
"ThirdPartyBtn": "Allow users to connect third-party storages",
"ThirdPartySettings": "Connected clouds",
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created."
"UpdateOrCreate": "Update the file version for the existing file with the same name. Otherwise, a copy of the file will be created.",
"Clouds": "Clouds"
}

View File

@ -19,5 +19,6 @@
"StoringFileVersion": "Хранение версий файлов",
"ThirdPartyBtn": "Разрешить пользователям подключать сторонние хранилища",
"ThirdPartySettings": "Подключенные облака",
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла."
"UpdateOrCreate": "Обновлять версию файла для существующего файла с таким же именем. В противном случае будет создаваться копия файла.",
"Clouds": "Облака"
}

View File

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

View File

@ -53,15 +53,30 @@ const EditingWrapper = styled.div`
border-bottom: ${(props) => props.theme.filesEditingWrapper.borderBottom};
padding-bottom: 4px;
margin-top: 4px;
/* margin-left: -4px; */
`}
${(props) =>
props.viewAs === "tile" &&
`margin-right: 10px !important; margin-left: 8px;`}
css`
position: absolute;
width: calc(100% - 18px);
z-index: 1;
gap: 4px;
background-color: ${(props) =>
props.theme.filesEditingWrapper.tile.background};
border: ${(props) => props.theme.filesEditingWrapper.border};
border-radius: 0 0 6px 6px;
height: 43px;
bottom: 0;
left: 0;
right: 0;
padding: 9px 8px 9px 8px;
`}
@media ${tablet} {
height: 56px;
}
@ -96,26 +111,37 @@ const EditingWrapper = styled.div`
`}
${(props) => props.viewAs === "table" && `padding-left: 12px`}
${(props) =>
props.viewAs === "tile" &&
css`
background: #fff;
border: ${(props) =>
`1px solid ${props.theme.filesEditingWrapper.tile.itemBorder}`};
&:focus {
border: ${(props) =>
`1px solid ${props.theme.filesEditingWrapper.tile.itemActiveBorder}`};
}
`};
}
.edit-button {
margin-left: 8px;
height: 32px;
padding: 8px 7px 7px 7px;
padding: 0px 7px 0px 7px;
${(props) =>
props.viewAs === "tile" &&
css`
margin-left: 0px;
background: none;
border: 1px solid transparent;
background: #fff;
border: ${(props) =>
`1px solid ${props.theme.filesEditingWrapper.tile.itemBorder}`};
:hover {
border: ${(props) => props.theme.filesEditingWrapper.border};
}
&:last-child {
margin-left: 2px;
&:hover {
border: ${(props) =>
`1px solid ${props.theme.filesEditingWrapper.tile.itemActiveBorder}`};
}
`};
@ -125,22 +151,23 @@ const EditingWrapper = styled.div`
width: 24px;
height: 24px;
border: 1px transparent;
padding: 4px 0 0 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
:hover {
&:hover {
border: ${(props) => props.theme.filesEditingWrapper.border};
}
`}
}
.edit-ok-icon {
margin-top: -6px;
width: 16px;
height: 16px;
}
.edit-cancel-icon {
margin-top: -6px;
width: 14px;
height: 14px;
padding: 1px;

View File

@ -202,6 +202,7 @@ const PureConnectDialogContainer = (props) => {
isLoading={!tReady}
visible={visible}
zIndex={310}
displayType="modal"
onClose={onClose}
>
<ModalDialog.Header>

View File

@ -8,88 +8,78 @@ import ModalDialog from "@appserver/components/modal-dialog";
import Text from "@appserver/components/text";
import Link from "@appserver/components/link";
import { connectedCloudsTitleTranslation } from "../../../helpers/utils";
import NoUserSelect from "@appserver/components/utils/commonStyles";
import { Base } from "@appserver/components/themes";
import Button from "@appserver/components/button";
import SelectorAddButton from "@appserver/components/selector-add-button";
import { isMobile } from "react-device-detect";
const StyledServicesBlock = styled.div`
display: grid;
column-gap: 55px;
row-gap: 20px;
justify-content: center;
align-items: center;
grid-template-columns: repeat(auto-fill, 158px);
padding-top: 24px;
.service-item {
border: ${(props) => props.theme.filesThirdPartyDialog.border};
width: 158px;
height: 40px;
:hover {
cursor: pointer;
}
const StyledModalDialog = styled(ModalDialog)`
.modal-dialog-aside-body {
margin-right: -16px;
}
.service-item__svg {
${NoUserSelect}
border: ${(props) => props.theme.filesThirdPartyDialog.border};
width: 158px;
height: 40px;
.service-block {
padding-top: 20px;
display: grid;
grid-gap: 16px;
display: flex;
justify-content: center;
align-item: center;
.service-item-container {
display: flex;
:hover {
cursor: pointer;
}
.service-name-container {
display: flex;
align-items: center;
${(props) =>
!props.theme.isBase &&
css`
svg {
rect {
fill: #333333;
}
path {
fill: #ffffff;
opacity: 0.16;
.service-item__svg {
width: 24px;
height: 24px;
margin-right: 8px;
}
.kDrive {
svg {
path:nth-child(7) {
opacity: 0.5 !important;
}
path:nth-child(8) {
opacity: 0.8 !important;
}
path:nth-child(9) {
opacity: 0.8 !important;
}
path:nth-child(10) {
opacity: 0.16 !important;
}
path:nth-child(11) {
opacity: 0.16 !important;
}
}
}
`}
}
}
.kDrive {
svg {
path:nth-child(7) {
opacity: 0.5 !important;
}
path:nth-child(8) {
opacity: 0.8 !important;
}
path:nth-child(9) {
opacity: 0.8 !important;
}
path:nth-child(10) {
opacity: 0.16 !important;
}
path:nth-child(11) {
opacity: 0.16 !important;
.service-btn {
margin-left: auto;
svg {
path {
fill: #333;
}
}
}
}
}
.service-text {
display: flex;
align-items: center;
justify-content: center;
}
`;
StyledServicesBlock.defaultProps = { theme: Base };
StyledModalDialog.defaultProps = { theme: Base };
const ServiceItem = (props) => {
const { capability, t, className, ...rest } = props;
const {
t,
capability,
className,
getThirdPartyIcon,
serviceName,
onClick,
} = props;
const capabilityName = capability[0];
const capabilityLink = capability.length > 1 ? capability[1] : "";
@ -100,13 +90,38 @@ const ServiceItem = (props) => {
"data-key": capabilityName,
};
const src = getThirdPartyIcon(capabilityName);
return (
<ReactSVG
{...dataProps}
{...rest}
className={`service-item__svg ${className}`}
alt=""
/>
<div className="service-item-container">
<div className="service-name-container">
<ReactSVG
src={src}
className={`service-item__svg ${className}`}
alt=""
/>
<Text fontWeight={600} fontSize="14px">
{serviceName ? serviceName : capabilityName}
</Text>
</div>
{isMobile ? (
<SelectorAddButton
onClick={onClick}
iconName="/static/images/actions.plus.icon.react.svg"
className="service-btn"
title={t("Common:Connect")}
{...dataProps}
/>
) : (
<Button
size="small"
className="service-btn"
label={t("Common:Connect")}
onClick={onClick}
{...dataProps}
/>
)}
</div>
);
};
@ -133,6 +148,7 @@ const ThirdPartyDialog = (props) => {
getOAuthToken,
setConnectDialogVisible,
setConnectItem,
getThirdPartyIcon,
} = props;
const onClose = () => {
@ -178,17 +194,12 @@ const ThirdPartyDialog = (props) => {
setThirdPartyDialogVisible(false);
};
const yandexLogoUrl =
i18n && i18n.language === "ru-RU"
? "images/services/logo_yandex_ru.svg"
: "images/services/logo_yandex_en.svg";
return (
<ModalDialog
<StyledModalDialog
isLoading={!tReady}
visible={visible}
scale={false}
displayType="auto"
displayType="aside"
zIndex={310}
onClose={onClose}
>
@ -207,100 +218,110 @@ const ThirdPartyDialog = (props) => {
</Trans>
)}
</Text>
<StyledServicesBlock>
<div className="service-block">
{googleConnectItem && (
<ServiceItem
t={t}
capability={googleConnectItem}
onClick={onShowService}
src="images/services/logo_google-drive.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{boxConnectItem && (
<ServiceItem
t={t}
capability={boxConnectItem}
onClick={onShowService}
src="images/services/logo_box.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{dropboxConnectItem && (
<ServiceItem
t={t}
capability={dropboxConnectItem}
onClick={onShowService}
src="images/services/logo_dropbox.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{sharePointConnectItem && (
<ServiceItem
t={t}
capability={sharePointConnectItem}
onClick={onShowService}
src={"images/services/logo_sharepoint.svg"}
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{oneDriveConnectItem && (
<ServiceItem
t={t}
capability={oneDriveConnectItem}
onClick={onShowService}
src="images/services/logo_onedrive.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{sharePointConnectItem && (
{/* {sharePointConnectItem && (
<ServiceItem
t={t}
capability={sharePointConnectItem}
onClick={onShowService}
src={"images/services/logo_onedrive-for-business.svg"}
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
)} */}
{nextCloudConnectItem && (
<ServiceItem
t={t}
serviceName="Nextcloud"
capability={webDavConnectItem}
onClick={onShowService}
src="images/services/logo_nextcloud.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{ownCloudConnectItem && (
<ServiceItem
t={t}
serviceName="ownCloud"
capability={webDavConnectItem}
onClick={onShowService}
src="images/services/logo_owncloud.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{kDriveConnectItem && (
<ServiceItem
t={t}
capability={kDriveConnectItem}
onClick={onShowService}
className={"kDrive"}
src="images/services/logo_kdrive.svg"
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{yandexConnectItem && (
<ServiceItem
t={t}
capability={yandexConnectItem}
onClick={onShowService}
src={yandexLogoUrl}
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
{webDavConnectItem && (
<Text
<ServiceItem
t={t}
serviceName={t("ConnextOtherAccount")}
capability={webDavConnectItem}
onClick={onShowService}
className="service-item service-text"
data-title={webDavConnectItem[0]}
data-key={webDavConnectItem[0]}
noSelect
>
{t("ConnextOtherAccount")}
</Text>
getThirdPartyIcon={getThirdPartyIcon}
/>
)}
</StyledServicesBlock>
</div>
</ModalDialog.Body>
</ModalDialog>
</StyledModalDialog>
);
};
@ -317,6 +338,7 @@ export default inject(({ auth, settingsStore, dialogsStore }) => {
webDavConnectItem,
sharePointConnectItem,
openConnectWindow,
getThirdPartyIcon,
} = settingsStore.thirdPartyStore;
const {
setThirdPartyDialogVisible,
@ -346,5 +368,10 @@ export default inject(({ auth, settingsStore, dialogsStore }) => {
setThirdPartyDialogVisible,
getOAuthToken,
openConnectWindow,
getThirdPartyIcon,
};
})(withTranslation(["Settings", "Translations"])(observer(ThirdPartyDialog)));
})(
withTranslation(["Settings", "Translations, Common"])(
observer(ThirdPartyDialog)
)
);

View File

@ -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) &&
`

View File

@ -5,20 +5,10 @@ import Text from "@appserver/components/text";
import Link from "@appserver/components/link";
import Box from "@appserver/components/box";
import Row from "@appserver/components/row";
import RowContent from "@appserver/components/row-content";
import RowContainer from "@appserver/components/row-container";
import { withTranslation } from "react-i18next";
import EmptyFolderContainer from "../../../../components/EmptyContainer/EmptyContainer";
import BoxIcon from "../../../../../public/images/icon_box.react.svg";
import DropBoxIcon from "../../../../../public/images/icon_dropbox.react.svg";
import GoogleDriveIcon from "../../../../../public/images/icon_google_drive.react.svg";
import KDriveIcon from "../../../../../public/images/icon_kdrive.react.svg";
import NextCloudIcon from "../../../../../public/images/icon_nextcloud.react.svg";
import OneDriveIcon from "../../../../../public/images/icon_onedrive.react.svg";
import OwnCloudIcon from "../../../../../public/images/icon_owncloud.react.svg";
import SharePointIcon from "../../../../../public/images/icon_sharepoint.react.svg";
import WebDavIcon from "../../../../../public/images/icon_webdav.react.svg";
import YandexDiskIcon from "../../../../../public/images/icon_yandex_disk.react.svg";
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
import { inject, observer } from "mobx-react";
import combineUrl from "@appserver/common/utils/combineUrl";
import AppServerConfig from "@appserver/common/constants/AppServerConfig";
@ -26,37 +16,8 @@ import config from "../../../../../package.json";
import { withRouter } from "react-router";
import { connectedCloudsTypeTitleTranslation } from "../../../../helpers/utils";
import Loaders from "@appserver/common/components/Loaders";
const StyledBoxIcon = styled(BoxIcon)`
${commonIconsStyles}
`;
const StyledDropBoxIcon = styled(DropBoxIcon)`
${commonIconsStyles}
`;
const StyledGoogleDriveIcon = styled(GoogleDriveIcon)`
${commonIconsStyles}
`;
const StyledKDriveIcon = styled(KDriveIcon)`
${commonIconsStyles}
`;
const StyledNextCloudIcon = styled(NextCloudIcon)`
${commonIconsStyles}
`;
const StyledOneDriveIcon = styled(OneDriveIcon)`
${commonIconsStyles}
`;
const StyledOwnCloudIcon = styled(OwnCloudIcon)`
${commonIconsStyles}
`;
const StyledSharePointIcon = styled(SharePointIcon)`
${commonIconsStyles}
`;
const StyledWebDavIcon = styled(WebDavIcon)`
${commonIconsStyles}
`;
const StyledYandexDiskIcon = styled(YandexDiskIcon)`
${commonIconsStyles}
`;
import { tablet } from "@appserver/components/utils/device";
import { ReactSVG } from "react-svg";
const linkStyles = {
isHovered: true,
@ -66,6 +27,48 @@ const linkStyles = {
display: "flex",
};
const StyledHeader = styled.div`
display: flex;
border-bottom: 1px solid #eceef1;
padding-bottom: 12px;
@media ${tablet} {
display: none;
}
.cloud-settings-clouds {
width: 30%;
margin-right: 12px;
}
.cloud-settings-name {
display: flex;
margin-left: 6px;
width: 70%;
}
.cloud-settings-separator {
display: block;
height: 10px;
margin: 4px 8px 0 0;
z-index: 1;
border-right: 1px solid #d0d5da;
}
.cloud-settings-header_connection {
display: flex;
margin-left: -15px;
}
`;
const StyledRow = styled(Row)`
.cloud-settings-row-content {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
width: 100%;
}
`;
class ConnectClouds extends React.Component {
constructor(props) {
super(props);
@ -111,36 +114,6 @@ class ConnectClouds extends React.Component {
this.props.setConnectDialogVisible(true);
};
getThirdPartyIcon = (iconName) => {
switch (iconName) {
case "Box":
return <StyledBoxIcon size="big" />;
case "DropboxV2":
return <StyledDropBoxIcon size="big" />;
case "GoogleDrive":
return <StyledGoogleDriveIcon size="big" />;
case "OneDrive":
return <StyledOneDriveIcon size="big" />;
case "SharePoint":
return <StyledSharePointIcon size="big" />;
case "kDrive":
return <StyledKDriveIcon size="big" />;
case "Yandex":
return <StyledYandexDiskIcon size="big" />;
case "OwnCloud":
return <StyledOwnCloudIcon size="big" />;
case "NextCloud":
return <StyledNextCloudIcon size="big" />;
case "OneDriveForBusiness":
return <StyledOneDriveIcon size="big" />;
case "WebDav":
return <StyledWebDavIcon size="big" />;
default:
return;
}
};
openLocation = (e) => {
const {
myFolderId,
@ -186,6 +159,7 @@ class ConnectClouds extends React.Component {
{
key: `${index}_change`,
"data-provider-id": item.provider_id,
icon: "/static/images/access.edit.react.svg",
label: t("Translations:ThirdPartyInfo"),
onClick: this.onChangeThirdPartyInfo,
},
@ -193,6 +167,7 @@ class ConnectClouds extends React.Component {
key: `${index}_delete`,
"data-id": item.provider_id,
"data-title": item.customer_title,
icon: "/static/images/catalog.trash.react.svg",
label: t("Translations:DeleteThirdParty"),
onClick: this.onDeleteThirdParty,
},
@ -200,7 +175,7 @@ class ConnectClouds extends React.Component {
};
render() {
const { t, providers, tReady, theme } = this.props;
const { t, providers, tReady, theme, getThirdPartyIcon } = this.props;
linkStyles.color = theme.filesSettings.color;
@ -210,43 +185,53 @@ class ConnectClouds extends React.Component {
<>
<Button
size="small"
style={{ marginBottom: "8px" }}
style={{ marginBottom: "24px" }}
onClick={this.onShowThirdPartyDialog}
label={t("ConnectedCloud")}
label={t("Common:AddButton")}
primary
/>
<StyledHeader>
<Text
className="cloud-settings-clouds"
fontSize="12px"
fontWeight={600}
color="#657077"
>
{t("Clouds")}
</Text>
<div className="cloud-settings-name">
<div className="cloud-settings-separator" />
<Text fontSize="12px" fontWeight={600} color="#A3A9AE">
{t("Common:Name")}
</Text>
</div>
</StyledHeader>
<RowContainer useReactWindow={false}>
{providers.map((item, index) => {
const element = this.getThirdPartyIcon(item.provider_key);
const src = getThirdPartyIcon(item.provider_key);
const element = <ReactSVG src={src} alt="" />;
const typeTitle = connectedCloudsTypeTitleTranslation(
item.provider_key,
t
);
return (
<Row
<StyledRow
key={index}
element={element}
contextOptions={this.getContextOptions(item, index)}
>
<Box
containerMinWidth="200px"
containerWidth="100%"
displayProp="flex"
flexDirection="row"
alignItems="baseline"
alignSelf="baseline"
marginProp="auto 0"
>
<RowContent>
<Text
style={{ width: 100 }}
as="div"
type="page"
fontSize="13px"
fontWeight={600}
title={item.provider_key}
fontWeight="600"
fontSize="15px"
color={theme.filesSettings.linkColor}
//color={theme.filesSettings.linkColor}
noSelect
containerWidth="30%"
>
{tReady ? (
typeTitle
@ -254,21 +239,25 @@ class ConnectClouds extends React.Component {
<Loaders.Rectangle width="90px" height="10px" />
)}
</Text>
<div></div>
<Link
type="page"
title={item.customer_title}
color={theme.filesSettings.linkColor}
fontSize="13px"
//color={theme.filesSettings.linkColor}
color="#A3A9AE"
fontSize="11px"
fontWeight={400}
truncate={true}
data-provider-key={item.provider_key}
data-provider-id={item.provider_id}
onClick={this.openLocation}
containerWidth="70%"
>
{item.customer_title}
</Link>
</Box>
</Row>
</RowContent>
</StyledRow>
);
})}
</RowContainer>
@ -302,7 +291,11 @@ class ConnectClouds extends React.Component {
export default inject(
({ auth, filesStore, settingsStore, treeFoldersStore, dialogsStore }) => {
const { providers, capabilities } = settingsStore.thirdPartyStore;
const {
providers,
capabilities,
getThirdPartyIcon,
} = settingsStore.thirdPartyStore;
const { filter, setFirstLoad } = filesStore;
const { myFolder, commonFolder, getSubfolders } = treeFoldersStore;
const {
@ -327,6 +320,7 @@ export default inject(
setDeleteThirdPartyDialogVisible,
setRemoveItem,
getSubfolders,
getThirdPartyIcon,
homepage: config.homepage,
};

View File

@ -1,6 +1,4 @@
import React from "react";
import styled, { css } from "styled-components";
import Error403 from "studio/Error403";
import Error520 from "studio/Error520";
import ConnectClouds from "./ConnectedClouds";
@ -12,29 +10,6 @@ import TabsContainer from "@appserver/components/tabs-container";
import CommonSettings from "./CommonSettings";
import AdminSettings from "./AdminSettings";
import { tablet } from "@appserver/components/utils/device";
import { isMobile } from "react-device-detect";
const StyledContainer = styled.div`
position: absolute;
top: 3px;
width: calc(100% - 40px);
height: auto;
@media ${tablet} {
position: static;
width: calc(100% - 32px);
}
${isMobile &&
css`
position: static;
width: calc(100% - 32px);
`}
`;
const SectionBodyContent = ({
setting,
isAdmin,
@ -116,13 +91,13 @@ const SectionBodyContent = ({
) : isErrorSettings ? (
<Error520 />
) : (
<StyledContainer>
<div>
<TabsContainer
elements={elements}
onSelect={onSelect}
selectedItem={selectedTab()}
/>
</StyledContainer>
</div>
);
};

View File

@ -17,6 +17,7 @@ const PureSettings = ({
isLoadedSettingsTree,
history,
setFirstLoad,
capabilities,
tReady,
}) => {
const [title, setTitle] = useState("");
@ -55,7 +56,10 @@ const PureSettings = ({
</Section.SectionHeader>
<Section.SectionBody>
{(!isLoadedSettingsTree && isLoading) || isLoading || !tReady ? (
{(!isLoadedSettingsTree && isLoading) ||
isLoading ||
!tReady ||
!capabilities ? (
setting === "thirdParty" ? (
<Loaders.Rows />
) : (
@ -79,7 +83,12 @@ const Settings = withTranslation(["Settings", "Common"])(PureSettings);
export default inject(({ filesStore, settingsStore, treeFoldersStore }) => {
const { setFirstLoad, isLoading } = filesStore;
const { setSelectedNode } = treeFoldersStore;
const { getFilesSettings, isLoadedSettingsTree } = settingsStore;
const {
getFilesSettings,
isLoadedSettingsTree,
thirdPartyStore,
} = settingsStore;
const { capabilities } = thirdPartyStore;
return {
isLoading,
@ -87,5 +96,6 @@ export default inject(({ filesStore, settingsStore, treeFoldersStore }) => {
setFirstLoad,
setSelectedNode,
getFilesSettings,
capabilities,
};
})(withRouter(observer(Settings)));

View File

@ -2,7 +2,7 @@ import { makeAutoObservable } from "mobx";
import api from "@appserver/common/api";
class ThirdPartyStore {
capabilities = [];
capabilities = null;
providers = [];
constructor() {
@ -87,44 +87,92 @@ class ThirdPartyStore {
});
};
getThirdPartyIcon = (iconName) => {
switch (iconName) {
case "Box":
return "images/icon_box.react.svg";
case "DropboxV2":
return "images/icon_dropbox.react.svg";
case "GoogleDrive":
return "images/icon_google_drive.react.svg";
case "OneDrive":
return "images/icon_onedrive.react.svg";
case "SharePoint":
return "images/icon_sharepoint.react.svg";
case "kDrive":
return "images/icon_kdrive.react.svg";
case "Yandex":
return "images/icon_yandex_disk.react.svg";
case "OwnCloud":
return "images/icon_owncloud.react.svg";
case "NextCloud":
return "images/icon_nextcloud.react.svg";
case "OneDriveForBusiness":
return "images/icon_onedrive.react.svg";
case "WebDav":
return "images/icon_webdav.react.svg";
default:
return "";
}
};
get googleConnectItem() {
return this.capabilities.find((x) => x[0] === "GoogleDrive");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "GoogleDrive")
);
}
get boxConnectItem() {
return this.capabilities.find((x) => x[0] === "Box");
return this.capabilities && this.capabilities.find((x) => x[0] === "Box");
}
get dropboxConnectItem() {
return this.capabilities.find((x) => x[0] === "DropboxV2");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "DropboxV2")
);
}
get oneDriveConnectItem() {
return this.capabilities.find((x) => x[0] === "OneDrive");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "OneDrive")
);
}
get sharePointConnectItem() {
return this.capabilities.find((x) => x[0] === "SharePoint");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "SharePoint")
);
}
get kDriveConnectItem() {
return this.capabilities.find((x) => x[0] === "kDrive");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "kDrive")
);
}
get yandexConnectItem() {
return this.capabilities.find((x) => x[0] === "Yandex");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "Yandex")
);
}
get webDavConnectItem() {
return this.capabilities.find((x) => x[0] === "WebDav");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "WebDav")
);
}
// TODO: remove WebDav get NextCloud
get nextCloudConnectItem() {
return this.capabilities.find((x) => x[0] === "WebDav");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "WebDav")
);
}
// TODO:remove WebDav get OwnCloud
get ownCloudConnectItem() {
return this.capabilities.find((x) => x[0] === "WebDav");
return (
this.capabilities && this.capabilities.find((x) => x[0] === "WebDav")
);
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Elektron poçt uğurla dəyişdirildi",
"ChangesApplied": "Dəyişiklər tətbiq olundu",
"Connect": "Qoşulmaq",
"ContactInformation": "Əlaqə məlumatları",
"CountCodesRemaining": "qalan kodlar",
"Disconnect": "Bağlantını kəs",
@ -18,4 +17,4 @@
"Subscriptions": "Abunəliklər",
"TfaLoginSettings": "Daxilolma sazlamaları",
"TwoFactorDescription": "Bütün istifadəçilər üçün ikili audentifikasiya (kod generasiyası ilə) inzibatçı tərəfindən yandırıldı."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Имейлът беше променен успешно ",
"ChangesApplied": "Промените са приложени",
"Connect": "Свържи",
"ContactInformation": "Информация за Контакт",
"CountCodesRemaining": "кода остават",
"Disconnect": "Прекъсни връзката",
@ -18,4 +17,4 @@
"Subscriptions": "Абонаменти",
"TfaLoginSettings": "Настройки за вписване",
"TwoFactorDescription": "Двуфакторното удостоверяване чрез приложението за генериране на кодове беше активирано за всички потребители от администратора."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-mail byl úspěšně změněn ",
"ChangesApplied": "Změny jsou aplikovány",
"Connect": "Připojit",
"ContactInformation": "Kontaktní informace",
"CountCodesRemaining": "zbývající kódy",
"Disconnect": "Odpojit",
@ -18,4 +17,4 @@
"Subscriptions": "Předplatné",
"TfaLoginSettings": "Nastavení přihlášení",
"TwoFactorDescription": "Dvoufázové ověřování prostřednictvím aplikace generující kódy bylo správcem povoleno pro všechny uživatele."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-Mail wurde erfolgreich geändert",
"ChangesApplied": "Die Änderungen wurden übernommen",
"Connect": "Verbinden",
"ContactInformation": "Kontaktdaten",
"CountCodesRemaining": "Codes übrig",
"Disconnect": "Trennen Sie die Verbindung",
@ -18,4 +17,4 @@
"Subscriptions": "Abonnements",
"TfaLoginSettings": "Login-Einstellungen",
"TwoFactorDescription": "Zwei-Faktor-Authentifizierung über eine App für Generierung von Codes wurde für alle aktiviert."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Το email άλλαξε με επιτυχία",
"ChangesApplied": "Το email άλλαξε με επιτυχία",
"Connect": "Σύνδεση",
"ContactInformation": "Στοιχεία επικοινωνίας",
"CountCodesRemaining": "εναπομείναντες κωδικοί",
"Disconnect": "Αποσύνδεση",
@ -18,4 +17,4 @@
"Subscriptions": "Συνδρομές",
"TfaLoginSettings": "Ρυθμίσεις σύνδεσης",
"TwoFactorDescription": "Ο έλεγχος ταυτότητας δύο παραγόντων μέσω μιας εφαρμογής δημιουργίας κωδικών ενεργοποιήθηκε για όλους τους χρήστες από τον διαχειριστή."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Email has been changed successfully ",
"ChangesApplied": "Changes are applied",
"Connect": "Connect",
"ContactInformation": "Contact Information",
"CountCodesRemaining": "codes remaining",
"Disconnect": "Disconnect",

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "El email se ha cambiado correctamente",
"ChangesApplied": "Los cambios se han aplicado",
"Connect": "Conectar",
"ContactInformation": "Información de contacto",
"CountCodesRemaining": "códigos restantes",
"Disconnect": "Desconectar",
@ -18,4 +17,4 @@
"Subscriptions": "Suscripciones",
"TfaLoginSettings": "Ajustes de acceso",
"TwoFactorDescription": "El administrador ha habilitado la autenticación de dos factores a través de una aplicación que genera códigos para todos los usuarios."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Sähköpostin vaihtaminen onnistui ",
"ChangesApplied": "Muutokset otetaan käyttöön",
"Connect": "Yhdistä",
"ContactInformation": "Yhteystiedot",
"CountCodesRemaining": "Jäljellä olevat koodit",
"Disconnect": "Katkaise",
@ -18,4 +17,4 @@
"Subscriptions": "Tilaukset",
"TfaLoginSettings": "Kirjautumisasetukset",
"TwoFactorDescription": "Järjestelmänvalvoja otti käyttöön kaksivaiheisen todennuksen koodia luovan sovelluksen kautta kaikille käyttäjille."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "L'adresse E-mail a été modifiée avec succès.",
"ChangesApplied": "Changements appliqués",
"Connect": "Connexion",
"ContactInformation": "Informations de contact",
"CountCodesRemaining": "Codes restants",
"Disconnect": "Déconnecter",
@ -18,4 +17,4 @@
"Subscriptions": "Abonnements",
"TfaLoginSettings": "Paramètres de connexion",
"TwoFactorDescription": "L'authentification à deux facteurs via une application générant des codes a été activée pour tous les utilisateurs par l'administrateur."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "L'indirizzo e-mail è stato modificato con successo",
"ChangesApplied": "Le modifiche sono state applicate",
"Connect": "Collega",
"ContactInformation": "Informazioni di contatto",
"CountCodesRemaining": "codici rimanenti",
"Disconnect": "Scollega",
@ -18,4 +17,4 @@
"Subscriptions": "Sottoscrizione",
"TfaLoginSettings": "Impostazioni di accesso",
"TwoFactorDescription": "L'autenticazione a due fattori tramite un'app che genera codice è stata attivata per tutti gli utenti dall'amministratore."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "メールの変更が完了しました 。",
"ChangesApplied": "変更が適用されました。",
"Connect": "接続",
"ContactInformation": "連絡先",
"CountCodesRemaining": "残されたコード",
"Disconnect": "接続解除",
@ -18,4 +17,4 @@
"Subscriptions": "サブスクリプション",
"TfaLoginSettings": "ログイン設定",
"TwoFactorDescription": "管理者がすべてのユーザーに対して、コード生成アプリによる二要素認証を有効にしました。"
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "이메일이 성공적으로 변경되었습니다",
"ChangesApplied": "변경 사항이 적용되었습니다",
"Connect": "연결",
"ContactInformation": "연락처 정보",
"CountCodesRemaining": "남은 코드",
"Disconnect": "연결 해제",
@ -18,4 +17,4 @@
"Subscriptions": "구독",
"TfaLoginSettings": "로그인 설정",
"TwoFactorDescription": "관리자에 의해 코드 생성 앱을 통한 이중 인증이 모든 사용자에 대해 활성화됩니다."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "ອີເມວໄດ້ຖືກປ່ຽນແປງແລ້ວ",
"ChangesApplied": "ນຳໃຊ້ການປ່ຽນແປງ",
"Connect": "ຕິດຕໍ່",
"ContactInformation": "ຂໍ້​ມູນ​ຕິດ​ຕໍ່",
"CountCodesRemaining": "ລະຫັດທີ່ເຫລື່ອ",
"Disconnect": "ຕັດການເຊື່ອມຕໍ່",
@ -18,4 +17,4 @@
"Subscriptions": "ການສະໝັກຮັບຂໍ້ມູນ",
"TfaLoginSettings": "ຕັ້ງຄ່າການເຂົ້າລະບົບ",
"TwoFactorDescription": "ການຢືນຢັນຕົວຕົນສອງຂັ້ນຕອນຜ່ານແອັບພລິເຄຊັນທີ່ສ້າງລະຫັດໄດ້ຖືກເປີດໂດຍ Admin."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-pasts ir veiksmīgi mainīts",
"ChangesApplied": "Izmaiņas ir piemērotas",
"Connect": "Savienot",
"ContactInformation": "Kontaktinformācija",
"CountCodesRemaining": "atlikušie kodi",
"Disconnect": "Atvienot",
@ -18,4 +17,4 @@
"Subscriptions": "Abonementi",
"TfaLoginSettings": "Pieteikšanās iestatījumi",
"TwoFactorDescription": "Administrators visiem lietotājiem ir iespējojis divu faktoru autentifikāciju, izmantojot kodu ģenerējošu lietotni."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-mail is met succes gewijzigd ",
"ChangesApplied": "Wijzigingen worden toegepast",
"Connect": "Verbinden",
"ContactInformation": "Contactinformatie",
"CountCodesRemaining": "resterende codes",
"Disconnect": "Loskoppelen",
@ -18,4 +17,4 @@
"Subscriptions": "Abonnementen",
"TfaLoginSettings": "Inlog instellingen",
"TwoFactorDescription": "Two-factor authenticatie via een code-genererende app was ingeschakeld voor alle gebruikers door de beheerder."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-mail został pomyślnie zmieniony ",
"ChangesApplied": "Zmiany zostały zastosowane",
"Connect": "Podłącz",
"ContactInformation": "Dane kontaktowe",
"CountCodesRemaining": "Pozostało kodów:",
"Disconnect": "Rozłącz",
@ -18,4 +17,4 @@
"Subscriptions": "Subskrypcje",
"TfaLoginSettings": "Ustawienia logowania",
"TwoFactorDescription": "Weryfikacja dwuetapowa za pośrednictwem aplikacji generującej kody została włączona przez administratora dla wszystkich użytkowników."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "O e-mail foi alterado com sucesso",
"ChangesApplied": "Alterações são aplicadas",
"Connect": "Conectar",
"ContactInformation": "Informação de Contato",
"CountCodesRemaining": "códigos restantes",
"Disconnect": "Desconectar",
@ -18,4 +17,4 @@
"Subscriptions": "Assinaturas",
"TfaLoginSettings": "Ajustes de acesso",
"TwoFactorDescription": "A autenticação de dois fatores por meio de um aplicativo de geração de código foi habilitada para todos os usuários pelo administrador."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "O e-mail foi alterado com êxito",
"ChangesApplied": "As alterações são aplicadas",
"Connect": "Ligar",
"ContactInformation": "Informação de contacto",
"CountCodesRemaining": "códigos restantes",
"Disconnect": "Desligar",
@ -18,4 +17,4 @@
"Subscriptions": "Subscrições",
"TfaLoginSettings": "Definições de acesso",
"TwoFactorDescription": "A autenticação de dois fatores através de uma aplicação geradora de códigos foi ativada para todos os utilizadores pelo administrador."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Adresa e-mail a fost modificată cu succes",
"ChangesApplied": "Modificările au fost aplicate",
"Connect": "Adaugă cont",
"ContactInformation": "Informații de contact",
"CountCodesRemaining": "codurile rămase ",
"Disconnect": "Deconectare",
@ -18,4 +17,4 @@
"Subscriptions": "Subscripții",
"TfaLoginSettings": "Setări de conexiune",
"TwoFactorDescription": "Autentificarea cu doi factori prin aplicația de generare coduri a fost activată pentru toți utilizatorii de către administratorul."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Email успешно изменен",
"ChangesApplied": "Изменения успешно применены",
"Connect": "Подключить",
"ContactInformation": "Контактные данные",
"CountCodesRemaining": "оставшиеся коды",
"Disconnect": "Отключить",
@ -18,4 +17,4 @@
"Subscriptions": "Подписки",
"TfaLoginSettings": "Настройки входа",
"TwoFactorDescription": "Двухфакторная аутентификация с помощью приложения для генерации кодов включена администратором для всех пользователей."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-mail bol úspešne zmenený ",
"ChangesApplied": "Zmeny boli vykonané",
"Connect": "Pripojiť",
"ContactInformation": "Kontaktné informácie",
"CountCodesRemaining": "zostávajúce kódy",
"Disconnect": "Odpojiť",
@ -18,4 +17,4 @@
"Subscriptions": "Predplatné",
"TfaLoginSettings": "Nastavenia prihlasovania",
"TwoFactorDescription": "Správca povolil všetkým používateľom dvojfaktorovú autentifikáciu prostredníctvom aplikácie generujúcej kód."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-mail naslov je bil uspešno spremenjen ",
"ChangesApplied": "Spremembe so uporabljene",
"Connect": "Poveži",
"ContactInformation": "Kontaktne informacije",
"CountCodesRemaining": "preostale kode",
"Disconnect": "Prekinitev",
@ -18,4 +17,4 @@
"Subscriptions": "Naročnine",
"TfaLoginSettings": "Nastavitve za prijavo",
"TwoFactorDescription": "Administrator je za vse uporabnike omogočil dvofaktorsko avtentikacijo preko aplikacije za ustvarjanje kode."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "E-posta başarıyla değiştirildi ",
"ChangesApplied": "Değişiklikler uygulandı",
"Connect": "Bağlan",
"ContactInformation": "İletişim bilgileri",
"CountCodesRemaining": "kalan kodlar",
"Disconnect": "Bağlantıyı kes",
@ -18,4 +17,4 @@
"Subscriptions": "Abonelikler",
"TfaLoginSettings": "Giriş ayarları",
"TwoFactorDescription": "Tüm kullanıcılar için kod üreten bir uygulama aracılığıyla iki faktörlü kimlik doğrulama yönetici tarafından etkinleştirildi."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Електронну пошту успішно змінено ",
"ChangesApplied": "Зміни застосовано",
"Connect": "Підключити",
"ContactInformation": "Контактна інформація",
"CountCodesRemaining": "кодів залишилося",
"Disconnect": "Відключити",
@ -18,4 +17,4 @@
"Subscriptions": "Підписки",
"TfaLoginSettings": "Параметри входу",
"TwoFactorDescription": "Двофакторна автентифікація за допомогою програми генерування кодів була ввімкнена для всіх користувачів адміністратором."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "Email đã được thay đổi thành công",
"ChangesApplied": "Thay đổi đã được áp dụng",
"Connect": "Kết nối",
"ContactInformation": "Thông tin liên hệ",
"CountCodesRemaining": "mã còn lại",
"Disconnect": "Ngắt kết nối",
@ -18,4 +17,4 @@
"Subscriptions": "Đăng ký",
"TfaLoginSettings": "Thiết lập đăng nhập ",
"TwoFactorDescription": " Xác thực hai yếu tố qua ứng dụng tạo mã đã được quản trị viên bật cho tất cả người dùng."
}
}

View File

@ -1,7 +1,6 @@
{
"ChangeEmailSuccess": "邮箱已成功更改",
"ChangesApplied": "已应用更改",
"Connect": "连接",
"ContactInformation": "联系信息",
"CountCodesRemaining": "剩余代码",
"Disconnect": "断开连接",
@ -18,4 +17,4 @@
"Subscriptions": "订阅",
"TfaLoginSettings": "登录设置",
"TwoFactorDescription": "管理员为所有用户启用了通过代码生成应用进行的双因素身份认证功能。"
}
}

View File

@ -314,7 +314,7 @@ class SectionBodyContent extends React.PureComponent {
onClick={(e) => this.linkAccount(item.provider, item.url, e)}
isHovered={true}
>
{t("Connect")}
{t("Common:Connect")}
</Link>
</div>
)}

View 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="M9 7V1H7V7H1V9H7V15H9V9H15V7H9Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 202 B

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Baxın",
"ViewWeb": "Veb versiyaya baxın",
"Warning": "Xəbərdarlıq"
"Warning": "Xəbərdarlıq",
"Connect": "Qoşulmaq"
}

View File

@ -145,5 +145,6 @@
"Video": "Видео",
"View": "Преглед",
"ViewWeb": "Отиди към уеб версия",
"Warning": "Внимание"
"Warning": "Внимание",
"Connect": "Свържи"
}

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Zobrazit",
"ViewWeb": "Zobrazit webovou verzi",
"Warning": "Varování"
"Warning": "Varování",
"Connect": "Připojit"
}

View File

@ -150,5 +150,6 @@
"Video": "Video",
"View": "Anzeigen",
"ViewWeb": "Web-Version öffnen",
"Warning": "Warnung"
"Warning": "Warnung",
"Connect": "Verbinden"
}

View File

@ -145,5 +145,6 @@
"Video": "Βίντεο",
"View": "Προβολή",
"ViewWeb": "Προβολή διαδικτυακής έκδοσης",
"Warning": "Προειδοποίηση"
"Warning": "Προειδοποίηση",
"Connect": "Σύνδεση"
}

View File

@ -157,5 +157,6 @@
"Video": "Video",
"View": "View",
"ViewWeb": "View web version",
"Warning": "Warning"
"Warning": "Warning",
"Connect": "Connect"
}

View File

@ -145,5 +145,6 @@
"Video": "Vídeo",
"View": "Ver",
"ViewWeb": "Ver versión web",
"Warning": "Advertencia"
"Warning": "Advertencia",
"Connect": "Conectar"
}

View File

@ -144,5 +144,6 @@
"Video": "Video",
"View": "Näkymä",
"ViewWeb": "Näytä verkkoversio",
"Warning": "Varoitus"
"Warning": "Varoitus",
"Connect": "Yhdistä"
}

View File

@ -150,5 +150,6 @@
"Video": "Vidéo",
"View": "Afficher",
"ViewWeb": "Voir la version web",
"Warning": "Attention"
"Warning": "Attention",
"Connect": "Connexion"
}

View File

@ -150,5 +150,6 @@
"Video": "Video",
"View": "Visualizza",
"ViewWeb": "Visualizza la versione web",
"Warning": "Avviso"
"Warning": "Avviso",
"Connect": "Collega"
}

View File

@ -145,5 +145,6 @@
"Video": "動画",
"View": "ビュー",
"ViewWeb": "ウェブ版を表示する",
"Warning": "警告"
"Warning": "警告",
"Connect": "接続"
}

View File

@ -145,5 +145,6 @@
"Video": "동영상",
"View": "보기",
"ViewWeb": "웹 버전 보기",
"Warning": "경고"
"Warning": "경고",
"Connect": "연결"
}

View File

@ -145,5 +145,6 @@
"Video": "ວິດີໂອ",
"View": "ມຸມມອງ",
"ViewWeb": "ເປີດຜ່ານຫນ້າເວັບ",
"Warning": "ແຈ້ງເຕືອນ"
"Warning": "ແຈ້ງເຕືອນ",
"Connect": "ຕິດຕໍ່"
}

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Skatīt",
"ViewWeb": "Skatīt tīmekļa versiju",
"Warning": "Brīdinājums"
"Warning": "Brīdinājums",
"Connect": "Savienot"
}

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Bekijk",
"ViewWeb": "Webversie bekijken",
"Warning": "Waarschuwing"
"Warning": "Waarschuwing",
"Connect": "Verbinden"
}

View File

@ -145,5 +145,6 @@
"Video": "Wideo",
"View": "Podgląd",
"ViewWeb": "Zobacz wersję internetową",
"Warning": "Ostrzeżenie"
"Warning": "Ostrzeżenie",
"Connect": "Podłącz"
}

View File

@ -150,5 +150,6 @@
"Video": "Vídeo",
"View": "Ver",
"ViewWeb": "Veja a versão web",
"Warning": "Aviso"
"Warning": "Aviso",
"Connect": "Conectar"
}

View File

@ -144,5 +144,6 @@
"Video": "Vídeo",
"View": "Ver",
"ViewWeb": "Ver versão web",
"Warning": "Aviso"
"Warning": "Aviso",
"Connect": "Ligar"
}

View File

@ -147,5 +147,6 @@
"Video": "Video",
"View": "Vizualizare",
"ViewWeb": "Accesați versiunea online",
"Warning": "Avertisment"
"Warning": "Avertisment",
"Connect": "Adaugă cont"
}

View File

@ -157,5 +157,6 @@
"Video": "Видео",
"View": "Просмотр",
"ViewWeb": "Просмотреть веб-версию",
"Warning": "Внимание"
"Warning": "Внимание",
"Connect": "Подключить"
}

View File

@ -148,5 +148,6 @@
"Video": "Video",
"View": "Vyhliadka",
"ViewWeb": "Zobraziť webovú verziu",
"Warning": "Upozornenie"
"Warning": "Upozornenie",
"Connect": "Pripojiť"
}

View File

@ -144,5 +144,6 @@
"Video": "Video",
"View": "Ogled",
"ViewWeb": "Ogled spletne verzije",
"Warning": "Opozorilo"
"Warning": "Opozorilo",
"Connect": "Poveži"
}

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Görüntüle",
"ViewWeb": "Web sürümünü görüntüle",
"Warning": "Uyarı"
"Warning": "Uyarı",
"Connect": "Bağlan"
}

View File

@ -145,5 +145,6 @@
"Video": "Відео",
"View": "Переглянути",
"ViewWeb": "Переглянути веб-версію",
"Warning": "Попередження"
"Warning": "Попередження",
"Connect": "Підключити"
}

View File

@ -145,5 +145,6 @@
"Video": "Video",
"View": "Xem",
"ViewWeb": "Xem phiên bản web",
"Warning": "Cảnh báo"
"Warning": "Cảnh báo",
"Connect": "Kết nối"
}

View File

@ -145,5 +145,6 @@
"Video": "视频",
"View": "查看",
"ViewWeb": "查看网页版",
"Warning": "警告"
"Warning": "警告",
"Connect": "连接"
}

View 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;

View File

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

View File

@ -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 = [
{

View File

@ -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,27 @@ class ArticleBodyContent extends React.Component {
render() {
const items = this.catalogItems();
const { isLoadedPage } = this.props;
const commonSettings = location.pathname.includes("common");
// TODO: styles fix
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)))
)
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@ 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 +10,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 +20,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 +50,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 +64,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 +76,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 +162,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 +242,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 +391,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} />
);
@ -399,9 +461,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 +501,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 +525,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))
)
);

View File

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

View File

@ -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:
@ -61,15 +61,17 @@ class WelcomePageSettings extends React.Component {
componentDidMount() {
window.addEventListener("resize", this.checkInnerWidth);
showLoader();
this.setState({
isLoadedData: true,
});
hideLoader();
}
componentDidUpdate(prevProps, prevState) {
const { isLoaded, setIsLoadedWelcomePageSettings, tReady } = this.props;
const { hasScroll } = this.state;
const isLoadedSetting = isLoaded && tReady;
if (isLoadedSetting) setIsLoadedWelcomePageSettings(isLoadedSetting);
const checkScroll = checkScrollSettingsBlock();
window.addEventListener("resize", checkScroll);
@ -90,12 +92,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 +213,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 +245,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 +287,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))
)
);

View File

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

View 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;

View File

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

View File

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