Merge branch 'develop' into feature/access-drop-down

This commit is contained in:
Nikita Gopienko 2023-04-18 16:19:44 +03:00
commit b75258bb90
155 changed files with 3181 additions and 3786 deletions

View File

@ -21,7 +21,7 @@ export default function withBadges(WrappedComponent) {
item,
setIsVerHistoryPanel,
fetchFileVersions,
history,
isTrashFolder,
} = this.props;
if (isTrashFolder) return;

View File

@ -1,6 +1,7 @@
import React, { useEffect } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { observer, inject } from "mobx-react";
import { useNavigate } from "react-router-dom";
import { Events } from "@docspace/common/constants";
import toastr from "@docspace/components/toast/toastr";
import throttle from "lodash/throttle";
@ -9,7 +10,7 @@ const withHotkeys = (Component) => {
const WithHotkeys = (props) => {
const {
t,
history,
setSelected,
viewAs,
setViewAs,
@ -60,6 +61,8 @@ const withHotkeys = (Component) => {
setInviteUsersWarningDialogVisible,
} = props;
const navigate = useNavigate();
const hotkeysFilter = {
filter: (ev) =>
ev.target?.type === "checkbox" || ev.target?.tagName !== "INPUT",
@ -330,7 +333,7 @@ const withHotkeys = (Component) => {
"Shift+u",
() => {
if (folderWithNoAction) return;
uploadFile(false, history, t);
uploadFile(false, navigate, t);
},
hotkeysFilter

View File

@ -1,5 +1,11 @@
import React, { useEffect } from "react";
import { Router, Switch, Route, Redirect } from "react-router-dom";
import {
BrowserRouter as Router,
Routes,
Route,
Navigate,
useLocation,
} from "react-router-dom";
import { inject, observer } from "mobx-react";
import NavMenu from "./components/NavMenu";
import Main from "./components/Main";
@ -8,7 +14,6 @@ import PublicRoute from "@docspace/common/components/PublicRoute";
import ErrorBoundary from "@docspace/common/components/ErrorBoundary";
import Layout from "./components/Layout";
import ScrollToTop from "./components/Layout/ScrollToTop";
import history from "@docspace/common/history";
import Toast from "@docspace/components/toast";
import toastr from "@docspace/components/toast/toastr";
import { getLogoFromPath, updateTempContent } from "@docspace/common/utils";
@ -40,20 +45,22 @@ const Wizard = React.lazy(() => import("./pages/Wizard"));
const PortalSettings = React.lazy(() => import("./pages/PortalSettings"));
const Confirm = !IS_PERSONAL && React.lazy(() => import("./pages/Confirm"));
// const MyProfile = React.lazy(() => import("./pages/My"));
const PreparationPortal = React.lazy(() => import("./pages/PreparationPortal"));
const PortalUnavailable = React.lazy(() => import("./pages/PortalUnavailable"));
const FormGallery = React.lazy(() => import("./pages/FormGallery"));
const ErrorUnavailable = React.lazy(() => import("./pages/Errors/Unavailable"));
const PortalSettingsRoute = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
<PortalSettings {...props} />
</ErrorBoundary>
</React.Suspense>
);
const PortalSettingsRoute = (props) => {
return (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
<PortalSettings {...props} />
</ErrorBoundary>
</React.Suspense>
);
};
const Error404Route = (props) => (
<React.Suspense fallback={<AppLoader />}>
@ -129,14 +136,6 @@ const WizardRoute = (props) => (
</React.Suspense>
);
// const MyProfileRoute = (props) => (
// <React.Suspense fallback={<AppLoader />}>
// <ErrorBoundary>
// <MyProfile {...props} />
// </ErrorBoundary>
// </React.Suspense>
// );
const FormGalleryRoute = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
@ -145,7 +144,19 @@ const FormGalleryRoute = (props) => (
</React.Suspense>
);
// const RedirectToHome = () => <Redirect to={PROXY_HOMEPAGE_URL} />;
const ConfirmNavigate = () => {
const location = useLocation();
const type = queryString.parse(location.search).type;
return (
<Navigate
to={`/confirm/${type}`}
search={location.search}
state={{ from: location }}
/>
);
};
const Shell = ({ items = [], page = "home", ...rest }) => {
const {
@ -440,8 +451,8 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
);
return (
<Layout>
<Router history={history}>
<Router>
<Layout>
{toast}
<ReactSmartBanner t={t} ready={ready} />
{isEditor || !isMobileOnly ? <></> : <NavMenu />}
@ -452,101 +463,108 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
<Main isDesktop={isDesktop}>
{!isMobileOnly && <MainBar />}
<div className="main-container">
<Switch>
<Redirect
exact
sensitive
from="/Products/Files/"
to="/rooms/shared"
/>
<PrivateRoute
exact
path={[
"/",
"/rooms/personal",
"/rooms/personal/filter",
"/rooms/shared",
"/rooms/shared/filter",
"/rooms/shared/:room",
"/rooms/shared/:room/filter",
"/rooms/archived",
"/rooms/archived/filter",
"/rooms/archived/:room",
"/rooms/archived/:room/filter",
"/files/favorite",
"/files/favorite/filter",
"/files/recent",
"/files/recent/filter",
"/files/trash",
"/files/trash/filter",
"/accounts",
"/accounts/filter",
"/accounts/create/:type",
"/accounts/edit/:userId",
"/accounts/view/:userId",
"/accounts/view/@self",
"/accounts/view/@self/notification",
"/settings",
"/settings/common",
"/settings/admin",
"/products/files",
//"/settings/connected-clouds",
]}
component={FilesRoute}
/>
<PrivateRoute
path={"/form-gallery/:folderId"}
component={FormGalleryRoute}
/>
<PublicRoute exact path={"/wizard"} component={WizardRoute} />
<PrivateRoute path={"/about"} component={AboutRoute} />
<Route path={"/confirm/:type"} component={ConfirmRoute} />
<Routes>
<Route
path={["/confirm", "/confirm.aspx"]}
component={({ location }) => {
const type = queryString.parse(location.search).type;
caseSensitive
path="/Products/Files/"
element={<Navigate to="/rooms/shared" replace />}
/>
return (
<Redirect
to={{
pathname: `/confirm/${type}`,
search: location.search,
state: { from: location },
}}
/>
);
}}
<Route
path="/*"
element={
<PrivateRoute>
<FilesRoute />
</PrivateRoute>
}
/>
<PrivateRoute
restricted
path={"/portal-settings"}
component={PortalSettingsRoute}
<Route
path={"/form-gallery/:folderId"}
element={
<PrivateRoute>
<FormGalleryRoute />
</PrivateRoute>
}
/>
<PublicRoute
path={"/preparation-portal"}
component={PreparationPortalRoute}
<Route
path={"/wizard"}
element={
<PublicRoute>
<WizardRoute />
</PublicRoute>
}
/>
<PrivateRoute
<Route
path={"/about"}
element={
<PrivateRoute>
<AboutRoute />
</PrivateRoute>
}
/>
{/* <Route path={"/confirm/:type/*"} element={<ConfirmRoute />} /> */}
<Route path={"/confirm/*"} element={<ConfirmRoute />} />
<Route path={"/confirm.aspx/*"} element={<ConfirmRoute />} />
<Route
path={"/portal-settings/*"}
element={
<PrivateRoute restricted>
<PortalSettingsRoute />
</PrivateRoute>
}
/>
<Route
path={"/portal-unavailable"}
component={PortalUnavailableRoute}
element={
<PrivateRoute>
<PortalUnavailableRoute />
</PrivateRoute>
}
/>
<Route path={"/unavailable"} component={ErrorUnavailableRoute} />
<PrivateRoute path={"/error401"} component={Error401Route} />
<PrivateRoute component={Error404Route} />
</Switch>
<Route
path={"/preparation-portal"}
element={
<PublicRoute>
<PreparationPortalRoute />
</PublicRoute>
}
/>
<Route
path={"/unavailable"}
element={
<PrivateRoute>
<ErrorUnavailableRoute />
</PrivateRoute>
}
/>
<Route
path={"/error401"}
element={
<PrivateRoute>
<Error401Route />
</PrivateRoute>
}
/>
<Route
element={
<PrivateRoute>
<Error404Route />
</PrivateRoute>
}
/>
</Routes>
</div>
</Main>
</Router>
</Layout>
</Layout>
</Router>
);
};

View File

@ -1,12 +1,11 @@
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import React from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import CatalogItem from "@docspace/components/catalog-item";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { combineUrl } from "@docspace/common/utils";
import withLoader from "../../../HOCs/withLoader";
import config from "PACKAGE_FILE";
const iconUrl = CatalogAccountsReactSvgUrl;
@ -16,21 +15,17 @@ const PureAccountsItem = ({
selectedTreeNode,
setSelectedNode,
toggleArticleOpen,
history,
t,
}) => {
const navigate = useNavigate();
const onClick = React.useCallback(() => {
setSelectedFolder(null);
setSelectedNode(["accounts", "filter"]);
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
"/accounts"
)
);
navigate("/accounts");
toggleArticleOpen();
}, [setSelectedFolder, setSelectedNode, history]);
@ -50,7 +45,7 @@ const PureAccountsItem = ({
};
const AccountsItem = withTranslation(["FilesSettings", "Common"])(
withRouter(withLoader(PureAccountsItem)(<></>))
withLoader(PureAccountsItem)(<></>)
);
export default inject(({ auth, treeFoldersStore, selectedFolderStore }) => {

View File

@ -1,11 +1,9 @@
import CatalogSettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
import React from "react";
import { withRouter } from "react-router";
import { useNavigate, useParams } from "react-router-dom";
import CatalogItem from "@docspace/components/catalog-item";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import withLoader from "../../../HOCs/withLoader";
import { isMobile } from "@docspace/components/utils/device";
import { isMobileOnly } from "react-device-detect";
@ -13,17 +11,17 @@ import { isMobileOnly } from "react-device-detect";
const iconUrl = CatalogSettingsReactSvgUrl;
const PureSettingsItem = ({
match,
expandedSetting,
setSelectedNode,
setExpandSettingsTree,
setSelectedFolder,
history,
t,
showText,
toggleArticleOpen,
}) => {
const { setting } = match.params;
const { setting } = useParams();
const navigate = useNavigate();
React.useEffect(() => {
setSelectedNode([setting]);
@ -39,19 +37,12 @@ const PureSettingsItem = ({
setSelectedNode(["common"]);
setExpandSettingsTree(["common"]);
if (isMobile() || isMobileOnly) toggleArticleOpen();
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
"/settings/common"
)
);
navigate("/settings/common");
}, [
setSelectedFolder,
setSelectedNode,
setExpandSettingsTree,
toggleArticleOpen,
history,
]);
const isActive = window.location.pathname.includes("settings");
@ -70,7 +61,7 @@ const PureSettingsItem = ({
};
const SettingsItem = withTranslation(["FilesSettings", "Common"])(
withRouter(withLoader(PureSettingsItem)(<></>))
withLoader(PureSettingsItem)(<></>)
);
export default inject(

View File

@ -1,7 +1,7 @@
import React from "react";
import styled from "styled-components";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { setDocumentTitle } from "@docspace/client/src/helpers/filesUtils";
import config from "PACKAGE_FILE";
import { RoomSearchArea } from "@docspace/common/constants";
@ -70,9 +70,6 @@ const ArticleBodyContent = (props) => {
fetchRooms,
setAlreadyFetchingRooms,
homepage,
history,
} = props;
if (filesIsLoading) return;
@ -238,9 +235,7 @@ export default inject(
};
}
)(
withRouter(
withTranslation([])(
withLoader(observer(ArticleBodyContent))(<Loaders.ArticleFolder />)
)
withTranslation([])(
withLoader(observer(ArticleBodyContent))(<Loaders.ArticleFolder />)
)
);

View File

@ -20,7 +20,7 @@ import MainButton from "@docspace/components/main-button";
import { withTranslation } from "react-i18next";
import Loaders from "@docspace/common/components/Loaders";
import { encryptionUploadDialog } from "../../../helpers/desktop";
import { withRouter } from "react-router";
import { useNavigate, useLocation } from "react-router-dom";
import MobileView from "./MobileView";
import { combineUrl } from "@docspace/common/utils";
@ -90,7 +90,7 @@ const ArticleMainButtonContent = (props) => {
const {
t,
isMobileArticle,
canCreate,
isPrivacy,
encryptedFile,
encrypted,
@ -101,7 +101,7 @@ const ArticleMainButtonContent = (props) => {
isFavoritesFolder,
isRecentFolder,
isRecycleBinFolder,
history,
currentFolderId,
isRoomsFolder,
isArchiveFolder,
@ -115,8 +115,6 @@ const ArticleMainButtonContent = (props) => {
isOwner,
isAdmin,
canCreateFiles,
setInvitePanelOptions,
mainButtonMobileVisible,
@ -136,6 +134,9 @@ const ArticleMainButtonContent = (props) => {
const [model, setModel] = React.useState([]);
const [isDropdownMainButton, setIsDropdownMainButton] = React.useState(true);
const navigate = useNavigate();
const location = useLocation();
const onCreate = React.useCallback(
(e) => {
const format = e.action || null;
@ -198,13 +199,7 @@ const ArticleMainButtonContent = (props) => {
const onInputClick = React.useCallback((e) => (e.target.value = null), []);
const onShowGallery = () => {
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
`/form-gallery/${currentFolderId}/`
)
);
navigate(`/form-gallery/${currentFolderId}/`);
};
const onInvite = React.useCallback((e) => {
@ -233,8 +228,8 @@ const ArticleMainButtonContent = (props) => {
React.useEffect(() => {
const isSettingFolder =
window.location.pathname.endsWith("/settings/common") ||
window.location.pathname.endsWith("/settings/admin");
location.pathname.endsWith("/settings/common") ||
location.pathname.endsWith("/settings/admin");
const isFolderHiddenDropdown =
isArchiveFolder ||
@ -253,7 +248,7 @@ const ArticleMainButtonContent = (props) => {
isFavoritesFolder,
isRecentFolder,
isRecycleBinFolder,
window.location.pathname,
location.pathname,
]);
React.useEffect(() => {
@ -467,7 +462,7 @@ const ArticleMainButtonContent = (props) => {
const isDisabled = isAccountsPage ? !canInvite : !security?.Create;
const isProfile = history.location.pathname === "/accounts/view/@self";
const isProfile = location.pathname === "/accounts/view/@self";
return (
<>
@ -552,7 +547,7 @@ export default inject(
isLoaded,
firstLoad,
isLoading,
canCreate,
mainButtonMobileVisible,
} = filesStore;
const {
@ -582,8 +577,6 @@ export default inject(
const { isAdmin, isOwner } = auth.userStore.user;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { canCreateFiles } = accessRightsStore;
return {
isGracePeriod,
setInviteUsersWarningDialogVisible,
@ -600,9 +593,6 @@ export default inject(
isArchiveFolder,
selectedTreeNode,
canCreate,
canCreateFiles,
startUpload,
setSelectFileDialogVisible,
@ -632,7 +622,7 @@ export default inject(
"People",
"PeopleTranslations",
])(
withLoader(observer(withRouter(ArticleMainButtonContent)))(
withLoader(observer(ArticleMainButtonContent))(
<Loaders.ArticleButton height="28px" />
)
)

View File

@ -5,14 +5,13 @@ import React from "react";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import EmptyContainer from "./EmptyContainer";
import Link from "@docspace/components/link";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { combineUrl } from "@docspace/common/utils";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import history from "@docspace/common/history";
import config from "PACKAGE_FILE";
const RoomNoAccessContainer = (props) => {
const {
@ -30,6 +29,8 @@ const RoomNoAccessContainer = (props) => {
const descriptionRoomNoAccess = t("NoAccessRoomDescription");
const titleRoomNoAccess = t("NoAccessRoomTitle");
const navigate = useNavigate();
React.useEffect(() => {
const timer = setTimeout(onGoToShared, 5000);
return () => clearTimeout(timer);
@ -49,13 +50,7 @@ const RoomNoAccessContainer = (props) => {
const pathname = `${url}?${filterParamsStr}`;
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
pathname
)
);
navigate(pathname);
})
.finally(() => {
setIsLoading(false);

View File

@ -3,6 +3,7 @@ import PersonSvgUrl from "PUBLIC_DIR/images/person.svg?url";
import PlusSvgUrl from "PUBLIC_DIR/images/plus.svg?url";
import EmptyFolderImageSvgUrl from "PUBLIC_DIR/images/empty-folder-image.svg?url";
import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { FolderType } from "@docspace/common/constants";
import { inject, observer } from "mobx-react";
@ -15,7 +16,6 @@ import Loaders from "@docspace/common/components/Loaders";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { combineUrl } from "@docspace/common/utils";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import history from "@docspace/common/history";
import config from "PACKAGE_FILE";
import PlusIcon from "PUBLIC_DIR/images/plus.react.svg";
import EmptyScreenPersonalUrl from "PUBLIC_DIR/images/empty_screen_personal.svg?url";
@ -74,6 +74,8 @@ const RootFolderContainer = (props) => {
} = props;
const personalDescription = t("EmptyFolderDecription");
const navigate = useNavigate();
const emptyScreenHeader = t("EmptyScreenFolder");
const archiveHeader = t("ArchiveEmptyScreenHeader");
const noFilesHeader = t("NoFilesHereYet");
@ -138,13 +140,7 @@ const RootFolderContainer = (props) => {
const pathname = `${url}?${filterParamsStr}`;
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
pathname
)
);
navigate(pathname);
})
.finally(() => {
setIsLoading(false);
@ -378,12 +374,8 @@ const RootFolderContainer = (props) => {
export default inject(
({ auth, filesStore, treeFoldersStore, selectedFolderStore }) => {
const {
isDesktopClient,
isEncryptionSupport,
organizationName,
theme,
} = auth.settingsStore;
const { isDesktopClient, isEncryptionSupport, organizationName, theme } =
auth.settingsStore;
const {
filter,

View File

@ -6,7 +6,7 @@ import { ChangeUserTypeDialog } from "../dialogs";
import toastr from "@docspace/components/toast/toastr";
import Link from "@docspace/components/link";
import { combineUrl } from "@docspace/common/utils";
import history from "@docspace/common/history";
import { useNavigate } from "react-router-dom";
const ChangeUserTypeEvent = ({
setVisible,
@ -17,13 +17,8 @@ const ChangeUserTypeEvent = ({
getUsersList,
onClose,
}) => {
const {
toType,
fromType,
userIDs,
successCallback,
abortCallback,
} = peopleDialogData;
const { toType, fromType, userIDs, successCallback, abortCallback } =
peopleDialogData;
const { t } = useTranslation(["ChangeUserTypeDialog", "Common", "Payments"]);
const onKeyUpHandler = (e) => {
@ -50,12 +45,12 @@ const ChangeUserTypeEvent = ({
const onClickPayments = () => {
const paymentPageUrl = combineUrl(
combineUrl(window.DocSpaceConfig?.proxy?.url, "/portal-settings"),
"/portal-settings",
"/payments/portal-payments"
);
toastr.clear();
history.push(paymentPageUrl);
navigate(paymentPageUrl);
};
const onChangeUserType = () => {

View File

@ -2,6 +2,8 @@ import React, { useEffect, useState } from "react";
import styled, { css } from "styled-components";
import PropTypes from "prop-types";
import MobileLayout from "./MobileLayout";
import history from "@docspace/common/history";
import { useNavigate, useLocation, useMatch } from "react-router-dom";
import { size } from "@docspace/components/utils/device";
import {
isIOS,
@ -39,6 +41,9 @@ const Layout = (props) => {
const [contentHeight, setContentHeight] = useState();
const [isPortrait, setIsPortrait] = useState();
history.navigate = useNavigate();
history.location = useLocation();
const intervalTime = 100;
const endTimeout = 300;
let intervalHandler;

View File

@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
import { inject, observer } from "mobx-react";
import difference from "lodash/difference";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { ADS_TIMEOUT } from "@docspace/client/src/helpers/filesConstants";
@ -340,4 +339,4 @@ export default inject(({ auth, profileActionsStore }) => {
currentColorScheme,
setMainBarVisible,
};
})(withTranslation(["Profile", "Common"])(withRouter(observer(Bar))));
})(withTranslation(["Profile", "Common"])(observer(Bar)));

View File

@ -8,7 +8,7 @@ import Header from "./sub-components/header";
import HeaderNav from "./sub-components/header-nav";
import HeaderUnAuth from "./sub-components/header-unauth";
import { I18nextProvider, withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate, useLocation } from "react-router-dom";
import Loaders from "@docspace/common/components/Loaders";
import { LayoutContextConsumer } from "../Layout/context";
@ -55,144 +55,124 @@ const StyledContainer = styled.header`
StyledContainer.defaultProps = { theme: Base };
class NavMenu extends React.Component {
constructor(props) {
super(props);
this.timeout = null;
const NavMenu = (props) => {
const timeout = React.useRef(null);
const {
isBackdropVisible,
isNavHoverEnabled,
isNavOpened,
isAsideVisible,
} = props;
const navigate = useNavigate();
const location = useLocation();
this.state = {
isBackdropVisible,
isNavOpened,
isAsideVisible,
isNavHoverEnabled,
};
}
const [isBackdropVisible, setIsBackdropVisible] = React.useState(
props.isBackdropVisible
);
const [isNavOpened, setIsNavOpened] = React.useState(props.isNavHoverEnabled);
const [isAsideVisible, setIsAsideVisible] = React.useState(props.isNavOpened);
const [isNavHoverEnabled, setIsNavHoverEnabled] = React.useState(
props.isAsideVisible
);
backdropClick = () => {
this.setState({
isBackdropVisible: false,
isNavOpened: false,
isAsideVisible: false,
isNavHoverEnabled: !this.state.isNavHoverEnabled,
});
const backdropClick = () => {
setIsBackdropVisible(false);
setIsNavOpened(false);
setIsAsideVisible(false);
setIsNavHoverEnabled((val) => !val);
};
showNav = () => {
this.setState({
isBackdropVisible: true,
isNavOpened: true,
isAsideVisible: false,
isNavHoverEnabled: false,
});
const showNav = () => {
setIsBackdropVisible(true);
setIsNavOpened(true);
setIsAsideVisible(false);
setIsNavHoverEnabled(false);
};
clearNavTimeout = () => {
if (this.timeout == null) return;
clearTimeout(this.timeout);
this.timeout = null;
const clearNavTimeout = () => {
if (timeout.current === null) return;
clearTimeout(timeout.current);
timeout.current = null;
};
handleNavMouseEnter = () => {
if (!this.state.isNavHoverEnabled) return;
this.timeout = setTimeout(() => {
this.setState({
isBackdropVisible: false,
isNavOpened: true,
isAsideVisible: false,
});
const handleNavMouseEnter = () => {
if (!isNavHoverEnabled) return;
timeout.current = setTimeout(() => {
setIsBackdropVisible(false);
setIsNavOpened(true);
setIsAsideVisible(false);
}, 1000);
};
handleNavMouseLeave = () => {
if (!this.state.isNavHoverEnabled) return;
this.clearNavTimeout();
this.setState({
isBackdropVisible: false,
isNavOpened: false,
isAsideVisible: false,
});
const handleNavMouseLeave = () => {
if (!isNavHoverEnabled) return;
clearNavTimeout();
setIsBackdropVisible(false);
setIsNavOpened(false);
setIsAsideVisible(false);
};
toggleAside = () => {
this.clearNavTimeout();
this.setState({
isBackdropVisible: true,
isNavOpened: false,
isAsideVisible: true,
isNavHoverEnabled: false,
});
const toggleAside = () => {
clearNavTimeout();
setIsBackdropVisible(true);
setIsNavOpened(false);
setIsAsideVisible(true);
setIsNavHoverEnabled(false);
};
render() {
const { isBackdropVisible, isNavOpened, isAsideVisible } = this.state;
const {
isAuthenticated,
isLoaded,
asideContent,
const {
isAuthenticated,
isLoaded,
asideContent,
history,
isDesktop,
isFrame,
showHeader,
} = this.props;
isDesktop,
isFrame,
showHeader,
} = props;
const isAsideAvailable = !!asideContent;
const hideHeader = isDesktop || (!showHeader && isFrame);
//console.log("NavMenu render", this.state, this.props);
const isPreparationPortal =
history.location.pathname === "/preparation-portal";
return (
<LayoutContextConsumer>
{(value) => (
<StyledContainer
isLoaded={isLoaded}
isVisible={value.isVisible}
isDesktop={hideHeader}
>
<Backdrop
visible={isBackdropVisible}
onClick={this.backdropClick}
withBackground={true}
/>
const isAsideAvailable = !!asideContent;
const hideHeader = isDesktop || (!showHeader && isFrame);
{!hideHeader &&
(isLoaded && isAuthenticated ? (
<>
{!isPreparationPortal && <HeaderNav />}
<Header
isPreparationPortal={isPreparationPortal}
isNavOpened={isNavOpened}
onClick={this.showNav}
onNavMouseEnter={this.handleNavMouseEnter}
onNavMouseLeave={this.handleNavMouseLeave}
toggleAside={this.toggleAside}
backdropClick={this.backdropClick}
/>
</>
) : !isLoaded && isAuthenticated ? (
<Loaders.Header />
) : (
<HeaderUnAuth />
))}
const isPreparationPortal = location.pathname === "/preparation-portal";
return (
<LayoutContextConsumer>
{(value) => (
<StyledContainer
isLoaded={isLoaded}
isVisible={value.isVisible}
isDesktop={hideHeader}
>
<Backdrop
visible={isBackdropVisible}
onClick={backdropClick}
withBackground={true}
/>
{isAsideAvailable && (
<Aside visible={isAsideVisible} onClick={this.backdropClick}>
{asideContent}
</Aside>
)}
</StyledContainer>
)}
</LayoutContextConsumer>
);
}
}
{!hideHeader &&
(isLoaded && isAuthenticated ? (
<>
{!isPreparationPortal && <HeaderNav />}
<Header
isPreparationPortal={isPreparationPortal}
isNavOpened={isNavOpened}
onClick={showNav}
onNavMouseEnter={handleNavMouseEnter}
onNavMouseLeave={handleNavMouseLeave}
toggleAside={toggleAside}
backdropClick={backdropClick}
/>
</>
) : !isLoaded && isAuthenticated ? (
<Loaders.Header />
) : (
<HeaderUnAuth />
))}
{isAsideAvailable && (
<Aside visible={isAsideVisible} onClick={backdropClick}>
{asideContent}
</Aside>
)}
</StyledContainer>
)}
</LayoutContextConsumer>
);
};
NavMenu.propTypes = {
isBackdropVisible: PropTypes.bool,
@ -231,7 +211,7 @@ const NavMenuWrapper = inject(({ auth }) => {
showHeader: frameConfig?.showHeader,
isFrame,
};
})(observer(withTranslation(["NavMenu", "Common"])(withRouter(NavMenu))));
})(observer(withTranslation(["NavMenu", "Common"])(NavMenu)));
export default () => (
<I18nextProvider i18n={i18n}>

View File

@ -5,7 +5,6 @@ import ProfileActions from "./profile-actions";
import { useTranslation } from "react-i18next";
import { tablet, mobile } from "@docspace/components/utils/device";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { isMobile, isMobileOnly } from "react-device-detect";
const StyledNav = styled.nav`
@ -80,18 +79,16 @@ HeaderNav.propTypes = {
isAuthenticated: PropTypes.bool,
};
export default withRouter(
inject(({ auth, profileActionsStore }) => {
const { userStore, isAuthenticated } = auth;
const { user, userIsUpdate, setUserIsUpdate } = userStore;
const { getActions } = profileActionsStore;
export default inject(({ auth, profileActionsStore }) => {
const { userStore, isAuthenticated } = auth;
const { user, userIsUpdate, setUserIsUpdate } = userStore;
const { getActions } = profileActionsStore;
return {
user,
isAuthenticated,
userIsUpdate,
setUserIsUpdate,
getActions,
};
})(observer(HeaderNav))
);
return {
user,
isAuthenticated,
userIsUpdate,
setUserIsUpdate,
getActions,
};
})(observer(HeaderNav));

View File

@ -5,7 +5,7 @@ import PropTypes from "prop-types";
import styled from "styled-components";
import { Link as LinkWithoutRedirect } from "react-router-dom";
import { isMobileOnly, isMobile } from "react-device-detect";
import history from "@docspace/common/history";
import { useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { isDesktop, tablet, mobile } from "@docspace/components/utils/device";
import { combineUrl } from "@docspace/common/utils";
@ -121,9 +121,13 @@ const HeaderComponent = ({
theme,
toggleArticleOpen,
logoUrl,
...props
}) => {
const { t } = useTranslation("Common");
const location = useLocation();
//const isNavAvailable = mainModules.length > 0;
// const onLogoClick = () => {
@ -190,13 +194,13 @@ const HeaderComponent = ({
});
const [isFormGallery, setIsFormGallery] = useState(
history.location.pathname.includes("/form-gallery")
location.pathname.includes("/form-gallery")
);
useEffect(() => {
return history.listen((location) => {
return () => {
setIsFormGallery(location.pathname.includes("/form-gallery"));
});
}, [history]);
};
}, [location]);
const logo = getLogoFromPath(
!theme.isBase ? logoUrl?.path?.dark : logoUrl?.path?.light

View File

@ -6,7 +6,7 @@ import Filter from "@docspace/common/api/people/filter";
import Loaders from "@docspace/common/components/Loaders";
import { inject, observer } from "mobx-react";
import { getSelectedGroup } from "../../../helpers/people-helpers";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { isMobile } from "@docspace/components/utils/device";
import { isMobileOnly } from "react-device-detect";
import config from "PACKAGE_FILE";
@ -23,7 +23,7 @@ const ArticleBodyContent = ({
toggleArticleOpen,
showText,
groupsCaption,
history,
filter,
selectGroup,
isVisitor,
@ -32,6 +32,8 @@ const ArticleBodyContent = ({
}) => {
const [groupItems, setGroupItems] = React.useState(null);
const navigate = useNavigate();
const changeTitleDocument = React.useCallback(
(id) => {
const currentGroup = getSelectedGroup(
@ -72,7 +74,7 @@ const ArticleBodyContent = ({
config.homepage,
`/accounts/filter?${urlFilter}`
);
history.push(url);
navigate(url);
if (isMobileOnly || isMobile()) toggleArticleOpen();
}
},
@ -126,7 +128,7 @@ const ArticleBodyContent = ({
};
const BodyContent = withTranslation(["Article"])(
withRouter(withLoader(ArticleBodyContent)(<Loaders.ArticleFolder />))
withLoader(ArticleBodyContent)(<Loaders.ArticleFolder />)
);
export default inject(({ auth, peopleStore }) => {

View File

@ -6,7 +6,7 @@ import AddGuestReactSvgUrl from "PUBLIC_DIR/images/add.guest.react.svg?url";
import AddEmployeeReactSvgUrl from "ASSETS/images/add.employee.react.svg?url";
import React from "react";
//import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import MainButton from "@docspace/components/main-button";
import InviteDialog from "../../dialogs/InviteDialog/index";
import { withTranslation } from "react-i18next";
@ -24,161 +24,110 @@ import MobileView from "./MobileView";
import withLoader from "../../../HOCs/withLoader";
class ArticleMainButtonContent extends React.Component {
constructor(props) {
super(props);
this.state = {
dialogVisible: false,
};
}
const ArticleMainButtonContent = (props) => {
const [dialogVisible, setDialogVisible] = React.useState(false);
const {
homepage,
toggleShowText,
t,
isAdmin,
goToEmployeeCreate = () => {
const { history, homepage } = this.props;
history.push(
userCaption,
sectionWidth,
isMobileArticle,
} = props;
const navigate = useNavigate();
const goToEmployeeCreate = () => {
navigate(
combineUrl(window.DocSpaceConfig?.proxy?.url, homepage, "/create/user")
);
if (isMobile || isMobileUtils()) this.props.toggleShowText();
if (isMobile || isMobileUtils()) toggleShowText();
};
// goToGuestCreate = () => {
// const { history, homepage } = this.props;
// history.push(
// combineUrl(window.DocSpaceConfig?.proxy?.url, homepage, "/create/guest")
// );
// if (isMobile || isMobileUtils()) this.props.toggleShowText();
// };
const onInvitationDialogClick = () => setDialogVisible((val) => !val);
// goToGroupCreate = () => {
// const { history, homepage } = this.props;
// history.push(
// combineUrl(window.DocSpaceConfig?.proxy?.url, homepage, "/group/create")
// );
// if (isMobile || isMobileUtils()) this.props.toggleShowText();
// };
const separator = {
key: "separator",
isSeparator: true,
};
onInvitationDialogClick = () =>
this.setState({ dialogVisible: !this.state.dialogVisible });
const menuModel = [
{
key: "create-user",
icon: combineUrl(
window.DocSpaceConfig?.proxy?.url,
homepage,
AddEmployeeReactSvgUrl
),
label: userCaption,
onClick: goToEmployeeCreate,
},
];
render() {
//console.log("People ArticleMainButtonContent render");
const {
t,
isAdmin,
homepage,
userCaption,
// guestCaption,
// groupCaption,
sectionWidth,
const links = [
{
key: "invite-link",
icon: combineUrl(
window.DocSpaceConfig?.proxy?.url,
InvitationLinkReactSvgUrl
),
label: t("PeopleTranslations:InviteLinkTitle"),
onClick: onInvitationDialogClick,
},
];
isMobileArticle,
} = this.props;
return isAdmin ? (
<>
{isMobileArticle ? (
<MobileView
labelProps={t("Common:OtherOperations")}
actionOptions={menuModel}
buttonOptions={links}
sectionWidth={sectionWidth}
/>
) : (
<MainButton
isDisabled={false}
isDropdown={true}
text={t("Common:Actions")}
model={[...menuModel, separator, ...links]}
className="main-button_invitation-link"
/>
)}
const { dialogVisible } = this.state;
{dialogVisible && (
<InviteDialog
visible={dialogVisible}
onClose={onInvitationDialogClick}
onCloseButton={onInvitationDialogClick}
/>
)}
</>
) : (
<></>
);
};
const separator = {
key: "separator",
isSeparator: true,
};
export default inject(({ auth }) => {
const { userCaption, guestCaption, groupCaption } =
auth.settingsStore.customNames;
const menuModel = [
{
key: "create-user",
icon: combineUrl(
window.DocSpaceConfig?.proxy?.url,
homepage,
AddEmployeeReactSvgUrl
),
label: userCaption,
onClick: this.goToEmployeeCreate,
},
// {
// key: "create-guest",
// icon: combineUrl(
// window.DocSpaceConfig?.proxy?.url,
// homepage,
// AddGuestReactSvgUrl
// ),
// label: guestCaption,
// onClick: this.goToGuestCreate,
// },
// {
// key: "create-group",
// icon: combineUrl(
// window.DocSpaceConfig?.proxy?.url,
// homepage,
// AddDepartmentReactSvgUrl
// ),
// label: groupCaption,
// onClick: this.goToGroupCreate,
// },
];
const links = [
{
key: "invite-link",
icon: combineUrl(
window.DocSpaceConfig?.proxy?.url,
InvitationLinkReactSvgUrl
),
label: t("PeopleTranslations:InviteLinkTitle"),
onClick: this.onInvitationDialogClick,
},
];
return isAdmin ? (
<>
{isMobileArticle ? (
<MobileView
labelProps={t("Common:OtherOperations")}
actionOptions={menuModel}
buttonOptions={links}
sectionWidth={sectionWidth}
/>
) : (
<MainButton
isDisabled={false}
isDropdown={true}
text={t("Common:Actions")}
model={[...menuModel, separator, ...links]}
className="main-button_invitation-link"
/>
)}
{dialogVisible && (
<InviteDialog
visible={dialogVisible}
onClose={this.onInvitationDialogClick}
onCloseButton={this.onInvitationDialogClick}
/>
)}
</>
) : (
<></>
);
}
}
export default withRouter(
inject(({ auth }) => {
const {
userCaption,
guestCaption,
groupCaption,
} = auth.settingsStore.customNames;
return {
isAdmin: auth.isAdmin,
homepage: config.homepage,
userCaption,
guestCaption,
groupCaption,
toggleShowText: auth.settingsStore.toggleShowText,
isMobileArticle: auth.settingsStore.isMobileArticle,
showText: auth.settingsStore.showText,
};
})(
withTranslation(["Article", "Common", "PeopleTranslations"])(
withLoader(observer(ArticleMainButtonContent))(<Loaders.ArticleButton />)
)
return {
isAdmin: auth.isAdmin,
homepage: config.homepage,
userCaption,
guestCaption,
groupCaption,
toggleShowText: auth.settingsStore.toggleShowText,
isMobileArticle: auth.settingsStore.isMobileArticle,
showText: auth.settingsStore.showText,
};
})(
withTranslation(["Article", "Common", "PeopleTranslations"])(
withLoader(observer(ArticleMainButtonContent))(<Loaders.ArticleButton />)
)
);

View File

@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import styled from "styled-components";
import { withRouter } from "react-router";
import ModalDialogContainer from "../ModalDialogContainer";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
@ -168,4 +168,4 @@ export default inject(
items,
};
}
)(withRouter(observer(ArchiveDialog)));
)(observer(ArchiveDialog));

View File

@ -1,5 +1,4 @@
import React, { memo } from "react";
import { withRouter } from "react-router";
import PropTypes from "prop-types";
import ModalDialog from "@docspace/components/modal-dialog";
@ -135,23 +134,21 @@ ChangeUserStatusDialog.propTypes = {
userIDs: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default withRouter(
inject(({ peopleStore, auth }) => {
const setSelected = peopleStore.selectionStore.setSelected;
export default inject(({ peopleStore, auth }) => {
const setSelected = peopleStore.selectionStore.setSelected;
const { getPeopleListItem, updateUserStatus } = peopleStore.usersStore;
const { getPeopleListItem, updateUserStatus } = peopleStore.usersStore;
const { setSelection, isVisible: infoPanelVisible } = auth.infoPanelStore;
const { setSelection, isVisible: infoPanelVisible } = auth.infoPanelStore;
return {
updateUserStatus,
return {
updateUserStatus,
setSelected,
setSelected,
getPeopleListItem,
getPeopleListItem,
setSelection,
infoPanelVisible,
};
})(observer(ChangeUserStatusDialog))
);
setSelection,
infoPanelVisible,
};
})(observer(ChangeUserStatusDialog));

View File

@ -1,5 +1,4 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import ModalDialog from "@docspace/components/modal-dialog";
import RadioButtonGroup from "@docspace/components/radio-button-group";
import Button from "@docspace/components/button";
@ -281,9 +280,7 @@ export default inject(({ auth, dialogsStore, uploadDataStore, filesStore }) => {
setCopyPanelVisible,
};
})(
withRouter(
withTranslation(["ConflictResolveDialog", "Common"])(
observer(ConflictResolveDialog)
)
withTranslation(["ConflictResolveDialog", "Common"])(
observer(ConflictResolveDialog)
)
);

View File

@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import { withRouter } from "react-router";
import ModalDialogContainer from "../ModalDialogContainer";
import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
@ -157,16 +156,10 @@ export default inject(
isFavoritesFolder,
isShareFolder,
} = treeFoldersStore;
const {
convertUploadedFiles,
convertFile,
setIsConvertSingleFile,
} = uploadDataStore;
const {
storeOriginalFiles,
setStoreOriginal,
hideConfirmConvert,
} = settingsStore;
const { convertUploadedFiles, convertFile, setIsConvertSingleFile } =
uploadDataStore;
const { storeOriginalFiles, setStoreOriginal, hideConfirmConvert } =
settingsStore;
const { id: folderId } = selectedFolderStore;
const {
convertDialogVisible: visible,
@ -191,4 +184,4 @@ export default inject(
setIsConvertSingleFile,
};
}
)(withRouter(observer(ConvertDialog)));
)(observer(ConvertDialog));

View File

@ -1,5 +1,4 @@
import React, { useEffect } from "react";
import { withRouter } from "react-router";
import ModalDialog from "@docspace/components/modal-dialog";
import { StyledDeleteDialog } from "./StyledDeleteDialog";
import Button from "@docspace/components/button";
@ -214,23 +213,12 @@ const DeleteDialog = withTranslation([
export default inject(
({ filesStore, dialogsStore, filesActionsStore, treeFoldersStore, auth }) => {
const {
selection,
isLoading,
bufferSelection,
setBufferSelection,
} = filesStore;
const {
deleteAction,
unsubscribeAction,
deleteRoomsAction,
} = filesActionsStore;
const {
isPrivacyFolder,
isRecycleBinFolder,
isPersonalRoom,
isRoom,
} = treeFoldersStore;
const { selection, isLoading, bufferSelection, setBufferSelection } =
filesStore;
const { deleteAction, unsubscribeAction, deleteRoomsAction } =
filesActionsStore;
const { isPrivacyFolder, isRecycleBinFolder, isPersonalRoom, isRoom } =
treeFoldersStore;
const {
deleteDialogVisible: visible,
@ -268,4 +256,4 @@ export default inject(
isRoom,
};
}
)(withRouter(observer(DeleteDialog)));
)(observer(DeleteDialog));

View File

@ -1,5 +1,5 @@
import React from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import Button from "@docspace/components/button";
@ -17,86 +17,67 @@ import { combineUrl } from "@docspace/common/utils";
const { deleteUser } = api.people; //TODO: Move to action
const { Filter } = api;
class DeleteProfileEverDialogComponent extends React.Component {
constructor(props) {
super(props);
const DeleteProfileEverDialogComponent = (props) => {
const { user, t, homepage, setFilter, onClose, tReady, visible } = props;
const [isRequestRunning, setIsRequestRunning] = React.useState(false);
this.state = {
isRequestRunning: false,
};
}
onDeleteProfileEver = () => {
const { user, t, history, homepage, setFilter, onClose } = this.props;
const navigate = useNavigate();
const onDeleteProfileEver = () => {
const filter = Filter.getDefault();
const params = filter.toUrlParams();
const url = combineUrl(
window.DocSpaceConfig?.proxy?.url,
homepage,
`/accounts/filter?${params}`
);
const url = `/accounts/filter?${params}`;
this.setState({ isRequestRunning: true }, () => {
deleteUser(user.id)
.then((res) => {
toastr.success(t("SuccessfullyDeleteUserInfoMessage"));
history.push(url, params);
setFilter(filter);
return;
})
.catch((error) => toastr.error(error))
.finally(() => onClose());
});
setIsRequestRunning(true);
deleteUser(user.id)
.then((res) => {
toastr.success(t("SuccessfullyDeleteUserInfoMessage"));
navigate(url, params);
setFilter(filter);
return;
})
.catch((error) => toastr.error(error))
.finally(() => onClose());
};
render() {
console.log("DeleteProfileEverDialog render");
const { t, tReady, visible, user, onClose, userCaption } = this.props;
const { isRequestRunning } = this.state;
return (
<ModalDialogContainer
isLoading={!tReady}
visible={visible}
onClose={onClose}
>
<ModalDialog.Header>{t("DeleteUser")}</ModalDialog.Header>
<ModalDialog.Body>
<Text>
<Trans
i18nKey="DeleteUserMessage"
ns="DeleteProfileEverDialog"
t={t}
>
{{ userCaption: t("Common:User") }}{" "}
<strong>{{ user: user.displayName }}</strong>
will be deleted. User personal documents which are available to
others will be deleted.
</Trans>
</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="OKBtn"
label={t("Common:Delete")}
size="normal"
primary={true}
scale
onClick={this.onDeleteProfileEver}
isLoading={isRequestRunning}
/>
<Button
label={t("Common:CancelButton")}
size="normal"
scale
onClick={onClose}
/>
</ModalDialog.Footer>
</ModalDialogContainer>
);
}
}
return (
<ModalDialogContainer
isLoading={!tReady}
visible={visible}
onClose={onClose}
>
<ModalDialog.Header>{t("DeleteUser")}</ModalDialog.Header>
<ModalDialog.Body>
<Text>
<Trans i18nKey="DeleteUserMessage" ns="DeleteProfileEverDialog" t={t}>
{{ userCaption: t("Common:User") }}{" "}
<strong>{{ user: user.displayName }}</strong>
will be deleted. User personal documents which are available to
others will be deleted.
</Trans>
</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="OKBtn"
label={t("Common:Delete")}
size="normal"
primary={true}
scale
onClick={onDeleteProfileEver}
isLoading={isRequestRunning}
/>
<Button
label={t("Common:CancelButton")}
size="normal"
scale
onClick={onClose}
/>
</ModalDialog.Footer>
</ModalDialogContainer>
);
};
const DeleteProfileEverDialog = withTranslation([
"DeleteProfileEverDialog",
@ -110,9 +91,7 @@ DeleteProfileEverDialog.propTypes = {
user: PropTypes.object.isRequired,
};
export default withRouter(
inject(({ peopleStore }) => ({
homepage: config.homepage,
setFilter: peopleStore.filterStore.setFilterParams,
}))(observer(DeleteProfileEverDialog))
);
export default inject(({ peopleStore }) => ({
homepage: config.homepage,
setFilter: peopleStore.filterStore.setFilterParams,
}))(observer(DeleteProfileEverDialog));

View File

@ -1,5 +1,4 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
import { withTranslation } from "react-i18next";
@ -104,11 +103,8 @@ export default inject(
selectedFolderStore,
backup,
}) => {
const {
providers,
setThirdPartyProviders,
deleteThirdParty,
} = settingsStore.thirdPartyStore;
const { providers, setThirdPartyProviders, deleteThirdParty } =
settingsStore.thirdPartyStore;
const { fetchFiles } = filesStore;
const { selectedThirdPartyAccount: backupConnectionItem } = backup;
const {
@ -132,9 +128,7 @@ export default inject(
};
}
)(
withRouter(
withTranslation(["DeleteThirdPartyDialog", "Common", "Translations"])(
observer(DeleteThirdPartyDialog)
)
withTranslation(["DeleteThirdPartyDialog", "Common", "Translations"])(
observer(DeleteThirdPartyDialog)
)
);

View File

@ -1,5 +1,4 @@
import React, { memo } from "react";
import { withRouter } from "react-router";
import PropTypes from "prop-types";
import Button from "@docspace/components/button";
@ -160,13 +159,11 @@ DeleteUsersDialog.propTypes = {
removeUser: PropTypes.func.isRequired,
};
export default withRouter(
inject(({ peopleStore, auth }) => ({
filter: peopleStore.filterStore.filter,
removeUser: peopleStore.usersStore.removeUser,
selectedUsers: peopleStore.selectionStore.selection,
setSelected: peopleStore.selectionStore.setSelected,
userIds: peopleStore.selectionStore.getUsersToRemoveIds,
theme: auth.settingsStore.theme,
}))(observer(DeleteUsersDialog))
);
export default inject(({ peopleStore, auth }) => ({
filter: peopleStore.filterStore.filter,
removeUser: peopleStore.usersStore.removeUser,
selectedUsers: peopleStore.selectionStore.selection,
setSelected: peopleStore.selectionStore.setSelected,
userIds: peopleStore.selectionStore.getUsersToRemoveIds,
theme: auth.settingsStore.theme,
}))(observer(DeleteUsersDialog));

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import { withTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import { StyledDownloadDialog } from "./StyledDownloadDialog";
@ -12,13 +11,8 @@ import DownloadContent from "./DownloadContent";
class DownloadDialogComponent extends React.Component {
constructor(props) {
super(props);
const {
documents,
spreadsheets,
presentations,
masterForms,
other,
} = this.props.sortedFiles;
const { documents, spreadsheets, presentations, masterForms, other } =
this.props.sortedFiles;
this.state = {
documents: {
@ -404,10 +398,8 @@ export default inject(
const { extsConvertible } = settingsStore;
const { theme } = auth.settingsStore;
const {
downloadDialogVisible: visible,
setDownloadDialogVisible,
} = dialogsStore;
const { downloadDialogVisible: visible, setDownloadDialogVisible } =
dialogsStore;
const { downloadFiles } = filesActionsStore;
@ -422,4 +414,4 @@ export default inject(
theme,
};
}
)(withRouter(observer(DownloadDialog)));
)(observer(DownloadDialog));

View File

@ -1,6 +1,5 @@
import React, { useEffect } from "react";
import styled from "styled-components";
import { withRouter } from "react-router";
import ModalDialogContainer from "../ModalDialogContainer";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
@ -113,10 +112,8 @@ export default inject(
const { isArchiveFolder } = treeFoldersStore;
const {
emptyTrashDialogVisible: visible,
setEmptyTrashDialogVisible,
} = dialogsStore;
const { emptyTrashDialogVisible: visible, setEmptyTrashDialogVisible } =
dialogsStore;
return {
isLoading,
@ -130,4 +127,4 @@ export default inject(
isArchiveFolder,
};
}
)(withRouter(observer(EmptyTrashDialog)));
)(observer(EmptyTrashDialog));

View File

@ -1,25 +1,19 @@
import React, { useState, useEffect } from "react";
import { inject, observer } from "mobx-react";
import { withTranslation, Trans } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import moment from "moment";
import { combineUrl } from "@docspace/common/utils";
import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
import Text from "@docspace/components/text";
import { getDaysRemaining } from "@docspace/common/utils";
const PROXY_BASE_URL = combineUrl(
window.DocSpaceConfig?.proxy?.url,
"/portal-settings"
);
const InviteUsersWarningDialog = (props) => {
const {
t,
tReady,
history,
language,
dueDate,
delayDueDate,
@ -30,6 +24,8 @@ const InviteUsersWarningDialog = (props) => {
isPaymentPageAvailable,
} = props;
const navigate = useNavigate();
const [datesData, setDatesData] = useState({});
const { fromDate, byDate, delayDaysCount } = datesData;
@ -56,11 +52,9 @@ const InviteUsersWarningDialog = (props) => {
const onUpgradePlan = () => {
onClose();
const paymentPageUrl = combineUrl(
PROXY_BASE_URL,
"/payments/portal-payments"
);
history.push(paymentPageUrl);
const paymentPageUrl = "/portal-settings/payments/portal-payments";
navigate(paymentPageUrl);
};
return (
@ -132,11 +126,8 @@ const InviteUsersWarningDialog = (props) => {
export default inject(({ auth, dialogsStore }) => {
const { isPaymentPageAvailable } = auth;
const {
dueDate,
delayDueDate,
isGracePeriod,
} = auth.currentTariffStatusStore;
const { dueDate, delayDueDate, isGracePeriod } =
auth.currentTariffStatusStore;
const { currentTariffPlanTitle } = auth.currentQuotaStore;
const {
@ -154,10 +145,4 @@ export default inject(({ auth, dialogsStore }) => {
delayDueDate,
isGracePeriod,
};
})(
observer(
withTranslation(["Payments", "Common"])(
withRouter(InviteUsersWarningDialog)
)
)
);
})(observer(withTranslation(["Payments", "Common"])(InviteUsersWarningDialog)));

View File

@ -4,69 +4,62 @@ import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
import Text from "@docspace/components/text";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import ModalDialogContainer from "../ModalDialogContainer";
import toastr from "@docspace/components/toast/toastr";
class ResetApplicationDialogComponent extends React.Component {
constructor(props) {
super(props);
}
const ResetApplicationDialogComponent = (props) => {
const { t, resetTfaApp, id, onClose, tReady, visible } = props;
resetApp = async () => {
const { t, resetTfaApp, id, onClose, history } = this.props;
const navigate = useNavigate();
const resetApp = async () => {
onClose && onClose();
try {
const res = await resetTfaApp(id);
toastr.success(t("SuccessResetApplication"));
if (res) history.push(res.replace(window.location.origin, ""));
if (res) navigate(res.replace(window.location.origin, ""));
} catch (e) {
toastr.error(e);
}
};
render() {
//console.log("Render ResetApplicationDialog");
const { t, tReady, visible, onClose } = this.props;
return (
<ModalDialogContainer
isLoading={!tReady}
visible={visible}
onClose={onClose}
>
<ModalDialog.Header>{t("ResetApplicationTitle")}</ModalDialog.Header>
<ModalDialog.Body>
<Text>{t("ResetApplicationDescription")}</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="ResetSendBtn"
label={t("Common:ResetApplication")}
size="normal"
scale
primary={true}
onClick={resetApp}
/>
<Button
key="CloseBtn"
label={t("Common:CancelButton")}
size="normal"
scale
primary={false}
onClick={onClose}
/>
</ModalDialog.Footer>
</ModalDialogContainer>
);
};
return (
<ModalDialogContainer
isLoading={!tReady}
visible={visible}
onClose={onClose}
>
<ModalDialog.Header>{t("ResetApplicationTitle")}</ModalDialog.Header>
<ModalDialog.Body>
<Text>{t("ResetApplicationDescription")}</Text>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="ResetSendBtn"
label={t("Common:ResetApplication")}
size="normal"
scale
primary={true}
onClick={this.resetApp}
/>
<Button
key="CloseBtn"
label={t("Common:CancelButton")}
size="normal"
scale
primary={false}
onClick={onClose}
/>
</ModalDialog.Footer>
</ModalDialogContainer>
);
}
}
const ResetApplicationDialog = withRouter(
withTranslation(["ResetApplicationDialog", "Common"])(
ResetApplicationDialogComponent
)
);
const ResetApplicationDialog = withTranslation([
"ResetApplicationDialog",
"Common",
])(ResetApplicationDialogComponent);
ResetApplicationDialog.propTypes = {
visible: PropTypes.bool.isRequired,

View File

@ -1,5 +1,4 @@
import React, { memo } from "react";
import { withRouter } from "react-router";
import PropTypes from "prop-types";
import ModalDialog from "@docspace/components/modal-dialog";
@ -166,10 +165,8 @@ SendInviteDialog.propTypes = {
setSelected: PropTypes.func.isRequired,
};
export default withRouter(
inject(({ peopleStore }) => ({
selectedUsers: peopleStore.selectionStore.selection,
setSelected: peopleStore.selectionStore.setSelected,
userIds: peopleStore.selectionStore.getUsersToInviteIds,
}))(observer(SendInviteDialog))
);
export default inject(({ peopleStore }) => ({
selectedUsers: peopleStore.selectionStore.selection,
setSelected: peopleStore.selectionStore.setSelected,
userIds: peopleStore.selectionStore.getUsersToInviteIds,
}))(observer(SendInviteDialog));

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import Backdrop from "@docspace/components/backdrop";
import Heading from "@docspace/components/heading";
import Aside from "@docspace/components/aside";
@ -29,13 +28,8 @@ class ChangeOwnerComponent extends React.Component {
onOwnerChange = () => {
const { owner } = this.state;
const {
selection,
setFolder,
setFile,
setIsLoading,
setFilesOwner,
} = this.props;
const { selection, setFolder, setFile, setIsLoading, setFilesOwner } =
this.props;
const folderIds = [];
const fileIds = [];
const selectedItem = selection[0];
@ -162,4 +156,4 @@ export default inject(({ auth, filesStore, dialogsStore }) => {
setFilesOwner,
setBufferSelection,
};
})(withRouter(observer(ChangeOwnerPanel)));
})(observer(ChangeOwnerPanel));

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import Backdrop from "@docspace/components/backdrop";
import Link from "@docspace/components/link";
import Loader from "@docspace/components/loader";
@ -94,11 +93,8 @@ class NewFilesPanel extends React.Component {
const { id, extension: fileExst } = e.target.dataset;
const {
/* updateFolderBadge, */ markAsRead,
newFiles,
refreshFiles,
} = this.props;
const { /* updateFolderBadge, */ markAsRead, newFiles, refreshFiles } =
this.props;
const readingFiles = this.state.readingFiles;
const fileIds = fileExst ? [id] : [];
@ -332,11 +328,8 @@ export default inject(
refreshFiles,
} = filesStore;
//const { updateRootBadge } = treeFoldersStore;
const {
playlist,
setMediaViewerData,
setCurrentItem,
} = mediaViewerDataStore;
const { playlist, setMediaViewerData, setCurrentItem } =
mediaViewerDataStore;
const { getIcon, getFolderIcon } = settingsStore;
const { markAsRead } = filesActionsStore;
const { pathParts, id: currentFolderId } = selectedFolderStore;
@ -379,9 +372,7 @@ export default inject(
};
}
)(
withRouter(
withTranslation(["NewFilesPanel", "Common"])(
withLoader(observer(NewFilesPanel))(<Loaders.DialogAsideLoader isPanel />)
)
withTranslation(["NewFilesPanel", "Common"])(
withLoader(observer(NewFilesPanel))(<Loaders.DialogAsideLoader isPanel />)
)
);

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import toastr from "@docspace/components/toast/toastr";
@ -246,4 +246,4 @@ export default inject(
thirdPartyMoveDialogVisible,
};
}
)(withRouter(observer(OperationsPanel)));
)(observer(OperationsPanel));

View File

@ -1,30 +1,27 @@
import React from "react";
import { Route } from "react-router-dom";
import { useLocation } from "react-router-dom";
import { ValidationResult } from "./../helpers/constants";
import { withRouter } from "react-router";
import Loader from "@docspace/components/loader";
import Section from "@docspace/common/components/Section";
import { checkConfirmLink } from "@docspace/common/api/user"; //TODO: Move AuthStore
import { combineUrl, getObjectByLocation } from "@docspace/common/utils";
import { inject, observer } from "mobx-react";
class ConfirmRoute extends React.Component {
constructor(props) {
super(props);
this.state = {
linkData: {},
isLoaded: false,
};
}
const ConfirmRoute = (props) => {
const [state, setState] = React.useState({
linkData: {},
isLoaded: false,
});
componentDidMount() {
const { forUnauthorized, isAuthenticated } = this.props;
const location = useLocation();
React.useEffect(() => {
const { forUnauthorized, isAuthenticated } = props;
if (forUnauthorized && isAuthenticated) {
this.props.logout();
props.logout();
}
const { location } = this.props;
const { search } = location;
const queryParams = getObjectByLocation(location);
@ -54,10 +51,7 @@ class ConfirmRoute extends React.Component {
linkData,
});
this.setState({
isLoaded: true,
linkData,
});
setState((val) => ({ ...val, isLoaded: true, linkData }));
break;
case ValidationResult.Invalid:
console.error("invlid link", { confirmLinkData, validationResult });
@ -99,33 +93,22 @@ class ConfirmRoute extends React.Component {
"/error"
);
});
}
}, []);
render() {
const { component: Component, ...rest } = this.props;
// console.log(`ConfirmRoute render`, this.props, this.state);
// console.log(`ConfirmRoute render`, this.props, this.state);
return (
<Route
{...rest}
render={(props) =>
!this.state.isLoaded ? (
<Section>
<Section.SectionBody>
<Loader className="pageLoader" type="rombs" size="40px" />
</Section.SectionBody>
</Section>
) : (
<Component
{...(props = { ...props, linkData: this.state.linkData })}
/>
)
}
/>
);
}
}
return !state.isLoaded ? (
<Section>
<Section.SectionBody>
<Loader className="pageLoader" type="rombs" size="40px" />
</Section.SectionBody>
</Section>
) : (
React.cloneElement(props.children, {
linkData: state.linkData,
})
);
};
export default inject(({ auth }) => {
const { isAuthenticated, logout } = auth;
@ -133,4 +116,4 @@ export default inject(({ auth }) => {
isAuthenticated,
logout,
};
})(observer(withRouter(ConfirmRoute)));
})(observer(ConfirmRoute));

View File

@ -95,15 +95,15 @@ export const onItemClick = (e) => {
return window.open(link, "_blank");
}
history.push(link);
history.navigate(link);
};
export const getPasswordErrorMessage = (t, settings) => {
return `${t("Common:PasswordMinimumLength")} ${
settings ? settings.minLength : 8
} ${settings.digits ? t("Common:PasswordLimitDigits") : ""} ${
settings.upperCase ? t("Common:PasswordLimitUpperCase") : ""
} ${settings.specSymbols ? t("Common:PasswordLimitSpecialSymbols") : ""}`;
settings ? settings?.minLength : 8
} ${settings?.digits ? t("Common:PasswordLimitDigits") : ""} ${
settings?.upperCase ? t("Common:PasswordLimitUpperCase") : ""
} ${settings?.specSymbols ? t("Common:PasswordLimitSpecialSymbols") : ""}`;
};
export const getCategoryType = (location) => {

View File

@ -2,7 +2,7 @@
import React from "react";
import styled from "styled-components";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import Headline from "@docspace/common/components/Headline";
import IconButton from "@docspace/components/icon-button";
import { tablet } from "@docspace/components/utils/device";
@ -24,10 +24,12 @@ const HeaderContainer = styled.div`
`;
const AboutHeader = (props) => {
const { t, history } = props;
const { t } = props;
const navigate = useNavigate();
const onBack = () => {
history.goBack();
navigate(-1);
};
return (
@ -46,4 +48,4 @@ const AboutHeader = (props) => {
);
};
export default withRouter(withTranslation(["About"])(AboutHeader));
export default withTranslation(["About"])(AboutHeader);

View File

@ -1,46 +1,18 @@
import React, { useEffect } from "react";
import { inject, observer } from "mobx-react";
import { Redirect, Switch } from "react-router-dom";
import { Navigate, Routes, Route, useLocation } from "react-router-dom";
import ErrorBoundary from "@docspace/common/components/ErrorBoundary";
import toastr from "@docspace/components/toast/toastr";
import PrivateRoute from "@docspace/common/components/PrivateRoute";
import AppLoader from "@docspace/common/components/AppLoader";
import { /*combineUrl,*/ updateTempContent } from "@docspace/common/utils";
import Home from "./AccountsHome";
import Profile from "./Profile";
import NotificationComponent from "./Notifications";
import Filter from "@docspace/common/api/people/filter";
import { showLoader, hideLoader } from "@docspace/common/utils";
const Error404 = React.lazy(() => import("client/Error404"));
const PeopleSection = React.memo(() => {
return (
<Switch>
<PrivateRoute exact path={["/accounts/view/@self"]} component={Profile} />
<PrivateRoute
exact
path={["/accounts/view/@self/notification"]}
component={NotificationComponent}
/>
<PrivateRoute
exact
withManager
path={["/accounts"]}
component={HomeRedirectToFilter}
/>
<PrivateRoute
path={"/accounts/filter"}
withManager
restricted
component={Home}
/>
<PrivateRoute component={Error404Route} />
</Switch>
);
});
const Error404Route = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
@ -49,12 +21,45 @@ const Error404Route = (props) => (
</React.Suspense>
);
const HomeRedirectToFilter = (props) => {
const HomeRedirectToFilter = () => {
const filter = Filter.getDefault();
const urlFilter = filter.toUrlParams();
return <Redirect to={`/accounts/filter?${urlFilter}`} />;
return <Navigate replace to={`/accounts/filter?${urlFilter}`} />;
};
const PeopleSection = React.memo(() => {
return (
<Routes>
<Route
path="/*"
element={
<PrivateRoute restricted withManager location={location}>
<HomeRedirectToFilter />
</PrivateRoute>
}
/>
<Route
path="/filter"
element={
<PrivateRoute restricted withManager location={location}>
<Home />
</PrivateRoute>
}
/>
<Route
element={
<PrivateRoute location={location}>
<Error404Route />
</PrivateRoute>
}
/>
</Routes>
);
});
const PeopleContent = (props) => {
const { loadBaseInfo, isLoading, setFirstLoad } = props;

View File

@ -1,6 +1,5 @@
import React from "react";
import styled, { css } from "styled-components";
import { withRouter } from "react-router";
import { isMobile } from "react-device-detect";
import Row from "@docspace/components/row";
@ -139,4 +138,4 @@ const SimpleUserRow = (props) => {
);
};
export default withRouter(withContent(SimpleUserRow));
export default withContent(SimpleUserRow);

View File

@ -1,6 +1,5 @@
import React from "react";
import styled, { css } from "styled-components";
import { withRouter } from "react-router";
import { isTablet } from "react-device-detect";
import { withTranslation } from "react-i18next";
@ -40,14 +39,8 @@ const UserContent = ({
t,
theme,
}) => {
const {
displayName,
email,
statusType,
role,
isVisitor,
isCollaborator,
} = item;
const { displayName, email, statusType, role, isVisitor, isCollaborator } =
item;
const nameColor =
statusType === "pending" || statusType === "disabled"
@ -120,4 +113,4 @@ const UserContent = ({
);
};
export default withTranslation(["People", "Common"])(withRouter(UserContent));
export default withTranslation(["People", "Common"])(UserContent);

View File

@ -1,6 +1,5 @@
import React from "react";
import styled from "styled-components";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import TableRow from "@docspace/components/table-container/TableRow";
@ -429,5 +428,5 @@ const PeopleTableRow = (props) => {
};
export default withTranslation(["People", "Common", "Settings"])(
withRouter(withContent(PeopleTableRow))
withContent(PeopleTableRow)
);

View File

@ -1,6 +1,5 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { isMobileOnly } from "react-device-detect";
import find from "lodash/find";
@ -484,43 +483,36 @@ const SectionFilterContent = ({
);
};
export default withRouter(
inject(({ auth, peopleStore }) => {
const {
loadingStore,
filterStore,
usersStore,
groupsStore,
viewAs,
} = peopleStore;
const { userStore, isLoaded, isAdmin } = auth;
const { user } = userStore;
const { groups } = groupsStore;
const { getUsersList: fetchPeople } = usersStore;
const { filter } = filterStore;
const { setIsLoading } = loadingStore;
export default inject(({ auth, peopleStore }) => {
const { loadingStore, filterStore, usersStore, groupsStore, viewAs } =
peopleStore;
const { userStore, isLoaded, isAdmin } = auth;
const { user } = userStore;
const { groups } = groupsStore;
const { getUsersList: fetchPeople } = usersStore;
const { filter } = filterStore;
const { setIsLoading } = loadingStore;
return {
isLoaded,
isAdmin,
user,
groups,
fetchPeople,
filter,
setIsLoading,
viewAs,
};
})(
observer(
withLayoutSize(
withTranslation([
"People",
"Common",
"PeopleTranslations",
"ConnectDialog",
"SmartBanner",
])(withPeopleLoader(SectionFilterContent)(<Loaders.Filter />))
)
return {
isLoaded,
isAdmin,
user,
groups,
fetchPeople,
filter,
setIsLoading,
viewAs,
};
})(
observer(
withLayoutSize(
withTranslation([
"People",
"Common",
"PeopleTranslations",
"ConnectDialog",
"SmartBanner",
])(withPeopleLoader(SectionFilterContent)(<Loaders.Filter />))
)
)
);

View File

@ -10,7 +10,6 @@ import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { isMobile, isMobileOnly } from "react-device-detect";
import styled, { css } from "styled-components";
import { withRouter } from "react-router";
import Headline from "@docspace/common/components/Headline";
import Loaders from "@docspace/common/components/Loaders";
import DropDownItem from "@docspace/components/drop-down-item";
@ -354,62 +353,54 @@ const SectionHeaderContent = (props) => {
);
};
export default withRouter(
inject(({ auth, peopleStore, dialogsStore }) => {
const {
setIsVisible: setInfoPanelIsVisible,
isVisible: isInfoPanelVisible,
} = auth.infoPanelStore;
export default inject(({ auth, peopleStore, dialogsStore }) => {
const { setIsVisible: setInfoPanelIsVisible, isVisible: isInfoPanelVisible } =
auth.infoPanelStore;
const {
setInvitePanelOptions,
setInviteUsersWarningDialogVisible,
} = dialogsStore;
const { setInvitePanelOptions, setInviteUsersWarningDialogVisible } =
dialogsStore;
const { isOwner, isAdmin } = auth.userStore.user;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { isOwner, isAdmin } = auth.userStore.user;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { selectionStore, headerMenuStore, getHeaderMenu } = peopleStore;
const { selectionStore, headerMenuStore, getHeaderMenu } = peopleStore;
const {
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
cbMenuItems,
getMenuItemId,
getCheckboxItemLabel,
} = headerMenuStore;
const {
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
cbMenuItems,
getMenuItemId,
getCheckboxItemLabel,
} = headerMenuStore;
const { setSelected } = selectionStore;
const { setSelected } = selectionStore;
return {
setSelected,
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
getHeaderMenu,
cbMenuItems,
getMenuItemId,
getCheckboxItemLabel,
setInfoPanelIsVisible,
isInfoPanelVisible,
isOwner,
isAdmin,
setInvitePanelOptions,
isGracePeriod,
setInviteUsersWarningDialogVisible,
};
})(
withTranslation([
"People",
"Common",
"PeopleTranslations",
"Files",
"ChangeUserTypeDialog",
])(
withPeopleLoader(observer(SectionHeaderContent))(
<Loaders.SectionHeader />
)
)
return {
setSelected,
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
getHeaderMenu,
cbMenuItems,
getMenuItemId,
getCheckboxItemLabel,
setInfoPanelIsVisible,
isInfoPanelVisible,
isOwner,
isAdmin,
setInvitePanelOptions,
isGracePeriod,
setInviteUsersWarningDialogVisible,
};
})(
withTranslation([
"People",
"Common",
"PeopleTranslations",
"Files",
"ChangeUserTypeDialog",
])(
withPeopleLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />)
)
);

View File

@ -1,7 +1,7 @@
import React, { useEffect } from "react";
import { inject, observer } from "mobx-react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import { isMobile } from "react-device-detect";
@ -26,7 +26,7 @@ import {
const PureHome = ({
isLoading,
history,
getUsersList,
setIsLoading,
setIsRefresh,
@ -45,8 +45,8 @@ const PureHome = ({
onClickBack,
setPortalTariff,
}) => {
const { location } = history;
const { pathname } = location;
const location = useLocation();
//console.log("People Home render");
useEffect(() => {
@ -58,7 +58,7 @@ const PureHome = ({
}, []);
useEffect(() => {
if (pathname.indexOf("/accounts/filter") > -1) {
if (location.pathname.indexOf("/accounts/filter") > -1) {
setSelectedNode(["accounts", "filter"]);
setIsLoading(true);
setIsRefresh(true);
@ -74,7 +74,7 @@ const PureHome = ({
setIsRefresh(false);
});
}
}, [pathname, location, setSelectedNode]);
}, [location, setSelectedNode]);
useEffect(() => {
if (isMobile) {
@ -140,23 +140,14 @@ export default inject(
const { settingsStore, currentTariffStatusStore } = auth;
const { setPortalTariff } = currentTariffStatusStore;
const { showCatalog, withPaging } = settingsStore;
const {
usersStore,
selectedGroupStore,
loadingStore,
viewAs,
} = peopleStore;
const { usersStore, selectedGroupStore, loadingStore, viewAs } =
peopleStore;
const { getUsersList } = usersStore;
const { selectedGroup } = selectedGroupStore;
const { setSelectedNode } = treeFoldersStore;
const { onClickBack } = filesActionsStore;
const {
isLoading,
setIsLoading,
setIsRefresh,
firstLoad,
setFirstLoad,
} = loadingStore;
const { isLoading, setIsLoading, setIsRefresh, firstLoad, setFirstLoad } =
loadingStore;
return {
setPortalTariff,
@ -178,4 +169,4 @@ export default inject(
onClickBack,
};
}
)(observer(withRouter(Home)));
)(observer(Home));

View File

@ -1,5 +1,5 @@
import React, { lazy } from "react";
import { Switch, Route } from "react-router-dom";
import { Routes, Route } from "react-router-dom";
import ConfirmRoute from "../../helpers/confirmRoute";
const ActivateUserForm = lazy(() => import("./sub-components/activateUser"));
@ -24,74 +24,135 @@ const Error404 = lazy(() => import("../Errors/404"));
const Confirm = () => {
//console.log("Confirm render");
const path = "/confirm";
return (
<Switch>
<ConfirmRoute
forUnauthorized
path={`${path}/LinkInvite`}
component={CreateUserForm}
/>
<ConfirmRoute
forUnauthorized
path={`${path}/Activation`}
component={ActivateUserForm}
/>
<ConfirmRoute
exact
path={`${path}/EmailActivation`}
component={ActivateEmailForm}
/>
<ConfirmRoute
exact
path={`${path}/EmailChange`}
component={ChangeEmailForm}
/>
<ConfirmRoute
forUnauthorized
path={`${path}/PasswordChange`}
component={ChangePasswordForm}
/>
<ConfirmRoute
exact
path={`${path}/ProfileRemove`}
component={ProfileRemoveForm}
/>
<ConfirmRoute
exact
path={`${path}/PhoneActivation`}
component={ChangePhoneForm}
/>
<ConfirmRoute
exact
path={`${path}/PortalOwnerChange`}
component={ChangeOwnerForm}
/>
<ConfirmRoute exact path={`${path}/TfaAuth`} component={TfaAuthForm} />
<ConfirmRoute
exact
path={`${path}/TfaActivation`}
component={TfaActivationForm}
/>
<ConfirmRoute
exact
path={`${path}/PortalRemove`}
component={RemovePortal}
/>
<ConfirmRoute
exact
path={`${path}/PortalSuspend`}
component={DeactivatePortal}
/>
<ConfirmRoute
exact
path={`${path}/PortalContinue`}
component={ContinuePortal}
/>
<ConfirmRoute forUnauthorized path={`${path}/Auth`} component={Auth} />
<Route component={Error404} />
</Switch>
return (
<Routes>
<Route
path={`LinkInvite`}
element={
<ConfirmRoute forUnauthorized>
<CreateUserForm />
</ConfirmRoute>
}
/>
<Route
path={`Activation`}
element={
<ConfirmRoute forUnauthorized>
<ActivateUserForm />
</ConfirmRoute>
}
/>
<Route
path={`EmailActivation`}
element={
<ConfirmRoute>
<ActivateEmailForm />
</ConfirmRoute>
}
/>
<Route
path={`EmailChange`}
element={
<ConfirmRoute>
<ChangeEmailForm />
</ConfirmRoute>
}
/>
<Route
path={`PasswordChange`}
element={
<ConfirmRoute forUnauthorized>
<ChangePasswordForm />
</ConfirmRoute>
}
/>
<Route
path={`ProfileRemove`}
element={
<ConfirmRoute>
<ProfileRemoveForm />
</ConfirmRoute>
}
/>
<Route
path={`PhoneActivation`}
element={
<ConfirmRoute>
<ChangePhoneForm />
</ConfirmRoute>
}
/>
<Route
path={`PortalOwnerChange`}
element={
<ConfirmRoute>
<ChangeOwnerForm />
</ConfirmRoute>
}
/>
<Route
path={`TfaAuth`}
element={
<ConfirmRoute>
<TfaAuthForm />
</ConfirmRoute>
}
/>
<Route
path={`TfaActivation`}
element={
<ConfirmRoute>
<TfaActivationForm />
</ConfirmRoute>
}
/>
<Route
path={`PortalRemove`}
element={
<ConfirmRoute>
<RemovePortal />
</ConfirmRoute>
}
/>
<Route
path={`PortalSuspend`}
element={
<ConfirmRoute>
<DeactivatePortal />
</ConfirmRoute>
}
/>
<Route
path={`PortalContinue`}
element={
<ConfirmRoute>
<ContinuePortal />
</ConfirmRoute>
}
/>
<Route
path={`Auth`}
element={
<ConfirmRoute forUnauthorized>
<Auth />
</ConfirmRoute>
}
/>
</Routes>
);
};

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import PropTypes from "prop-types";
import Loader from "@docspace/components/loader";
import Section from "@docspace/common/components/Section";
@ -57,7 +56,6 @@ class ActivateEmail extends React.PureComponent {
ActivateEmail.propTypes = {
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
};
const ActivateEmailForm = (props) => (
<Section>
@ -73,4 +71,4 @@ export default inject(({ auth }) => {
logout,
updateEmailActivationStatus: userStore.updateEmailActivationStatus,
};
})(withRouter(observer(ActivateEmailForm)));
})(observer(ActivateEmailForm));

View File

@ -1,5 +1,4 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import TextInput from "@docspace/components/text-input";
@ -266,9 +265,7 @@ export default inject(({ auth }) => {
login: auth.login,
};
})(
withRouter(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ActivateUserForm))
)
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ActivateUserForm))
)
);

View File

@ -1,5 +1,4 @@
import React, { useEffect } from "react";
import { withRouter } from "react-router";
import Loader from "@docspace/components/loader";
import Section from "@docspace/common/components/Section";
import { loginWithConfirmKey } from "@docspace/common/api/user";
@ -35,4 +34,4 @@ const AuthPage = (props) => (
</Section>
);
export default withRouter(AuthPage);
export default AuthPage;

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import Loader from "@docspace/components/loader";
@ -72,7 +71,6 @@ class ChangeEmail extends React.PureComponent {
}
ChangeEmail.propTypes = {
location: PropTypes.object.isRequired,
changeEmail: PropTypes.func.isRequired,
};
const ChangeEmailForm = (props) => (
@ -92,4 +90,4 @@ export default inject(({ auth }) => {
changeEmail: userStore.changeEmail,
defaultPage: settingsStore.defaultPage,
};
})(observer(withRouter(ChangeEmailForm)));
})(observer(ChangeEmailForm));

View File

@ -1,5 +1,4 @@
import React from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
@ -60,9 +59,5 @@ export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
defaultPage: auth.settingsStore.defaultPage,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(
withLoader(observer(ChangeOwnerForm))
)
)
withTranslation(["Confirm", "Common"])(withLoader(observer(ChangeOwnerForm)))
);

View File

@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import PasswordInput from "@docspace/components/password-input";
@ -191,9 +190,7 @@ export default inject(({ auth, setup }) => {
getSettings,
};
})(
withRouter(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ChangePasswordForm))
)
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(ChangePasswordForm))
)
);

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import Text from "@docspace/components/text";
import TextInput from "@docspace/components/text-input";
@ -64,6 +64,4 @@ const ChangePhoneForm = (props) => {
export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
}))(
withRouter(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))))
);
}))(withTranslation("Confirm")(withLoader(observer(ChangePhoneForm))));

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Text from "@docspace/components/text";
@ -20,21 +20,23 @@ import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
const ContinuePortal = (props) => {
const { t, greetingTitle, linkData, history } = props;
const { t, greetingTitle, linkData } = props;
const [isReactivate, setIsReactivate] = useState(false);
const navigate = useNavigate();
const onRestoreClick = async () => {
try {
await continuePortal(linkData.confirmHeader);
setIsReactivate(true);
setTimeout(() => (location.href = "/"), 10000);
setTimeout(() => (window.location.href = "/"), 10000);
} catch (e) {
toastr.error(e);
}
};
const onCancelClick = () => {
history.push("/");
navigate("/");
};
return (
@ -90,7 +92,5 @@ export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(withLoader(observer(ContinuePortal)))
)
withTranslation(["Confirm", "Common"])(withLoader(observer(ContinuePortal)))
);

View File

@ -1,6 +1,5 @@
import SsoReactSvgUrl from "PUBLIC_DIR/images/sso.react.svg?url";
import React, { useEffect, useState, useCallback } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import PropTypes from "prop-types";
import { createUser, signupOAuth } from "@docspace/common/api/people";
@ -52,7 +51,7 @@ const CreateUserForm = (props) => {
} = props;
const inputRef = React.useRef(null);
const emailFromLink = linkData.email ? linkData.email : "";
const emailFromLink = linkData?.email ? linkData.email : "";
const [moreAuthVisible, setMoreAuthVisible] = useState(false);
const [ssoLabel, setSsoLabel] = useState("");
@ -125,7 +124,7 @@ const CreateUserForm = (props) => {
};
fetchData();
}, []);
}, [props.isAuthenticated]);
const onSubmit = () => {
const { defaultPage, linkData, hashSettings } = props;
@ -325,9 +324,8 @@ const CreateUserForm = (props) => {
if (!providersData[item.provider]) return;
if (index > 1) return;
const { icon, label, iconOptions, className } = providersData[
item.provider
];
const { icon, label, iconOptions, className } =
providersData[item.provider];
return (
<div className="buttonWrapper" key={`${item.provider}ProviderItem`}>
@ -651,11 +649,6 @@ const CreateUserForm = (props) => {
);
};
CreateUserForm.propTypes = {
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
};
export default inject(({ auth }) => {
const {
login,
@ -692,9 +685,7 @@ export default inject(({ auth }) => {
currentColorScheme,
};
})(
withRouter(
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(CreateUserForm))
)
withTranslation(["Confirm", "Common", "Wizard"])(
withLoader(observer(CreateUserForm))
)
);

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { Trans, withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Text from "@docspace/components/text";
@ -20,15 +20,11 @@ import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
const DeactivatePortal = (props) => {
const {
t,
greetingTitle,
linkData,
history,
companyInfoSettingsData,
} = props;
const { t, greetingTitle, linkData, companyInfoSettingsData } = props;
const [isDeactivate, setIsDeactivate] = useState(false);
const navigate = useNavigate();
const url = companyInfoSettingsData?.site
? companyInfoSettingsData.site
: "https://onlyoffice.com";
@ -37,14 +33,14 @@ const DeactivatePortal = (props) => {
try {
await suspendPortal(linkData.confirmHeader);
setIsDeactivate(true);
setTimeout(() => (location.href = url), 10000);
setTimeout(() => (window.location.href = url), 10000);
} catch (e) {
toastr.error(e);
}
};
const onCancelClick = () => {
history.push("/");
navigate("/");
};
return (
@ -101,9 +97,7 @@ export default inject(({ auth }) => ({
theme: auth.settingsStore.theme,
companyInfoSettingsData: auth.settingsStore.companyInfoSettingsData,
}))(
withRouter(
withTranslation(["Confirm", "Settings", "Common"])(
withLoader(observer(DeactivatePortal))
)
withTranslation(["Confirm", "Settings", "Common"])(
withLoader(observer(DeactivatePortal))
)
);

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { withTranslation, Trans } from "react-i18next";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
@ -13,14 +13,8 @@ import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
const ProfileRemoveForm = (props) => {
const {
t,
greetingTitle,
linkData,
logout,
legalTerms,
currentColorScheme,
} = props;
const { t, greetingTitle, linkData, logout, legalTerms, currentColorScheme } =
props;
const [isProfileDeleted, setIsProfileDeleted] = useState(false);
const [isLoading, setIsLoading] = useState(false);
@ -137,8 +131,4 @@ export default inject(({ auth }) => ({
logout: auth.logout,
legalTerms: auth.settingsStore.legalTerms,
currentColorScheme: auth.settingsStore.currentColorScheme,
}))(
withRouter(
withTranslation("Confirm")(withLoader(observer(ProfileRemoveForm)))
)
);
}))(withTranslation("Confirm")(withLoader(observer(ProfileRemoveForm))));

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Text from "@docspace/components/text";
@ -19,14 +19,9 @@ import FormWrapper from "@docspace/components/form-wrapper";
import DocspaceLogo from "../../../DocspaceLogo";
const RemovePortal = (props) => {
const {
t,
greetingTitle,
linkData,
history,
companyInfoSettingsData,
} = props;
const { t, greetingTitle, linkData, companyInfoSettingsData } = props;
const [isRemoved, setIsRemoved] = useState(false);
const navigate = useNavigate();
const url = companyInfoSettingsData?.site
? companyInfoSettingsData.site
@ -43,7 +38,7 @@ const RemovePortal = (props) => {
};
const onCancelClick = () => {
history.push("/");
navigate("/");
};
return (
@ -99,8 +94,4 @@ export default inject(({ auth }) => ({
greetingTitle: auth.settingsStore.greetingSettings,
theme: auth.settingsStore.theme,
companyInfoSettingsData: auth.settingsStore.companyInfoSettingsData,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(withLoader(observer(RemovePortal)))
)
);
}))(withTranslation(["Confirm", "Common"])(withLoader(observer(RemovePortal))));

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { Trans, withTranslation } from "react-i18next";
import styled from "styled-components";
import Button from "@docspace/components/button";
@ -94,7 +94,7 @@ const TfaActivationForm = withLoader((props) => {
qrCode,
loginWithCode,
loginWithCodeAndCookie,
history,
location,
currentColorScheme,
} = props;
@ -103,6 +103,8 @@ const TfaActivationForm = withLoader((props) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const navigate = useNavigate();
const onSubmit = async () => {
try {
const { user, hash } = (location && location.state) || {};
@ -112,10 +114,10 @@ const TfaActivationForm = withLoader((props) => {
if (user && hash) {
const url = await loginWithCode(user, hash, code);
history.push(url || "/");
navigate(url || "/");
} else {
const url = await loginWithCodeAndCookie(code, linkData.confirmHeader);
history.push("/");
navigate("/");
}
} catch (err) {
let errorMessage = "";
@ -303,8 +305,4 @@ export default inject(({ auth, confirm }) => ({
tfaIosAppUrl: auth.tfaStore.tfaIosAppUrl,
tfaWinAppUrl: auth.tfaStore.tfaWinAppUrl,
currentColorScheme: auth.settingsStore.currentColorScheme,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(observer(TfaActivationWrapper))
)
);
}))(withTranslation(["Confirm", "Common"])(observer(TfaActivationWrapper)));

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router";
import { useNavigate, useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import Button from "@docspace/components/button";
@ -48,12 +48,15 @@ const StyledForm = styled(Box)`
`;
const TfaAuthForm = withLoader((props) => {
const { t, loginWithCode, loginWithCodeAndCookie, location, history } = props;
const { t, loginWithCode, loginWithCodeAndCookie } = props;
const [code, setCode] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const navigate = useNavigate();
const location = useLocation();
const onSubmit = async () => {
try {
const { user, hash } = (location && location.state) || {};
@ -63,10 +66,10 @@ const TfaAuthForm = withLoader((props) => {
if (user && hash) {
const url = await loginWithCode(user, hash, code);
history.push(url || "/");
navigate(url || "/");
} else {
const url = await loginWithCodeAndCookie(code, linkData.confirmHeader);
history.push(url || "/");
navigate(url || "/");
}
} catch (err) {
let errorMessage = "";
@ -174,8 +177,4 @@ export default inject(({ auth, confirm }) => ({
setIsLoading: confirm.setIsLoading,
loginWithCode: auth.loginWithCode,
loginWithCodeAndCookie: auth.tfaStore.loginWithCodeAndCookie,
}))(
withRouter(
withTranslation(["Confirm", "Common"])(observer(TfaAuthFormWrapper))
)
);
}))(withTranslation(["Confirm", "Common"])(observer(TfaAuthFormWrapper)));

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import { observer, inject } from "mobx-react";
import { useNavigate } from "react-router-dom";
import Loader from "@docspace/components/loader";
import axios from "axios";
import { combineUrl } from "@docspace/common/utils";
@ -15,7 +16,7 @@ export default function withLoader(WrappedComponent) {
passwordSettings,
getSettings,
getPortalPasswordSettings,
history,
getAuthProviders,
getCapabilities,
} = props;
@ -24,6 +25,8 @@ export default function withLoader(WrappedComponent) {
const type = linkData ? linkData.type : null;
const confirmHeader = linkData ? linkData.confirmHeader : null;
const navigate = useNavigate();
useEffect(() => {
if (
(type === "PasswordChange" ||
@ -46,7 +49,7 @@ export default function withLoader(WrappedComponent) {
}
console.error(errorMessage);
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
`/login/error?message=${errorMessage}`
@ -70,7 +73,7 @@ export default function withLoader(WrappedComponent) {
errorMessage = error;
}
console.error(errorMessage);
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
`/login/error?message=${errorMessage}`
@ -121,11 +124,8 @@ export default function withLoader(WrappedComponent) {
return inject(({ auth, confirm }) => {
const { isLoaded, isLoading } = confirm;
const {
passwordSettings,
getSettings,
getPortalPasswordSettings,
} = auth.settingsStore;
const { passwordSettings, getSettings, getPortalPasswordSettings } =
auth.settingsStore;
const { getAuthProviders, getCapabilities } = auth;
return {

View File

@ -1,21 +1,18 @@
import React from "react";
import PropTypes from "prop-types";
import ErrorContainer from "@docspace/common/components/ErrorContainer";
import { useParams } from "react-router-dom";
import { I18nextProvider, useTranslation } from "react-i18next";
import i18n from "./i18n";
const Error520 = ({ match }) => {
const { t } = useTranslation(["Common"]);
const { error } = (match && match.params) || {};
const { error } = useParams();
return (
<ErrorContainer headerText={t("SomethingWentWrong")} bodyText={error} />
);
};
Error520.propTypes = {
match: PropTypes.object,
};
export default () => (
<I18nextProvider i18n={i18n}>
<Error520 />

View File

@ -1,7 +1,7 @@
import React from "react";
//import { Provider as FilesProvider } from "mobx-react";
import { inject, observer } from "mobx-react";
import { Switch, withRouter, Redirect } from "react-router-dom";
import { Routes, useLocation, Navigate, Route } from "react-router-dom";
//import config from "PACKAGE_FILE";
import PrivateRoute from "@docspace/common/components/PrivateRoute";
import AppLoader from "@docspace/common/components/AppLoader";
@ -30,6 +30,8 @@ import {
import GlobalEvents from "../components/GlobalEvents";
import Accounts from "./Accounts";
import Profile from "./Profile";
import NotificationComponent from "./Notifications";
// const homepage = config.homepage;
@ -49,10 +51,9 @@ import Accounts from "./Accounts";
const Error404 = React.lazy(() => import("client/Error404"));
const FilesArticle = React.memo(({ history, withMainButton }) => {
const isFormGallery = history.location.pathname
.split("/")
.includes("form-gallery");
const FilesArticle = React.memo(({ withMainButton }) => {
const location = useLocation();
const isFormGallery = location.pathname.split("/").includes("form-gallery");
return !isFormGallery ? (
<Article withMainButton={withMainButton}>
@ -73,89 +74,6 @@ const FilesArticle = React.memo(({ history, withMainButton }) => {
);
});
const FilesSection = React.memo(({ withMainButton }) => {
return (
<Switch>
{/*<PrivateRoute exact path={HISTORY_URL} component={VersionHistory} />*/}
{/* <PrivateRoute path={"/private"} component={PrivateRoomsPage} /> */}
<PrivateRoute
exact
path={"/settings"}
component={() => <Redirect to="/settings/common" />}
/>
<PrivateRoute
exact
path={["/", "/rooms"]}
component={() => <Redirect to="/rooms/shared" />}
/>
<PrivateRoute
restricted
withManager
withCollaborator
path={[
"/rooms/personal",
"/rooms/personal/filter",
"/files/trash",
"/files/trash/filter",
]}
component={Home}
/>
<PrivateRoute
path={[
"/rooms/shared",
"/rooms/shared/filter",
"/rooms/shared/:room",
"/rooms/shared/:room/filter",
"/rooms/archived",
"/rooms/archived/filter",
"/rooms/archived/:room",
"/rooms/archived/:room/filter",
// "/files/favorite",
// "/files/favorite/filter",
// "/files/recent",
// "/files/recent/filter",
"/products/files/",
]}
component={Home}
/>
{/* <PrivateRoute path={["/rooms/personal/filter"]} component={Home} /> */}
{/* <PrivateRoute path={"/#preview"} component={Home} /> */}
{/* <PrivateRoute path={"/rooms"} component={Home} /> */}
{/* <PrivateRoute path={ROOMS_URL} component={VirtualRooms} /> */}
<PrivateRoute
exact
restricted
withManager
path={["/accounts", "/accounts/filter", "/accounts/create/:type"]}
component={Accounts}
/>
<PrivateRoute
exact
path={["/accounts/view/@self", "/accounts/view/@self/notification"]}
component={Accounts}
/>
<PrivateRoute
exact
restricted
path={"/settings/admin"}
component={Settings}
/>
{withMainButton && (
<PrivateRoute exact path={"/settings/common"} component={Settings} />
)}
<PrivateRoute component={Error404Route} />
</Switch>
);
});
const Error404Route = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
@ -164,54 +82,197 @@ const Error404Route = (props) => (
</React.Suspense>
);
class FilesContent extends React.Component {
constructor(props) {
super(props);
const FilesSection = React.memo(({ withMainButton }) => {
return (
<Routes>
<Route
path="/"
element={
<PrivateRoute location={location}>
<Navigate to="/rooms/shared" replace />
</PrivateRoute>
}
/>
const pathname = window.location.pathname.toLowerCase();
this.isEditor = pathname.indexOf("doceditor") !== -1;
this.isDesktopInit = false;
}
<Route
path="/rooms"
element={
<PrivateRoute location={location}>
<Navigate to="/rooms/shared" replace />
</PrivateRoute>
}
/>
componentDidMount() {
<Route
path="/rooms/personal/*"
element={
<PrivateRoute
restricted
withManager
withCollaborator
location={location}
>
<Home />
</PrivateRoute>
}
/>
<Route
path="/files/trash/*"
element={
<PrivateRoute
restricted
withManager
withCollaborator
location={location}
>
<Home />
</PrivateRoute>
}
/>
<Route
path="/rooms/shared/*"
element={
<PrivateRoute location={location}>
<Home />
</PrivateRoute>
}
/>
<Route
path="/rooms/archived/*"
element={
<PrivateRoute location={location}>
<Home />
</PrivateRoute>
}
/>
<Route
path="/products/files/"
element={
<PrivateRoute location={location}>
<Home />
</PrivateRoute>
}
/>
<Route
path="/accounts/*"
element={
<PrivateRoute restricted withManager location={location}>
<Accounts />
</PrivateRoute>
}
/>
<Route
path="/accounts/create/:type"
element={
<PrivateRoute restricted withManager location={location}>
<Accounts />
</PrivateRoute>
}
/>
<Route
path="/accounts/view/@self"
element={
<PrivateRoute location={location}>
<Profile />
</PrivateRoute>
}
/>
<Route
path="accounts/view/@self/notification"
element={
<PrivateRoute location={location}>
<NotificationComponent />
</PrivateRoute>
}
/>
<Route
path={"/settings"}
element={
<PrivateRoute withCollaborator restricted location={location}>
<Navigate to="/settings/common" replace />
</PrivateRoute>
}
/>
<Route
path={"/settings/*"}
element={
<PrivateRoute withCollaborator restricted location={location}>
<Settings />
</PrivateRoute>
}
/>
<Route
element={
<PrivateRoute location={location}>
<Error404Route />
</PrivateRoute>
}
/>
</Routes>
);
});
const FilesContent = (props) => {
const pathname = window.location.pathname.toLowerCase();
const isEditor = pathname.indexOf("doceditor") !== -1;
const [isDesktopInit, setIsDesktopInit] = React.useState(false);
const {
loadFilesInfo,
setIsLoaded,
isAuthenticated,
user,
isEncryption,
encryptionKeys,
setEncryptionKeys,
isLoaded,
isDesktop,
showMenu,
isFrame,
withMainButton,
t,
} = props;
React.useEffect(() => {
loadScript("/static/scripts/tiff.min.js", "img-tiff-script");
this.props
.loadFilesInfo()
loadFilesInfo()
.catch((err) => toastr.error(err))
.finally(() => {
this.props.setIsLoaded(true);
setIsLoaded(true);
updateTempContent();
});
}
componentWillUnmount() {
const script = document.getElementById("img-tiff-script");
document.body.removeChild(script);
}
return () => {
const script = document.getElementById("img-tiff-script");
document.body.removeChild(script);
};
}, []);
componentDidUpdate(prevProps) {
const {
isAuthenticated,
user,
isEncryption,
encryptionKeys,
setEncryptionKeys,
isLoaded,
isDesktop,
} = this.props;
// console.log("componentDidUpdate: ", this.props);
if (isAuthenticated && !this.isDesktopInit && isDesktop && isLoaded) {
this.isDesktopInit = true;
React.useEffect(() => {
if (isAuthenticated && !isDesktopInit && isDesktop && isLoaded) {
setIsDesktopInit(true);
regDesktop(
user,
isEncryption,
encryptionKeys,
setEncryptionKeys,
this.isEditor,
isEditor,
null,
this.props.t
t
);
console.log(
"%c%s",
@ -220,25 +281,31 @@ class FilesContent extends React.Component {
encryptionKeys
);
}
}
}, [
t,
isAuthenticated,
user,
isEncryption,
encryptionKeys,
setEncryptionKeys,
isLoaded,
isDesktop,
isDesktopInit,
]);
render() {
const { showMenu, isFrame, withMainButton, history } = this.props;
return (
<>
<GlobalEvents />
<Panels />
{isFrame ? (
showMenu && <FilesArticle history={history} />
) : (
<FilesArticle history={history} withMainButton={withMainButton} />
)}
<FilesSection withMainButton={withMainButton} />
</>
);
}
}
return (
<>
<GlobalEvents />
<Panels />
{isFrame ? (
showMenu && <FilesArticle />
) : (
<FilesArticle withMainButton={withMainButton} />
)}
<FilesSection withMainButton={withMainButton} />
</>
);
};
const Files = inject(({ auth, filesStore }) => {
const {
@ -250,6 +317,8 @@ const Files = inject(({ auth, filesStore }) => {
isEncryptionSupport,
} = auth.settingsStore;
if (!auth.userStore.user) return;
const { isVisitor } = auth.userStore.user;
const withMainButton = !isVisitor;
@ -272,6 +341,6 @@ const Files = inject(({ auth, filesStore }) => {
//auth.setProductVersion(config.version);
},
};
})(withTranslation("Common")(observer(withRouter(FilesContent))));
})(withTranslation("Common")(observer(FilesContent)));
export default () => <Files />;

View File

@ -4,7 +4,7 @@ import React from "react";
import { inject, observer } from "mobx-react";
import IconButton from "@docspace/components/icon-button";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import {
StyledHeadline,
StyledContainer,
@ -18,20 +18,22 @@ import { getCategoryUrl } from "SRC_DIR/helpers/utils";
const SectionHeaderContent = (props) => {
const {
t,
history,
match,
isInfoPanelVisible,
setIsInfoPanelVisible,
setGallerySelected,
categoryType,
} = props;
const navigate = useNavigate();
const params = useParams();
const onBackToFiles = () => {
setGallerySelected(null);
const filter = FilesFilter.getDefault();
filter.folder = match.params.folderId;
filter.folder = params.folderId;
const filterParamsStr = filter.toUrlParams();
@ -39,7 +41,7 @@ const SectionHeaderContent = (props) => {
const pathname = `${url}?${filterParamsStr}`;
history.push(
navigate(
combineUrl(window.DocSpaceConfig?.proxy?.url, config.homepage, pathname)
);
};
@ -86,4 +88,4 @@ export default inject(({ auth, filesStore, oformsStore }) => {
setGallerySelected,
categoryType,
};
})(withTranslation("Common")(withRouter(observer(SectionHeaderContent))));
})(withTranslation("Common")(observer(SectionHeaderContent)));

View File

@ -9,7 +9,7 @@ import { ReactSVG } from "react-svg";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import FilesFilter from "@docspace/common/api/files/filter";
import { withRouter } from "react-router-dom";
import { useParams, useNavigate } from "react-router-dom";
import {
StyledTile,
@ -20,27 +20,39 @@ import {
} from "../StyledTileView";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
class Tile extends React.PureComponent {
constructor(props) {
super(props);
const Tile = (props) => {
const [errorLoadSrc, setErrorLoadSrc] = React.useState(false);
this.state = {
errorLoadSrc: false,
};
const cm = React.useRef();
const tile = React.useRef();
this.cm = React.createRef();
this.tile = React.createRef();
}
const {
t,
thumbnailClick,
item,
onError = () => {
this.setState({
errorLoadSrc: true,
});
setIsInfoPanelVisible,
categoryType,
isInfoPanelVisible,
setGallerySelected,
children,
contextButtonSpacerWidth,
tileContextClick,
isActive,
isSelected,
title,
showHotkeyBorder,
getIcon,
} = props;
const params = useParams();
const navigate = useNavigate();
const onError = () => {
setErrorLoadSrc(true);
};
getIconFile = () => {
const { thumbnailClick, item } = this.props;
const getIconFile = () => {
// const src =
// item.attributes.template_image.data.attributes.formats.small.url;
const src = item.attributes.card_prewiew.data.attributes.url;
@ -56,7 +68,7 @@ class Tile extends React.PureComponent {
src={src}
className="thumbnail-image"
alt="Thumbnail-img"
onError={this.onError}
onError={onError}
/>
</Link>
) : (
@ -64,27 +76,25 @@ class Tile extends React.PureComponent {
);
};
getContextModel = () => {
const getContextModel = () => {
return [
{
key: "create",
label: this.props.t("Common:Create"),
onClick: this.onCreateForm,
label: t("Common:Create"),
onClick: onCreateForm,
},
{
key: "template-info",
label: this.props.t("TemplateInfo"),
onClick: this.onShowTemplateInfo,
label: t("TemplateInfo"),
onClick: onShowTemplateInfo,
},
];
};
onCreateForm = () => {
const { match, history, setIsInfoPanelVisible, categoryType } = this.props;
const onCreateForm = () => {
const filter = FilesFilter.getDefault();
filter.folder = match.params.folderId;
filter.folder = params.folderId;
const filterParamsStr = filter.toUrlParams();
@ -94,89 +104,76 @@ class Tile extends React.PureComponent {
setIsInfoPanelVisible(false);
history.push(
navigate(
combineUrl(window.DocSpaceConfig?.proxy?.url, config.homepage, pathname)
);
};
onShowTemplateInfo = () => {
this.onSelectForm();
if (!this.props.isInfoPanelVisible) this.props.setIsInfoPanelVisible(true);
const onShowTemplateInfo = () => {
onSelectForm();
if (!isInfoPanelVisible) setIsInfoPanelVisible(true);
};
getOptions = () => ["create", "template-info"];
const getOptions = () => ["create", "template-info"];
onSelectForm = () => {
this.props.setGallerySelected(this.props.item);
const onSelectForm = () => {
setGallerySelected(item);
};
render() {
const {
children,
contextButtonSpacerWidth,
tileContextClick,
isActive,
isSelected,
title,
showHotkeyBorder,
getIcon,
} = this.props;
const src = getIcon(32, ".docxf");
const element = <img className="react-svg-icon" src={src} />;
const src = getIcon(32, ".docxf");
const element = <img className="react-svg-icon" src={src} />;
const onContextMenu = (e) => {
tileContextClick && tileContextClick();
if (!cm.current.menuRef.current) {
tile.current.click(e); //TODO: need fix context menu to global
}
cm.current.show(e);
};
const onContextMenu = (e) => {
tileContextClick && tileContextClick();
if (!this.cm.current.menuRef.current) {
this.tile.current.click(e); //TODO: need fix context menu to global
}
this.cm.current.show(e);
};
const icon = getIconFile();
const icon = this.getIconFile();
//TODO: OFORM isActive
//TODO: OFORM isActive
return (
<StyledTile
ref={tile}
isSelected={isSelected}
onContextMenu={onContextMenu}
isActive={isActive}
showHotkeyBorder={showHotkeyBorder}
onDoubleClick={onCreateForm}
onClick={onSelectForm}
className="files-item"
>
<StyledFileTileTop isActive={isActive}>{icon}</StyledFileTileTop>
return (
<StyledTile
ref={this.tile}
isSelected={isSelected}
onContextMenu={onContextMenu}
isActive={isActive}
showHotkeyBorder={showHotkeyBorder}
onDoubleClick={this.onCreateForm}
onClick={this.onSelectForm}
className="files-item"
>
<StyledFileTileTop isActive={isActive}>{icon}</StyledFileTileTop>
<StyledFileTileBottom isSelected={isSelected} isActive={isActive}>
<div className="file-icon_container">
<div className="file-icon">{element}</div>
</div>
<StyledFileTileBottom isSelected={isSelected} isActive={isActive}>
<div className="file-icon_container">
<div className="file-icon">{element}</div>
</div>
<StyledContent>{children}</StyledContent>
<StyledOptionButton spacerWidth={contextButtonSpacerWidth}>
<ContextMenuButton
className="expandButton"
directionX="right"
getData={getOptions}
isNew={true}
onClick={onContextMenu}
title={title}
/>
<StyledContent>{children}</StyledContent>
<StyledOptionButton spacerWidth={contextButtonSpacerWidth}>
<ContextMenuButton
className="expandButton"
directionX="right"
getData={this.getOptions}
isNew={true}
onClick={onContextMenu}
title={title}
/>
<ContextMenu
getContextModel={this.getContextModel}
ref={this.cm}
withBackdrop={true}
/>
</StyledOptionButton>
</StyledFileTileBottom>
</StyledTile>
);
}
}
<ContextMenu
getContextModel={getContextModel}
ref={cm}
withBackdrop={true}
/>
</StyledOptionButton>
</StyledFileTileBottom>
</StyledTile>
);
};
Tile.propTypes = {
children: PropTypes.oneOfType([
@ -214,4 +211,4 @@ export default inject(
categoryType,
};
}
)(withTranslation(["FormGallery", "Common"])(withRouter(observer(Tile))));
)(withTranslation(["FormGallery", "Common"])(observer(Tile)));

View File

@ -64,7 +64,7 @@ class DetailsHelper {
constructor(props) {
this.t = props.t;
this.item = props.item;
this.history = props.history;
this.navigate = props.navigate;
this.openUser = props.openUser;
this.personal = props.personal;
this.culture = props.culture;
@ -112,39 +112,40 @@ class DetailsHelper {
};
getNeededProperties = () => {
return (this.item.isRoom
? [
"Owner",
this.item.providerKey && "Storage Type",
"Type",
"Content",
"Date modified",
"Last modified by",
"Creation date",
this.item.tags.length && "Tags",
]
: this.item.isFolder
? [
"Owner",
//"Location",
"Type",
"Content",
"Date modified",
"Last modified by",
"Creation date",
]
: [
"Owner",
//"Location",
"Type",
"File extension",
"Size",
"Date modified",
"Last modified by",
"Creation date",
"Versions",
"Comments",
]
return (
this.item.isRoom
? [
"Owner",
this.item.providerKey && "Storage Type",
"Type",
"Content",
"Date modified",
"Last modified by",
"Creation date",
this.item.tags.length && "Tags",
]
: this.item.isFolder
? [
"Owner",
//"Location",
"Type",
"Content",
"Date modified",
"Last modified by",
"Creation date",
]
: [
"Owner",
//"Location",
"Type",
"File extension",
"Size",
"Date modified",
"Last modified by",
"Creation date",
"Versions",
"Comments",
]
).filter((nP) => !!nP);
};
@ -225,7 +226,7 @@ class DetailsHelper {
/// Property //
getItemOwner = () => {
const onOpenUser = () => this.openUser(this.item.createdBy, this.history);
const onOpenUser = () => this.openUser(this.item.createdBy, this.navigate);
return this.personal || this.isVisitor
? text(decode(this.item.createdBy?.displayName))
@ -277,7 +278,7 @@ class DetailsHelper {
};
getItemLastModifiedBy = () => {
const onOpenUser = () => this.openUser(this.item.updatedBy, this.history);
const onOpenUser = () => this.openUser(this.item.updatedBy, this.navigate);
return this.personal || this.isVisitor
? text(decode(this.item.updatedBy?.displayName))

View File

@ -1,5 +1,4 @@
import React, { useState, useEffect, useCallback } from "react";
import { withRouter } from "react-router";
import { inject, observer } from "mobx-react";
import ViewHelper from "./helpers/ViewHelper";
@ -207,4 +206,4 @@ export default inject(({ auth, selectedFolderStore, oformsStore }) => {
isRootFolder,
gallerySelected,
};
})(withRouter(observer(InfoPanelBodyContent)));
})(observer(InfoPanelBodyContent));

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from "react";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { inject } from "mobx-react";
import { withTranslation } from "react-i18next";
@ -25,14 +25,14 @@ const Details = ({
const [isThumbnailError, setIsThumbmailError] = useState(false);
const onThumbnailError = () => setIsThumbmailError(true);
const history = useHistory();
const navigate = useNavigate();
const detailsHelper = new DetailsHelper({
isVisitor,
t,
item: selection,
openUser,
history,
navigate,
personal,
culture,
});

View File

@ -1,5 +1,5 @@
import React from "react";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { decode } from "he";
import Link from "@docspace/components/link";
@ -13,10 +13,10 @@ const HistoryBlockUser = ({
isCollaborator,
}) => {
const username = user.displayName;
const history = useHistory();
const navigate = useNavigate();
const onUserClick = () => {
openUser(user, history);
openUser(user, navigate);
};
return (

View File

@ -1,9 +1,8 @@
import React, { useEffect } from "react";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate, useLocation } from "react-router-dom";
import queryString from "query-string";
import history from "@docspace/common/history";
import MediaViewer from "@docspace/common/components/MediaViewer";
const FilesMediaViewer = (props) => {
@ -16,7 +15,7 @@ const FilesMediaViewer = (props) => {
currentMediaFileId,
deleteItemAction,
setMediaViewerData,
location,
setRemoveMediaItem,
userAccess,
deleteDialogVisible,
@ -52,6 +51,9 @@ const FilesMediaViewer = (props) => {
setSelection,
} = props;
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (visible) {
resetSelection();
@ -97,7 +99,7 @@ const FilesMediaViewer = (props) => {
const onChangeUrl = (id) => {
const url = "/products/files/#preview/" + id;
setCurrentId(id);
window.history.pushState(null, null, url);
navigate(url);
};
const resetSelection = () => {
@ -109,7 +111,7 @@ const FilesMediaViewer = (props) => {
if (queryParams.has(queryName)) {
queryParams.delete(queryName);
history.replace({
navigate(_, {
search: queryParams.toString(),
});
}
@ -169,7 +171,7 @@ const FilesMediaViewer = (props) => {
const targetFile = files.find((item) => item.id === currentMediaFileId);
if (targetFile) setBufferSelection(targetFile);
window.history.replaceState(null, null, url);
navigate(url, { replace: true });
};
return (
@ -304,8 +306,4 @@ export default inject(
setSelection,
};
}
)(
withRouter(
withTranslation(["Files", "Translations"])(observer(FilesMediaViewer))
)
);
)(withTranslation(["Files", "Translations"])(observer(FilesMediaViewer)));

View File

@ -1,6 +1,5 @@
import React, { useCallback } from "react";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import styled, { css } from "styled-components";
import { isMobile, isTablet, isMobileOnly } from "react-device-detect";
@ -186,10 +185,8 @@ export default inject(({ auth, treeFoldersStore }) => {
return { theme: auth.settingsStore.theme, isTrashFolder: isRecycleBinFolder };
})(
observer(
withRouter(
withTranslation(["Files", "Translations"])(
withContent(withBadges(FilesRowContent))
)
withTranslation(["Files", "Translations"])(
withContent(withBadges(FilesRowContent))
)
)
);

View File

@ -4,7 +4,6 @@ import { withTranslation } from "react-i18next";
import DragAndDrop from "@docspace/components/drag-and-drop";
import Row from "@docspace/components/row";
import FilesRowContent from "./FilesRowContent";
import { withRouter } from "react-router-dom";
import { isTablet, isMobile } from "react-device-detect";
import withFileActions from "../../../../../HOCs/withFileActions";
@ -369,5 +368,5 @@ const SimpleFilesRow = (props) => {
};
export default withTranslation(["Files", "Translations", "InfoPanel"])(
withRouter(withFileActions(withQuickButtons(SimpleFilesRow)))
withFileActions(withQuickButtons(SimpleFilesRow))
);

View File

@ -1,5 +1,4 @@
import React, { useState } from "react";
import { withRouter } from "react-router";
import withContent from "../../../../../HOCs/withContent";
import withBadges from "../../../../../HOCs/withBadges";
import withQuickButtons from "../../../../../HOCs/withQuickButtons";
@ -170,7 +169,5 @@ const FilesTableRow = (props) => {
};
export default withTranslation(["Files", "Common", "InfoPanel"])(
withRouter(
withFileActions(withContent(withQuickButtons(withBadges(FilesTableRow))))
)
withFileActions(withContent(withQuickButtons(withBadges(FilesTableRow))))
);

View File

@ -6,7 +6,6 @@ import DragAndDrop from "@docspace/components/drag-and-drop";
import Tile from "./sub-components/Tile";
import FilesTileContent from "./FilesTileContent";
import { withRouter } from "react-router-dom";
import withFileActions from "../../../../../HOCs/withFileActions";
import withQuickButtons from "../../../../../HOCs/withQuickButtons";
@ -172,8 +171,6 @@ export default inject(
}
)(
withTranslation(["Files", "InfoPanel"])(
withRouter(
withFileActions(withBadges(withQuickButtons(observer(FileTile))))
)
withFileActions(withBadges(withQuickButtons(observer(FileTile))))
)
);

View File

@ -1,6 +1,5 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import styled, { css } from "styled-components";
@ -128,10 +127,8 @@ export default inject(({ auth, treeFoldersStore }) => {
return { theme: auth.settingsStore.theme, isRooms };
})(
observer(
withRouter(
withTranslation(["Files", "Translations"])(
withContent(withBadges(FilesTileContent))
)
withTranslation(["Files", "Translations"])(
withContent(withBadges(FilesTileContent))
)
)
);

View File

@ -1,5 +1,4 @@
import React, { useEffect } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { isMobile, isMobileOnly } from "react-device-detect";
@ -328,9 +327,7 @@ export default inject(
};
}
)(
withRouter(
withTranslation(["Files", "Common", "Translations"])(
withLoader(withHotkeys(observer(SectionBodyContent)))()
)
withTranslation(["Files", "Common", "Translations"])(
withLoader(withHotkeys(observer(SectionBodyContent)))()
)
);

View File

@ -3,7 +3,6 @@ import ViewTilesReactSvgUrl from "PUBLIC_DIR/images/view-tiles.react.svg?url";
import React, { useCallback, useEffect } from "react";
import { inject, observer } from "mobx-react";
import { isMobile } from "react-device-detect";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { isMobileOnly } from "react-device-detect";
import find from "lodash/find";
@ -1453,9 +1452,10 @@ const SectionFilterContent = ({
}
};
useEffect(() => (!!isLoadedFilter ? showLoader() : hideLoader()), [
isLoadedFilter,
]);
useEffect(
() => (!!isLoadedFilter ? showLoader() : hideLoader()),
[isLoadedFilter]
);
if (!isLoadedFilter) {
return <Loaders.Filter style={{ display: "none" }} id="filter-loader" />;
@ -1579,15 +1579,13 @@ export default inject(
};
}
)(
withRouter(
withLayoutSize(
withTranslation([
"Files",
"Settings",
"Common",
"Translations",
"InfoPanel",
])(withLoader(observer(SectionFilterContent))(<Loaders.Filter />))
)
withLayoutSize(
withTranslation([
"Files",
"Settings",
"Common",
"Translations",
"InfoPanel",
])(withLoader(observer(SectionFilterContent))(<Loaders.Filter />))
)
);

View File

@ -24,7 +24,7 @@ import CatalogTrashReactSvgUrl from "PUBLIC_DIR/images/catalog.trash.react.svg?u
import React from "react";
import copy from "copy-to-clipboard";
import styled, { css } from "styled-components";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import toastr from "@docspace/components/toast/toastr";
import Loaders from "@docspace/common/components/Loaders";
import { withTranslation } from "react-i18next";
@ -94,13 +94,12 @@ const StyledContainer = styled.div`
}
`;
class SectionHeaderContent extends React.Component {
constructor(props) {
super(props);
this.state = { navigationItems: [] };
}
const SectionHeaderContent = (props) => {
const [navigationItems, setNavigationItems] = React.useState([]);
onCreate = (format) => {
const navigate = useNavigate();
const onCreate = (format) => {
const event = new Event(Events.CREATE);
const payload = {
@ -113,9 +112,9 @@ class SectionHeaderContent extends React.Component {
window.dispatchEvent(event);
};
onCreateRoom = () => {
if (this.props.isGracePeriod) {
this.props.setInviteUsersWarningDialogVisible(true);
const onCreateRoom = () => {
if (props.isGracePeriod) {
props.setInviteUsersWarningDialogVisible(true);
return;
}
@ -123,21 +122,21 @@ class SectionHeaderContent extends React.Component {
window.dispatchEvent(event);
};
createDocument = () => this.onCreate("docx");
const createDocument = () => onCreate("docx");
createSpreadsheet = () => this.onCreate("xlsx");
const createSpreadsheet = () => onCreate("xlsx");
createPresentation = () => this.onCreate("pptx");
const createPresentation = () => onCreate("pptx");
createForm = () => this.onCreate("docxf");
const createForm = () => onCreate("docxf");
createFormFromFile = () => {
this.props.setSelectFileDialogVisible(true);
const createFormFromFile = () => {
props.setSelectFileDialogVisible(true);
};
onShowGallery = () => {
const { history, currentFolderId } = this.props;
history.push(
const onShowGallery = () => {
const { currentFolderId } = props;
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -146,10 +145,10 @@ class SectionHeaderContent extends React.Component {
);
};
createFolder = () => this.onCreate();
const createFolder = () => onCreate();
// TODO: add privacy room check for files
onUploadAction = (type) => {
const onUploadAction = (type) => {
const element =
type === "file"
? document.getElementById("customFileInput")
@ -158,21 +157,16 @@ class SectionHeaderContent extends React.Component {
element?.click();
};
getContextOptionsPlus = () => {
const {
t,
isPrivacyFolder,
isRoomsFolder,
enablePlugins,
security,
} = this.props;
const getContextOptionsPlus = () => {
const { t, isPrivacyFolder, isRoomsFolder, enablePlugins, security } =
props;
const options = isRoomsFolder
? [
{
key: "new-room",
label: t("NewRoom"),
onClick: this.onCreateRoom,
onClick: onCreateRoom,
icon: FolderLockedReactSvgUrl,
},
]
@ -181,21 +175,21 @@ class SectionHeaderContent extends React.Component {
id: "personal_new-documnet",
key: "new-document",
label: t("Common:NewDocument"),
onClick: this.createDocument,
onClick: createDocument,
icon: ActionsDocumentsReactSvgUrl,
},
{
id: "personal_new-spreadsheet",
key: "new-spreadsheet",
label: t("Common:NewSpreadsheet"),
onClick: this.createSpreadsheet,
onClick: createSpreadsheet,
icon: SpreadsheetReactSvgUrl,
},
{
id: "personal_new-presentation",
key: "new-presentation",
label: t("Common:NewPresentation"),
onClick: this.createPresentation,
onClick: createPresentation,
icon: ActionsPresentationReactSvgUrl,
},
{
@ -209,14 +203,14 @@ class SectionHeaderContent extends React.Component {
key: "new-form",
label: t("Translations:SubNewForm"),
icon: FormBlankReactSvgUrl,
onClick: this.createForm,
onClick: createForm,
},
{
id: "personal_template_new-form-file",
key: "new-form-file",
label: t("Translations:SubNewFormFile"),
icon: FormFileReactSvgUrl,
onClick: this.createFormFromFile,
onClick: createFormFromFile,
disabled: isPrivacyFolder,
},
{
@ -224,7 +218,7 @@ class SectionHeaderContent extends React.Component {
key: "oforms-gallery",
label: t("Common:OFORMsGallery"),
icon: FormGalleryReactSvgUrl,
onClick: this.onShowGallery,
onClick: onShowGallery,
disabled: isPrivacyFolder || (isMobile && isTablet),
},
],
@ -233,20 +227,20 @@ class SectionHeaderContent extends React.Component {
id: "personal_new-folder",
key: "new-folder",
label: t("Common:NewFolder"),
onClick: this.createFolder,
onClick: createFolder,
icon: CatalogFolderReactSvgUrl,
},
{ key: "separator", isSeparator: true },
{
key: "upload-files",
label: t("Article:UploadFiles"),
onClick: () => this.onUploadAction("file"),
onClick: () => onUploadAction("file"),
icon: ActionsUploadReactSvgUrl,
},
{
key: "upload-folder",
label: t("Article:UploadFolder"),
onClick: () => this.onUploadAction("folder"),
onClick: () => onUploadAction("folder"),
icon: ActionsUploadReactSvgUrl,
},
];
@ -267,9 +261,8 @@ class SectionHeaderContent extends React.Component {
return options;
};
createLinkForPortalUsers = () => {
const { currentFolderId } = this.props;
const { t } = this.props;
const createLinkForPortalUsers = () => {
const { currentFolderId, t } = props;
copy(
`${window.location.origin}/filter?folder=${currentFolderId}` //TODO: Change url by category
@ -278,28 +271,28 @@ class SectionHeaderContent extends React.Component {
toastr.success(t("Translations:LinkCopySuccess"));
};
onMoveAction = () => {
this.props.setIsFolderActions(true);
this.props.setBufferSelection(this.props.selectedFolder);
return this.props.setMoveToPanelVisible(true);
const onMoveAction = () => {
props.setIsFolderActions(true);
props.setBufferSelection(props.selectedFolder);
return props.setMoveToPanelVisible(true);
};
onCopyAction = () => {
this.props.setIsFolderActions(true);
this.props.setBufferSelection(this.props.currentFolderId);
return this.props.setCopyPanelVisible(true);
const onCopyAction = () => {
props.setIsFolderActions(true);
props.setBufferSelection(props.currentFolderId);
return props.setCopyPanelVisible(true);
};
downloadAction = () => {
this.props.setBufferSelection(this.props.currentFolderId);
this.props.setIsFolderActions(true);
this.props
.downloadAction(this.props.t("Translations:ArchivingData"), [
this.props.currentFolderId,
const downloadAction = () => {
props.setBufferSelection(props.currentFolderId);
props.setIsFolderActions(true);
props
.downloadAction(props.t("Translations:ArchivingData"), [
props.currentFolderId,
])
.catch((err) => toastr.error(err));
};
renameAction = () => {
const { selectedFolder } = this.props;
const renameAction = () => {
const { selectedFolder } = props;
const event = new Event(Events.RENAME);
@ -308,13 +301,13 @@ class SectionHeaderContent extends React.Component {
window.dispatchEvent(event);
};
onOpenSharingPanel = () => {
this.props.setBufferSelection(this.props.currentFolderId);
this.props.setIsFolderActions(true);
return this.props.setSharingPanelVisible(true);
const onOpenSharingPanel = () => {
props.setBufferSelection(props.currentFolderId);
props.setIsFolderActions(true);
return props.setSharingPanelVisible(true);
};
onDeleteAction = () => {
const onDeleteAction = () => {
const {
t,
deleteAction,
@ -324,9 +317,10 @@ class SectionHeaderContent extends React.Component {
currentFolderId,
getFolderInfo,
setBufferSelection,
} = this.props;
setIsFolderActions,
} = props;
this.props.setIsFolderActions(true);
setIsFolderActions(true);
if (confirmDelete || isThirdPartySelection) {
getFolderInfo(currentFolderId).then((data) => {
@ -347,58 +341,66 @@ class SectionHeaderContent extends React.Component {
}
};
onEmptyTrashAction = () => {
const { activeFiles, activeFolders } = this.props;
const onEmptyTrashAction = () => {
const { activeFiles, activeFolders, setEmptyTrashDialogVisible } = props;
const isExistActiveItems = [...activeFiles, ...activeFolders].length > 0;
if (isExistActiveItems) return;
this.props.setEmptyTrashDialogVisible(true);
setEmptyTrashDialogVisible(true);
};
onRestoreAllAction = () => {
const { activeFiles, activeFolders } = this.props;
const onRestoreAllAction = () => {
const { activeFiles, activeFolders, setRestoreAllPanelVisible } = props;
const isExistActiveItems = [...activeFiles, ...activeFolders].length > 0;
if (isExistActiveItems) return;
this.props.setRestoreAllPanelVisible(true);
setRestoreAllPanelVisible(true);
};
onRestoreAllArchiveAction = () => {
const { activeFiles, activeFolders } = this.props;
const onRestoreAllArchiveAction = () => {
const {
activeFiles,
activeFolders,
isGracePeriod,
setInviteUsersWarningDialogVisible,
setArchiveAction,
setRestoreAllArchive,
setArchiveDialogVisible,
} = props;
const isExistActiveItems = [...activeFiles, ...activeFolders].length > 0;
if (isExistActiveItems) return;
if (this.props.isGracePeriod) {
this.props.setInviteUsersWarningDialogVisible(true);
if (isGracePeriod) {
setInviteUsersWarningDialogVisible(true);
return;
}
this.props.setArchiveAction("unarchive");
this.props.setRestoreAllArchive(true);
this.props.setArchiveDialogVisible(true);
setArchiveAction("unarchive");
setRestoreAllArchive(true);
setArchiveDialogVisible(true);
};
onShowInfo = () => {
const { setIsInfoPanelVisible } = this.props;
const onShowInfo = () => {
const { setIsInfoPanelVisible } = props;
setIsInfoPanelVisible(true);
};
onToggleInfoPanel = () => {
const { isInfoPanelVisible, setIsInfoPanelVisible } = this.props;
const onToggleInfoPanel = () => {
const { isInfoPanelVisible, setIsInfoPanelVisible } = props;
setIsInfoPanelVisible(!isInfoPanelVisible);
};
onCopyLinkAction = () => {
const { t, selectedFolder, onCopyLink } = this.props;
const onCopyLinkAction = () => {
const { t, selectedFolder, onCopyLink } = props;
onCopyLink && onCopyLink({ ...selectedFolder, isFolder: true }, t);
};
getContextOptionsFolder = () => {
const getContextOptionsFolder = () => {
const {
t,
isRoom,
@ -418,7 +420,7 @@ class SectionHeaderContent extends React.Component {
canDeleteAll,
security,
} = this.props;
} = props;
const isDisabled = isRecycleBinFolder || isRoom;
@ -428,7 +430,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_empty-archive",
key: "empty-archive",
label: t("ArchiveAction"),
onClick: this.onEmptyTrashAction,
onClick: onEmptyTrashAction,
disabled: !canDeleteAll,
icon: ClearTrashReactSvgUrl,
},
@ -436,7 +438,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_restore-all",
key: "restore-all",
label: t("RestoreAll"),
onClick: this.onRestoreAllArchiveAction,
onClick: onRestoreAllArchiveAction,
disabled: !canRestoreAll,
icon: MoveReactSvgUrl,
},
@ -448,7 +450,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_sharing-settings",
key: "sharing-settings",
label: t("SharingPanel:SharingSettingsTitle"),
onClick: this.onOpenSharingPanel,
onClick: onOpenSharingPanel,
disabled: true,
icon: ShareReactSvgUrl,
},
@ -456,7 +458,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_link-portal-users",
key: "link-portal-users",
label: t("LinkForPortalUsers"),
onClick: this.createLinkForPortalUsers,
onClick: createLinkForPortalUsers,
disabled: true,
icon: InvitationLinkReactSvgUrl,
},
@ -464,7 +466,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_link-for-room-members",
key: "link-for-room-members",
label: t("LinkForRoomMembers"),
onClick: this.onCopyLinkAction,
onClick: onCopyLinkAction,
disabled: isRecycleBinFolder || isPersonalRoom,
icon: InvitationLinkReactSvgUrl,
},
@ -472,7 +474,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_empty-trash",
key: "empty-trash",
label: t("RecycleBinAction"),
onClick: this.onEmptyTrashAction,
onClick: onEmptyTrashAction,
disabled: !isRecycleBinFolder,
icon: ClearTrashReactSvgUrl,
},
@ -480,7 +482,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_restore-all",
key: "restore-all",
label: t("RestoreAll"),
onClick: this.onRestoreAllAction,
onClick: onRestoreAllAction,
disabled: !isRecycleBinFolder,
icon: MoveReactSvgUrl,
},
@ -488,7 +490,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_show-info",
key: "show-info",
label: t("Common:Info"),
onClick: this.onShowInfo,
onClick: onShowInfo,
disabled: isDisabled,
icon: InfoOutlineReactSvgUrl,
},
@ -521,7 +523,7 @@ class SectionHeaderContent extends React.Component {
key: "room-info",
label: t("Common:Info"),
icon: InfoOutlineReactSvgUrl,
onClick: this.onToggleInfoPanel,
onClick: onToggleInfoPanel,
disabled: !isRoom,
},
{
@ -544,7 +546,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_download",
key: "download",
label: t("Common:Download"),
onClick: this.downloadAction,
onClick: downloadAction,
disabled: isDisabled,
icon: DownloadReactSvgUrl,
},
@ -552,7 +554,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_move-to",
key: "move-to",
label: t("MoveTo"),
onClick: this.onMoveAction,
onClick: onMoveAction,
disabled: isDisabled || !security?.MoveTo,
icon: MoveReactSvgUrl,
},
@ -560,7 +562,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_copy",
key: "copy",
label: t("Translations:Copy"),
onClick: this.onCopyAction,
onClick: onCopyAction,
disabled: isDisabled || !security?.CopyTo,
icon: CopyReactSvgUrl,
},
@ -568,7 +570,7 @@ class SectionHeaderContent extends React.Component {
id: "header_option_rename",
key: "rename",
label: t("Rename"),
onClick: this.renameAction,
onClick: renameAction,
disabled: isDisabled || !security?.Rename,
icon: RenameReactSvgUrl,
},
@ -582,29 +584,24 @@ class SectionHeaderContent extends React.Component {
id: "header_option_delete",
key: "delete",
label: t("Common:Delete"),
onClick: this.onDeleteAction,
onClick: onDeleteAction,
disabled: isDisabled || !security?.Delete,
icon: CatalogTrashReactSvgUrl,
},
];
};
onSelect = (e) => {
const onSelect = (e) => {
const key = e.currentTarget.dataset.key;
this.props.setSelected(key);
props.setSelected(key);
};
onClose = () => {
this.props.setSelected("close");
const onClose = () => {
props.setSelected("close");
};
getMenuItems = () => {
const {
t,
cbMenuItems,
getCheckboxItemLabel,
getCheckboxItemId,
} = this.props;
const getMenuItems = () => {
const { t, cbMenuItems, getCheckboxItemLabel, getCheckboxItemId } = props;
const checkboxOptions = (
<>
{cbMenuItems.map((key) => {
@ -616,7 +613,7 @@ class SectionHeaderContent extends React.Component {
key={key}
label={label}
data-key={key}
onClick={this.onSelect}
onClick={onSelect}
/>
);
})}
@ -626,17 +623,13 @@ class SectionHeaderContent extends React.Component {
return checkboxOptions;
};
onChange = (checked) => {
this.props.setSelected(checked ? "all" : "none");
const onChange = (checked) => {
props.setSelected(checked ? "all" : "none");
};
onClickFolder = (id, isRootRoom) => {
const {
setSelectedNode,
setIsLoading,
fetchFiles,
moveToRoomsPage,
} = this.props;
const onClickFolder = (id, isRootRoom) => {
const { setSelectedNode, setIsLoading, fetchFiles, moveToRoomsPage } =
props;
if (isRootRoom) {
return moveToRoomsPage();
@ -649,122 +642,117 @@ class SectionHeaderContent extends React.Component {
.finally(() => setIsLoading(false));
};
render() {
//console.log("Body header render");
const {
t,
tReady,
isInfoPanelVisible,
isRootFolder,
title,
const {
t,
tReady,
isInfoPanelVisible,
isRootFolder,
title,
isDesktop,
isTabletView,
personal,
navigationPath,
getHeaderMenu,
isRecycleBinFolder,
isArchiveFolder,
isEmptyFilesList,
isHeaderVisible,
isHeaderChecked,
isHeaderIndeterminate,
showText,
isRoomsFolder,
isEmptyPage,
isDesktop,
isTabletView,
personal,
navigationPath,
getHeaderMenu,
isRecycleBinFolder,
isArchiveFolder,
isEmptyFilesList,
isHeaderVisible,
isHeaderChecked,
isHeaderIndeterminate,
showText,
isRoomsFolder,
isEmptyPage,
isEmptyArchive,
isEmptyArchive,
isRoom,
isGroupMenuBlocked,
security,
onClickBack,
hideContextMenuInsideArchiveRoom,
activeFiles,
activeFolders,
} = props;
isRoom,
isGroupMenuBlocked,
security,
onClickBack,
hideContextMenuInsideArchiveRoom,
} = this.props;
const menuItems = getMenuItems();
const isLoading = !title || !tReady;
const headerMenu = getHeaderMenu(t);
const isEmptyTrash = !![...activeFiles, ...activeFolders].length;
const menuItems = this.getMenuItems();
const isLoading = !title || !tReady;
const headerMenu = getHeaderMenu(t);
const isEmptyTrash = !![
...this.props.activeFiles,
...this.props.activeFolders,
].length;
return [
<Consumer key="header">
{(context) => (
<StyledContainer
isRecycleBinFolder={isRecycleBinFolder}
hideContextMenuInsideArchiveRoom={hideContextMenuInsideArchiveRoom}
>
{isHeaderVisible && headerMenu.length ? (
<TableGroupMenu
checkboxOptions={menuItems}
onChange={this.onChange}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
isInfoPanelVisible={isInfoPanelVisible}
toggleInfoPanel={this.onToggleInfoPanel}
isMobileView={isMobileOnly}
isBlocked={isGroupMenuBlocked}
/>
) : (
<div className="header-container">
{isLoading ? (
<Loaders.SectionHeader />
) : (
<Navigation
sectionWidth={context.sectionWidth}
showText={showText}
isRootFolder={isRootFolder}
canCreate={security?.Create}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}
personal={personal}
tReady={tReady}
menuItems={menuItems}
navigationItems={navigationPath}
getContextOptionsPlus={this.getContextOptionsPlus}
getContextOptionsFolder={this.getContextOptionsFolder}
onClose={this.onClose}
onClickFolder={this.onClickFolder}
isTrashFolder={isRecycleBinFolder}
isRecycleBinFolder={isRecycleBinFolder || isArchiveFolder}
isEmptyFilesList={
isArchiveFolder ? isEmptyArchive : isEmptyFilesList
}
clearTrash={this.onEmptyTrashAction}
onBackToParentFolder={onClickBack}
toggleInfoPanel={this.onToggleInfoPanel}
isInfoPanelVisible={isInfoPanelVisible}
titles={{
trash: t("EmptyRecycleBin"),
trashWarning: t("TrashErasureWarning"),
}}
withMenu={!isRoomsFolder}
onPlusClick={this.onCreateRoom}
isEmptyPage={isEmptyPage}
isRoom={isRoom}
/>
)}
</div>
)}
</StyledContainer>
)}
</Consumer>,
isRecycleBinFolder && !isEmptyPage && (
<TrashWarning
key="trash-warning"
title={t("Files:TrashErasureWarning")}
isTabletView
/>
),
];
}
}
return [
<Consumer key="header">
{(context) => (
<StyledContainer
isRecycleBinFolder={isRecycleBinFolder}
hideContextMenuInsideArchiveRoom={hideContextMenuInsideArchiveRoom}
>
{isHeaderVisible && headerMenu.length ? (
<TableGroupMenu
checkboxOptions={menuItems}
onChange={onChange}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
isInfoPanelVisible={isInfoPanelVisible}
toggleInfoPanel={onToggleInfoPanel}
isMobileView={isMobileOnly}
isBlocked={isGroupMenuBlocked}
/>
) : (
<div className="header-container">
{isLoading ? (
<Loaders.SectionHeader />
) : (
<Navigation
sectionWidth={context.sectionWidth}
showText={showText}
isRootFolder={isRootFolder}
canCreate={security?.Create}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}
personal={personal}
tReady={tReady}
menuItems={menuItems}
navigationItems={navigationPath}
getContextOptionsPlus={getContextOptionsPlus}
getContextOptionsFolder={getContextOptionsFolder}
onClose={onClose}
onClickFolder={onClickFolder}
isTrashFolder={isRecycleBinFolder}
isRecycleBinFolder={isRecycleBinFolder || isArchiveFolder}
isEmptyFilesList={
isArchiveFolder ? isEmptyArchive : isEmptyFilesList
}
clearTrash={onEmptyTrashAction}
onBackToParentFolder={onClickBack}
toggleInfoPanel={onToggleInfoPanel}
isInfoPanelVisible={isInfoPanelVisible}
titles={{
trash: t("EmptyRecycleBin"),
trashWarning: t("TrashErasureWarning"),
}}
withMenu={!isRoomsFolder}
onPlusClick={onCreateRoom}
isEmptyPage={isEmptyPage}
isRoom={isRoom}
/>
)}
</div>
)}
</StyledContainer>
)}
</Consumer>,
isRecycleBinFolder && !isEmptyPage && (
<TrashWarning
key="trash-warning"
title={t("Files:TrashErasureWarning")}
isTabletView
/>
),
];
};
export default inject(
({
@ -841,14 +829,8 @@ export default inject(
const { setIsVisible, isVisible } = auth.infoPanelStore;
const {
title,
id,
roomType,
pathParts,
navigationPath,
security,
} = selectedFolderStore;
const { title, id, roomType, pathParts, navigationPath, security } =
selectedFolderStore;
const selectedFolder = { ...selectedFolderStore };
@ -971,9 +953,5 @@ export default inject(
"InfoPanel",
"SharingPanel",
"Article",
])(
withLoader(withRouter(observer(SectionHeaderContent)))(
<Loaders.SectionHeader />
)
)
])(withLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />))
);

View File

@ -1,6 +1,5 @@
import React from "react";
//import PropTypes from "prop-types";
import { withRouter } from "react-router";
import { isMobile } from "react-device-detect";
import axios from "axios";
import toastr from "@docspace/components/toast/toastr";
@ -662,12 +661,8 @@ export default inject(
itemsSelectionTitle,
} = secondaryProgressDataStore;
const {
setUploadPanelVisible,
startUpload,
uploaded,
converted,
} = uploadDataStore;
const { setUploadPanelVisible, startUpload, uploaded, converted } =
uploadDataStore;
const { uploadEmptyFolders } = filesActionsStore;
@ -773,4 +768,4 @@ export default inject(
isLoadedEmptyPage,
};
}
)(withRouter(observer(Home)));
)(observer(Home));

View File

@ -5,7 +5,6 @@ import PeopleStore from "../../store/PeopleStore";
import PropTypes from "prop-types";
import Section from "@docspace/common/components/Section";
import toastr from "@docspace/components/toast/toastr";
import { withRouter } from "react-router";
import { Provider as PeopleProvider, inject, observer } from "mobx-react";
import { I18nextProvider, withTranslation } from "react-i18next";
@ -89,25 +88,21 @@ class My extends React.Component {
My.propTypes = {
fetchProfile: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
match: PropTypes.object.isRequired,
profile: PropTypes.object,
language: PropTypes.string,
};
const MyProfile = withRouter(
inject(({ auth, peopleStore }) => ({
setDocumentTitle: auth.setDocumentTitle,
language: auth.language,
resetProfile: peopleStore.targetUserStore.resetTargetUser,
fetchProfile: peopleStore.targetUserStore.getTargetUser,
profile: peopleStore.targetUserStore.targetUser,
setLoadedProfile: peopleStore.loadingStore.setLoadedProfile,
setIsLoading: peopleStore.loadingStore.setIsLoading,
setFirstLoad: peopleStore.loadingStore.setFirstLoad,
}))(withTranslation(["Profile", "ProfileAction"])(observer(My)))
);
const MyProfile = inject(({ auth, peopleStore }) => ({
setDocumentTitle: auth.setDocumentTitle,
language: auth.language,
resetProfile: peopleStore.targetUserStore.resetTargetUser,
fetchProfile: peopleStore.targetUserStore.getTargetUser,
profile: peopleStore.targetUserStore.targetUser,
setLoadedProfile: peopleStore.loadingStore.setLoadedProfile,
setIsLoading: peopleStore.loadingStore.setIsLoading,
setFirstLoad: peopleStore.loadingStore.setFirstLoad,
}))(withTranslation(["Profile", "ProfileAction"])(observer(My)));
const peopleStore = new PeopleStore();
export default ({ i18n, ...rest }) => {

View File

@ -1,15 +1,17 @@
import React from "react";
import config from "PACKAGE_FILE";
import { useNavigate } from "react-router-dom";
import IconButton from "@docspace/components/icon-button";
import { combineUrl } from "@docspace/common/utils";
import Headline from "@docspace/common/components/Headline";
import { StyledSectionHeader } from "../../StyledComponent";
const SectionHeaderContent = ({ history, t }) => {
const SectionHeaderContent = ({ t }) => {
const navigate = useNavigate();
const onClickBack = () => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,

View File

@ -8,17 +8,18 @@ import SectionBodyContent from "./Section/Body/index";
import SectionHeaderContent from "./Section/Header/index";
const NotificationComponent = (props) => {
const { history, setSelectedNode } = props;
const { setSelectedNode, setFirstLoad } = props;
const { t, ready } = useTranslation("Notifications");
useEffect(() => {
setFirstLoad(false);
setSelectedNode(["accounts"]);
}, []);
return (
<Section>
<Section.SectionHeader>
<SectionHeaderContent history={history} t={t} />
<SectionHeaderContent t={t} />
</Section.SectionHeader>
<Section.SectionBody>
@ -28,10 +29,11 @@ const NotificationComponent = (props) => {
);
};
export default inject(({ treeFoldersStore }) => {
export default inject(({ treeFoldersStore, filesStore }) => {
const { setSelectedNode } = treeFoldersStore;
const { setFirstLoad } = filesStore;
return {
setFirstLoad,
setSelectedNode,
};
})(observer(NotificationComponent));

View File

@ -1,5 +1,5 @@
import React from "react";
import { withRouter } from "react-router";
import { useNavigate, useLocation, useParams } from "react-router-dom";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
@ -94,16 +94,36 @@ const getTreeItems = (data, path, t) => {
});
};
class ArticleBodyContent extends React.Component {
constructor(props) {
super(props);
const ArticleBodyContent = (props) => {
const {
t,
const fullSettingsUrl = props.match.url;
const locationPathname = props.location.pathname;
tReady,
setIsLoadedArticleBody,
toggleArticleOpen,
showText,
isNotPaidPeriod,
isOwner,
isLoadedArticleBody,
} = props;
const fullSettingsUrlLength = fullSettingsUrl.length;
const resultPath = locationPathname.slice(fullSettingsUrlLength + 1);
const [selectedKeys, setSelectedKeys] = React.useState([]);
const prevLocation = React.useRef(null);
const navigate = useNavigate();
const location = useLocation();
React.useEffect(() => {
prevLocation.current = location;
}, [location]);
React.useEffect(() => {
const locationPathname = location.pathname;
const resultPath = locationPathname;
const arrayOfParams = resultPath.split("/");
arrayOfParams.splice(0, 2);
let link = "";
const selectedItem = arrayOfParams[arrayOfParams.length - 1];
@ -116,6 +136,7 @@ class ArticleBodyContent extends React.Component {
} else if (selectedItem === "accessrights") {
link = `/${resultPath}/owner`;
}
const CurrentSettingsCategoryKey = getCurrentSettingsCategory(
arrayOfParams,
settingsTree
@ -125,78 +146,69 @@ class ArticleBodyContent extends React.Component {
link = getSelectedLinkByKey(CurrentSettingsCategoryKey, settingsTree);
}
this.state = {
selectedKeys: [CurrentSettingsCategoryKey],
};
}
componentDidUpdate(prevProps, prevState) {
const { tReady, setIsLoadedArticleBody } = this.props;
setSelectedKeys([CurrentSettingsCategoryKey]);
}, []);
React.useEffect(() => {
if (tReady) setIsLoadedArticleBody(true);
if (prevProps.location.pathname !== this.props.location.pathname) {
if (this.props.location.pathname.includes("common")) {
this.setState({ selectedKeys: ["0-0"] });
if (prevLocation.current.pathname !== location.pathname) {
if (location.pathname.includes("common")) {
setSelectedKeys(["0-0"]);
}
if (this.props.location.pathname.includes("security")) {
this.setState({ selectedKeys: ["1-0"] });
if (location.pathname.includes("security")) {
setSelectedKeys(["1-0"]);
}
if (this.props.location.pathname.includes("backup")) {
this.setState({ selectedKeys: ["2-0"] });
if (location.pathname.includes("backup")) {
setSelectedKeys(["2-0"]);
}
if (this.props.location.pathname.includes("restore")) {
this.setState({ selectedKeys: ["3-0"] });
if (location.pathname.includes("restore")) {
setSelectedKeys(["3-0"]);
}
if (this.props.location.pathname.includes("integration")) {
this.setState({ selectedKeys: ["4-0"] });
if (location.pathname.includes("integration")) {
setSelectedKeys(["4-0"]);
}
if (this.props.location.pathname.includes("developer")) {
this.setState({ selectedKeys: ["5-0"] });
if (location.pathname.includes("developer")) {
setSelectedKeys(["5-0"]);
}
if (this.props.location.pathname.includes("delete-data")) {
this.setState({ selectedKeys: ["6-0"] });
if (location.pathname.includes("delete-data")) {
setSelectedKeys(["6-0"]);
}
if (this.props.location.pathname.includes("payments")) {
this.setState({ selectedKeys: ["7-0"] });
if (location.pathname.includes("payments")) {
setSelectedKeys(["7-0"]);
}
}
}
onSelect = (value) => {
const { selectedKeys } = this.state;
const { toggleArticleOpen } = this.props;
}, [tReady, setIsLoadedArticleBody, location.pathname, selectedKeys]);
const onSelect = (value) => {
if (isArrayEqual([value], selectedKeys)) {
return;
}
this.setState({ selectedKeys: [value + "-0"] });
setSelectedKeys([value + "-0"]);
if (isMobileOnly || isMobile()) {
toggleArticleOpen();
}
const { match, history } = this.props;
const settingsPath = getSelectedLinkByKey(value + "-0", settingsTree);
const newPath = match.path + settingsPath;
const currentUrl = window.location.href.replace(window.location.origin, "");
const settingsPath = `/portal-settings${getSelectedLinkByKey(
value + "-0",
settingsTree
)}`;
if (newPath === currentUrl) return;
if (settingsPath === location.pathname) return;
history.push(newPath);
navigate(`${settingsPath}`, { relative: false });
};
mapKeys = (tKey) => {
const { t } = this.props;
const mapKeys = (tKey) => {
switch (tKey) {
case "AccessRights":
return t("Common:AccessRights");
@ -237,11 +249,9 @@ class ArticleBodyContent extends React.Component {
}
};
catalogItems = () => {
const { selectedKeys } = this.state;
const { showText, isNotPaidPeriod, t, isOwner } = this.props;
const catalogItems = () => {
const items = [];
let resultTree = [...settingsTree];
if (isNotPaidPeriod) {
@ -261,6 +271,8 @@ class ArticleBodyContent extends React.Component {
}
}
if (selectedKeys.length === 0) return <></>;
resultTree.map((item) => {
items.push(
<CatalogItem
@ -268,10 +280,10 @@ class ArticleBodyContent extends React.Component {
id={item.key}
icon={item.icon}
showText={showText}
text={this.mapKeys(item.tKey)}
text={mapKeys(item.tKey)}
value={item.link}
isActive={item.key === selectedKeys[0][0]}
onClick={() => this.onSelect(item.key)}
onClick={() => onSelect(item.key)}
folderId={item.id}
style={{ marginTop: `${item.key.includes(7) ? "16px" : "0"}` }}
/>
@ -281,13 +293,10 @@ class ArticleBodyContent extends React.Component {
return items;
};
render() {
const items = this.catalogItems();
const { isLoadedArticleBody } = this.props;
const items = catalogItems();
return !isLoadedArticleBody ? <LoaderArticleBody /> : <>{items}</>;
}
}
return !isLoadedArticleBody ? <LoaderArticleBody /> : <>{items}</>;
};
export default inject(({ auth, common }) => {
const { isLoadedArticleBody, setIsLoadedArticleBody } = common;
@ -306,8 +315,6 @@ export default inject(({ auth, common }) => {
};
})(
withLoading(
withRouter(
withTranslation(["Settings", "Common"])(observer(ArticleBodyContent))
)
withTranslation(["Settings", "Common"])(observer(ArticleBodyContent))
)
);

View File

@ -4,7 +4,7 @@ import ActionsHeaderTouchReactSvgUrl from "PUBLIC_DIR/images/actions.header.touc
import React from "react";
import { inject, observer } from "mobx-react";
import styled, { css } from "styled-components";
import { withRouter } from "react-router";
import { useNavigate, useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import Headline from "@docspace/common/components/Headline";
import IconButton from "@docspace/components/icon-button";
@ -117,20 +117,29 @@ const StyledContainer = styled.div`
}
`;
class SectionHeaderContent extends React.Component {
constructor(props) {
super(props);
const SectionHeaderContent = (props) => {
const {
isBrandingAndCustomizationAvailable,
isRestoreAndAutoBackupAvailable,
tReady,
setIsLoadedSectionHeader,
} = props;
const { match, location } = props;
const fullSettingsUrl = match.url;
const locationPathname = location.pathname;
const navigate = useNavigate();
const location = useLocation();
const fullSettingsUrlLength = fullSettingsUrl.length;
const [state, setState] = React.useState({
header: "",
isCategoryOrHeader: false,
showSelector: false,
isHeaderVisible: false,
});
const resultPath = locationPathname.slice(fullSettingsUrlLength + 1);
const arrayOfParams = resultPath.split("/");
React.useEffect(() => {
const arrayOfParams = location.pathname.split("/");
const key = getKeyByLink(arrayOfParams, settingsTree);
const currKey = key.length > 3 ? key : key[0];
const header = getTKeyByKey(currKey, settingsTree);
const isCategory = checkPropertyByLink(
@ -144,20 +153,14 @@ class SectionHeaderContent extends React.Component {
"isHeader"
);
this.state = {
setState((val) => ({
...val,
header,
isCategoryOrHeader: isCategory || isHeader,
showSelector: false,
isHeaderVisible: false,
};
}
isAvailableSettings = (key) => {
const {
isBrandingAndCustomizationAvailable,
isRestoreAndAutoBackupAvailable,
} = this.props;
}));
}, [location.pathname]);
const isAvailableSettings = (key) => {
switch (key) {
case "DNSSettings":
return isBrandingAndCustomizationAvailable;
@ -167,14 +170,13 @@ class SectionHeaderContent extends React.Component {
return true;
}
};
componentDidUpdate() {
const { tReady, setIsLoadedSectionHeader } = this.props;
React.useEffect(() => {
if (tReady) setIsLoadedSectionHeader(true);
const arrayOfParams = this.getArrayOfParams();
const arrayOfParams = getArrayOfParams();
const key = getKeyByLink(arrayOfParams, settingsTree);
const key = getKeyByLink(arrayOfParams, settingsTree, 2);
const currKey = key.length > 3 ? key : key[0];
const header = getTKeyByKey(currKey, settingsTree);
const isCategory = checkPropertyByLink(
@ -189,161 +191,162 @@ class SectionHeaderContent extends React.Component {
);
const isCategoryOrHeader = isCategory || isHeader;
const isNeedPaidIcon = !this.isAvailableSettings(header);
const isNeedPaidIcon = !isAvailableSettings(header);
this.state.isNeedPaidIcon !== isNeedPaidIcon &&
this.setState({ isNeedPaidIcon });
state.isNeedPaidIcon !== isNeedPaidIcon &&
setState((val) => ({ ...val, isNeedPaidIcon }));
header !== this.state.header && this.setState({ header });
header !== state.header && setState((val) => ({ ...val, header }));
isCategoryOrHeader !== this.state.isCategoryOrHeader &&
this.setState({ isCategoryOrHeader });
}
isCategoryOrHeader !== state.isCategoryOrHeader &&
setState((val) => ({ ...val, isCategoryOrHeader }));
}, [
tReady,
setIsLoadedSectionHeader,
getArrayOfParams,
isAvailableSettings,
state.isNeedPaidIcon,
state.header,
state.isCategoryOrHeader,
]);
onBackToParent = () => {
let newArrayOfParams = this.getArrayOfParams();
const onBackToParent = () => {
let newArrayOfParams = getArrayOfParams();
newArrayOfParams.splice(-1, 1);
const newPath = "/portal-settings/" + newArrayOfParams.join("/");
this.props.history.push(
combineUrl(window.DocSpaceConfig?.proxy?.url, newPath)
);
navigate(combineUrl(window.DocSpaceConfig?.proxy?.url, newPath));
};
getArrayOfParams = () => {
const { match, location } = this.props;
const fullSettingsUrl = match.url;
const getArrayOfParams = () => {
const locationPathname = location.pathname;
const fullSettingsUrlLength = fullSettingsUrl.length;
const resultPath = locationPathname.slice(fullSettingsUrlLength + 1);
const resultPath = locationPathname;
const arrayOfParams = resultPath.split("/").filter((param) => {
return param !== "filter";
});
return arrayOfParams;
};
addUsers = (items) => {
const { addUsers } = this.props;
const addUsers = (items) => {
const { addUsers } = props;
if (!addUsers) return;
addUsers(items);
};
onToggleSelector = (isOpen = !this.props.selectorIsOpen) => {
const { toggleSelector } = this.props;
const onToggleSelector = (isOpen = !props.selectorIsOpen) => {
const { toggleSelector } = props;
toggleSelector(isOpen);
};
onClose = () => {
const { deselectUser } = this.props;
const onClose = () => {
const { deselectUser } = props;
deselectUser();
};
onCheck = (checked) => {
const { setSelected } = this.props;
const onCheck = (checked) => {
const { setSelected } = props;
setSelected(checked ? "all" : "close");
};
onSelectAll = () => {
const { setSelected } = this.props;
const onSelectAll = () => {
const { setSelected } = props;
setSelected("all");
};
removeAdmins = () => {
const { removeAdmins } = this.props;
const removeAdmins = () => {
const { removeAdmins } = props;
if (!removeAdmins) return;
removeAdmins();
};
render() {
const {
t,
isLoadedSectionHeader,
addUsers,
isHeaderIndeterminate,
isHeaderChecked,
isHeaderVisible,
selection,
} = this.props;
const { header, isCategoryOrHeader, isNeedPaidIcon } = this.state;
const arrayOfParams = this.getArrayOfParams();
const {
t,
isLoadedSectionHeader,
const menuItems = (
<>
<DropDownItem
key="all"
label={t("Common:SelectAll")}
data-index={1}
onClick={this.onSelectAll}
/>
</>
);
isHeaderIndeterminate,
isHeaderChecked,
isHeaderVisible,
selection,
} = props;
const { header, isCategoryOrHeader, isNeedPaidIcon } = state;
const arrayOfParams = getArrayOfParams();
const headerMenu = [
{
label: t("Common:Delete"),
disabled: !selection || !selection.length > 0,
onClick: this.removeAdmins,
iconUrl: DeleteReactSvgUrl,
},
];
const menuItems = (
<>
<DropDownItem
key="all"
label={t("Common:SelectAll")}
data-index={1}
onClick={onSelectAll}
/>
</>
);
return (
<StyledContainer isHeaderVisible={isHeaderVisible}>
{isHeaderVisible ? (
<div className="group-button-menu-container">
<TableGroupMenu
checkboxOptions={menuItems}
onChange={this.onCheck}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
const headerMenu = [
{
label: t("Common:Delete"),
disabled: !selection || !selection.length > 0,
onClick: removeAdmins,
iconUrl: DeleteReactSvgUrl,
},
];
return (
<StyledContainer isHeaderVisible={isHeaderVisible}>
{isHeaderVisible ? (
<div className="group-button-menu-container">
<TableGroupMenu
checkboxOptions={menuItems}
onChange={onCheck}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
/>
</div>
) : !isLoadedSectionHeader ? (
<LoaderSectionHeader />
) : (
<HeaderContainer>
{!isCategoryOrHeader && arrayOfParams[0] && (
<IconButton
iconName={ArrowPathReactSvgUrl}
size="17"
isFill={true}
onClick={onBackToParent}
className="arrow-button"
/>
</div>
) : !isLoadedSectionHeader ? (
<LoaderSectionHeader />
) : (
<HeaderContainer>
{!isCategoryOrHeader && arrayOfParams[0] && (
)}
<Headline type="content" truncate={true}>
<div className="settings-section_header">
<div className="header"> {t(header)}</div>
{isNeedPaidIcon ? (
<Badge
backgroundColor="#EDC409"
label={t("Common:Paid")}
className="settings-section_badge"
isPaidBadge={true}
/>
) : (
""
)}
</div>
</Headline>
{addUsers && (
<div className="action-wrapper">
<IconButton
iconName={ArrowPathReactSvgUrl}
iconName={ActionsHeaderTouchReactSvgUrl}
size="17"
isFill={true}
onClick={this.onBackToParent}
className="arrow-button"
onClick={onToggleSelector}
className="action-button"
/>
)}
<Headline type="content" truncate={true}>
<div className="settings-section_header">
<div className="header"> {t(header)}</div>
{isNeedPaidIcon ? (
<Badge
backgroundColor="#EDC409"
label={t("Common:Paid")}
className="settings-section_badge"
isPaidBadge={true}
/>
) : (
""
)}
</div>
</Headline>
{addUsers && (
<div className="action-wrapper">
<IconButton
iconName={ActionsHeaderTouchReactSvgUrl}
size="17"
isFill={true}
onClick={this.onToggleSelector}
className="action-button"
/>
</div>
)}
</HeaderContainer>
)}
</StyledContainer>
);
}
}
</div>
)}
</HeaderContainer>
)}
</StyledContainer>
);
};
export default inject(({ auth, setup, common }) => {
const { currentQuotaStore } = auth;
@ -386,8 +389,6 @@ export default inject(({ auth, setup, common }) => {
};
})(
withLoading(
withRouter(
withTranslation(["Settings", "Common"])(observer(SectionHeaderContent))
)
withTranslation(["Settings", "Common"])(observer(SectionHeaderContent))
)
);

View File

@ -8,7 +8,7 @@ import Button from "@docspace/components/button";
import { inject, observer } from "mobx-react";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
import { useNavigate } from "react-router-dom";
import { isMobileOnly } from "react-device-detect";
import { isSmallTablet } from "@docspace/components/utils/device";
import checkScrollSettingsBlock from "../utils";
@ -36,6 +36,7 @@ const DNSSettings = (props) => {
const [hasScroll, setHasScroll] = useState(false);
const isLoadedSetting = isLoaded && tReady;
const [isCustomizationView, setIsCustomizationView] = useState(false);
const navigate = useNavigate();
useEffect(() => {
setDocumentTitle(t("DNSSettings"));
@ -53,9 +54,8 @@ const DNSSettings = (props) => {
}
// TODO: Remove div with height 64 and remove settings-mobile class
const settingsMobile = document.getElementsByClassName(
"settings-mobile"
)[0];
const settingsMobile =
document.getElementsByClassName("settings-mobile")[0];
if (settingsMobile) {
settingsMobile.style.display = "none";
@ -89,7 +89,7 @@ const DNSSettings = (props) => {
if (newUrl === currentUrl) return;
history.push(newUrl);
navigate(newUrl);
} else {
setIsCustomizationView(false);
}
@ -169,12 +169,8 @@ const DNSSettings = (props) => {
export default inject(({ auth, common }) => {
const { theme, helpLink } = auth.settingsStore;
const {
isLoaded,
setIsLoadedDNSSettings,
initSettings,
setIsLoaded,
} = common;
const { isLoaded, setIsLoadedDNSSettings, initSettings, setIsLoaded } =
common;
const { currentQuotaStore } = auth;
const { isBrandingAndCustomizationAvailable } = currentQuotaStore;
return {

View File

@ -13,7 +13,7 @@ import { LANGUAGE, COOKIE_EXPIRATION_YEAR } from "@docspace/common/constants";
import { LanguageTimeSettingsTooltip } from "../sub-components/common-tooltips";
import { combineUrl, setCookie } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
import { useNavigate } from "react-router-dom";
import { isMobileOnly } from "react-device-detect";
import { isSmallTablet } from "@docspace/components/utils/device";
import checkScrollSettingsBlock from "../utils";
@ -45,70 +45,71 @@ let timezoneDefaultFromSessionStorage = "";
const settingNames = ["language", "timezone"];
class LanguageAndTimeZone extends React.Component {
constructor(props) {
super(props);
const LanguageAndTimeZone = (props) => {
const {
i18n,
language,
cultureNames,
rawTimezones,
portalTimeZoneId,
isLoaded,
cultures,
portalLanguage,
tReady,
setIsLoadedLngTZSettings,
t,
setIsLoaded,
timezone,
const { t } = props;
initSettings,
} = props;
const navigate = useNavigate();
const [state, setState] = React.useState({
isLoading: false,
timezone: "",
timezoneDefault: "",
language: "",
languageDefault: "",
hasChanged: false,
showReminder: false,
hasScroll: false,
isCustomizationView: false,
});
const prevProps = React.useRef({ language: "", tReady: "", isLoaded: "" });
const prevState = React.useRef({ language: "", timezone: "" });
React.useEffect(() => {
languageFromSessionStorage = getFromSessionStorage("language");
languageDefaultFromSessionStorage = getFromSessionStorage(
"languageDefault"
);
languageDefaultFromSessionStorage =
getFromSessionStorage("languageDefault");
timezoneFromSessionStorage = getFromSessionStorage("timezone");
timezoneDefaultFromSessionStorage = getFromSessionStorage(
"timezoneDefault"
);
timezoneDefaultFromSessionStorage =
getFromSessionStorage("timezoneDefault");
setDocumentTitle(t("StudioTimeLanguageSettings"));
this.state = {
isLoading: false,
timezone: timezoneFromSessionStorage || "",
timezoneDefault: timezoneDefaultFromSessionStorage || "",
language: languageFromSessionStorage || "",
languageDefault: languageDefaultFromSessionStorage || "",
hasChanged: false,
showReminder: false,
hasScroll: false,
isCustomizationView: false,
};
}
componentDidMount() {
const { languageDefault, timezoneDefault } = this.state;
const {
i18n,
language,
timezone,
rawTimezones,
portalTimeZoneId,
isLoaded,
cultures,
portalLanguage,
tReady,
setIsLoadedLngTZSettings,
initSettings,
setIsLoaded,
} = this.props;
if (!isLoaded) initSettings().then(() => setIsLoaded(true));
const isLoadedSetting =
isLoaded && tReady && this.state.timezone && this.state.language;
isLoaded &&
tReady &&
timezoneFromSessionStorage &&
languageFromSessionStorage;
if (isLoadedSetting) {
setIsLoadedLngTZSettings(isLoadedSetting);
}
this.checkInnerWidth();
window.addEventListener("resize", this.checkInnerWidth);
checkInnerWidth();
window.addEventListener("resize", checkInnerWidth);
if (
rawTimezones.length > 0 &&
isLoaded === true &&
tReady === true &&
this.state.timezone === ""
isLoaded &&
tReady &&
timezoneFromSessionStorage === ""
) {
const timezones = mapTimezonesToArray(rawTimezones);
@ -120,17 +121,18 @@ class LanguageAndTimeZone extends React.Component {
const timezoneDefault =
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
this.setState({
setState((val) => ({
...val,
timezone,
timezoneDefault,
});
}));
}
if (
cultures.length > 0 &&
isLoaded === true &&
tReady === true &&
this.state.language === ""
isLoaded &&
tReady &&
languageFromSessionStorage === ""
) {
const cultureNames = mapCulturesToArray(cultures, i18n);
@ -141,52 +143,55 @@ class LanguageAndTimeZone extends React.Component {
const languageDefault =
findSelectedItemByKey(cultureNames, portalLanguage) || cultureNames[0];
this.setState({
setState((val) => ({
...val,
language,
languageDefault,
});
}));
}
if (!languageDefault) {
this.setState({
languageDefault: language,
});
if (!languageDefaultFromSessionStorage) {
setState((val) => ({
...val,
languageDefault: languageFromSessionStorage,
}));
}
if (timezoneDefault || timezone) {
this.checkChanges();
if (timezoneDefaultFromSessionStorage || timezone) {
checkChanges();
}
if (languageDefault || language) {
this.checkChanges();
if (languageDefaultFromSessionStorage || language) {
checkChanges();
}
}
return () => {
window.removeEventListener("resize", checkInnerWidth);
};
}, []);
componentDidUpdate(prevProps, prevState) {
const { timezoneDefault, languageDefault, hasScroll } = this.state;
React.useState(() => {
prevProps.current = {
language: language,
tReady: tReady,
isLoaded: isLoaded,
};
}, [language, tReady, isLoaded]);
const {
i18n,
language,
cultureNames,
rawTimezones,
portalTimeZoneId,
isLoaded,
cultures,
portalLanguage,
tReady,
setIsLoadedLngTZSettings,
} = this.props;
React.useState(() => {
prevState.current = { language: state.language, timezone: state.timezone };
}, [state.language, state.timezone]);
React.useEffect(() => {
const { timezoneDefault, languageDefault, hasScroll } = state;
if (
isLoaded !== prevProps.isLoaded ||
tReady !== prevProps.tReady ||
this.state.language !== prevState.language ||
this.state.timezone !== prevState.timezone
isLoaded !== prevProps.current.isLoaded ||
tReady !== prevProps.current.tReady ||
state.language !== prevState.current.language ||
state.timezone !== prevState.current.timezone
) {
const isLoadedSetting =
isLoaded && tReady && this.state.timezone && this.state.language;
isLoaded && tReady && state.timezone && state.language;
if (isLoadedSetting) {
setIsLoadedLngTZSettings(isLoadedSetting);
@ -195,9 +200,9 @@ class LanguageAndTimeZone extends React.Component {
if (
rawTimezones.length > 0 &&
isLoaded === true &&
tReady === true &&
this.state.timezone === ""
isLoaded &&
tReady &&
state.timezone === ""
) {
const timezones = mapTimezonesToArray(rawTimezones);
@ -209,18 +214,10 @@ class LanguageAndTimeZone extends React.Component {
const timezoneDefault =
findSelectedItemByKey(timezones, portalTimeZoneId) || timezones[0];
this.setState({
timezone,
timezoneDefault,
});
setState((val) => ({ ...val, timezone, timezoneDefault }));
}
if (
cultures.length > 0 &&
isLoaded === true &&
tReady === true &&
this.state.language === ""
) {
if (cultures.length > 0 && isLoaded && tReady && state.language === "") {
const cultureNames = mapCulturesToArray(cultures, i18n);
const language =
languageFromSessionStorage ||
@ -230,10 +227,7 @@ class LanguageAndTimeZone extends React.Component {
const languageDefault =
findSelectedItemByKey(cultureNames, portalLanguage) || cultureNames[0];
this.setState({
language,
languageDefault,
});
setState((val) => ({ ...val, language, languageDefault }));
}
const checkScroll = checkScrollSettingsBlock();
@ -242,146 +236,157 @@ class LanguageAndTimeZone extends React.Component {
const scrollLngTZSettings = checkScroll();
if (scrollLngTZSettings !== hasScroll) {
this.setState({
hasScroll: scrollLngTZSettings,
});
setState((val) => ({ ...val, hasScroll: scrollLngTZSettings }));
}
// TODO: Remove div with height 64 and remove settings-mobile class
const settingsMobile = document.getElementsByClassName(
"settings-mobile"
)[0];
const settingsMobile =
document.getElementsByClassName("settings-mobile")[0];
if (settingsMobile) {
settingsMobile.style.display = "none";
}
if (language !== prevProps.language) {
if (language !== prevProps.current.language) {
i18n.changeLanguage(language).then(() => {
const newLocaleSelectedLanguage =
findSelectedItemByKey(cultureNames, this.state.language.key) ||
findSelectedItemByKey(cultureNames, state.language.key) ||
cultureNames[0];
this.setState({
setState((val) => ({
...val,
language: languageFromSessionStorage || newLocaleSelectedLanguage,
});
}));
});
}
if (timezoneDefault && languageDefault) {
this.checkChanges();
checkChanges();
}
}
}, [
state.timezoneDefault,
state.languageDefault,
state.hasScroll,
state.timezone,
state.language,
i18n,
language,
cultureNames,
rawTimezones,
portalTimeZoneId,
isLoaded,
cultures,
portalLanguage,
tReady,
setIsLoadedLngTZSettings,
componentWillUnmount() {
window.removeEventListener("resize", this.checkInnerWidth);
}
timezone,
onLanguageSelect = (language) => {
this.setState({ language });
if (this.settingIsEqualInitialValue("language", language)) {
initSettings,
]);
const onLanguageSelect = (language) => {
setState((val) => ({ ...val, language }));
if (settingIsEqualInitialValue("language", language)) {
saveToSessionStorage("language", "");
saveToSessionStorage("languageDefault", "");
} else {
saveToSessionStorage("language", language);
}
this.checkChanges();
checkChanges();
};
onTimezoneSelect = (timezone) => {
this.setState({ timezone });
if (this.settingIsEqualInitialValue("timezone", timezone)) {
const onTimezoneSelect = (timezone) => {
setState((val) => ({ ...val, timezone }));
if (settingIsEqualInitialValue("timezone", timezone)) {
saveToSessionStorage("timezone", "");
saveToSessionStorage("timezoneDefault", "");
} else {
saveToSessionStorage("timezone", timezone);
}
this.checkChanges();
checkChanges();
};
onSaveLngTZSettings = () => {
const { t, setLanguageAndTime, user, language: lng } = this.props;
const { language, timezone } = this.state;
const onSaveLngTZSettings = () => {
const { t, setLanguageAndTime, user, language: lng } = props;
const { language, timezone } = state;
this.setState({ isLoading: true }, function () {
setLanguageAndTime(language.key, timezone.key)
.then(
() =>
!user.cultureName &&
setCookie(LANGUAGE, language.key || "en", {
"max-age": COOKIE_EXPIRATION_YEAR,
})
)
.then(() => toastr.success(t("SuccessfullySaveSettingsMessage")))
.then(
() => !user.cultureName && lng !== language.key && location.reload()
)
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoading: false }));
});
setState((val) => ({ ...val, isLoading: true }));
setLanguageAndTime(language.key, timezone.key)
.then(
() =>
!user.cultureName &&
setCookie(LANGUAGE, language.key || "en", {
"max-age": COOKIE_EXPIRATION_YEAR,
})
)
.then(() => toastr.success(t("SuccessfullySaveSettingsMessage")))
.then(
() => !user.cultureName && lng !== language.key && location.reload()
)
.catch((error) => toastr.error(error))
.finally(() => setState((val) => ({ ...val, isLoading: false })));
this.setState({
setState((val) => ({
...val,
showReminder: false,
timezoneDefault: this.state.timezone,
languageDefault: this.state.language,
});
timezoneDefault: state.timezone,
languageDefault: state.language,
}));
saveToSessionStorage("languageDefault", language);
saveToSessionStorage("timezoneDefault", timezone);
};
onCancelClick = () => {
const onCancelClick = () => {
settingNames.forEach((settingName) => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (
valueFromSessionStorage !== "none" &&
valueFromSessionStorage !== null &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
!settingIsEqualInitialValue(settingName, valueFromSessionStorage)
) {
const defaultValue = this.state[settingName + "Default"];
const defaultValue = state[settingName + "Default"];
this.setState({ [settingName]: defaultValue || null });
setState((val) => ({ ...val, [settingName]: defaultValue || null }));
saveToSessionStorage(settingName, "");
}
});
this.setState({
showReminder: false,
});
setState((val) => ({ ...val, showReminder: false }));
this.checkChanges();
checkChanges();
};
settingIsEqualInitialValue = (settingName, value) => {
const defaultValue = JSON.stringify(this.state[settingName + "Default"]);
const settingIsEqualInitialValue = (settingName, value) => {
const defaultValue = JSON.stringify(state[settingName + "Default"]);
const currentValue = JSON.stringify(value);
return defaultValue === currentValue;
};
checkChanges = () => {
const checkChanges = () => {
let hasChanged = false;
settingNames.forEach((settingName) => {
const valueFromSessionStorage = getFromSessionStorage(settingName);
if (
valueFromSessionStorage &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
!settingIsEqualInitialValue(settingName, valueFromSessionStorage)
)
hasChanged = true;
});
if (hasChanged !== this.state.hasChanged) {
this.setState({
if (hasChanged !== state.hasChanged) {
setState((val) => ({
...val,
hasChanged: hasChanged,
showReminder: hasChanged,
});
}));
}
};
checkInnerWidth = () => {
const checkInnerWidth = () => {
if (!isSmallTablet()) {
this.setState({
isCustomizationView: true,
});
setState((val) => ({ ...val, isCustomizationView: true }));
const currentUrl = window.location.href.replace(
window.location.origin,
@ -396,141 +401,133 @@ class LanguageAndTimeZone extends React.Component {
if (newUrl === currentUrl) return;
history.push(newUrl);
navigate(newUrl);
} else {
this.setState({
isCustomizationView: false,
});
setState((val) => ({ ...val, isCustomizationView: false }));
}
};
onClickLink = (e) => {
const onClickLink = (e) => {
e.preventDefault();
history.push(e.target.pathname);
navigate(e.target.pathname);
};
render() {
const {
t,
theme,
isMobileView,
rawTimezones,
cultures,
i18n,
isLoadedPage,
helpLink,
organizationName,
currentColorScheme,
} = this.props;
const {
theme,
isMobileView,
const {
language,
isLoading,
timezone,
showReminder,
hasScroll,
isCustomizationView,
} = this.state;
isLoadedPage,
helpLink,
organizationName,
currentColorScheme,
} = props;
const timezones = mapTimezonesToArray(rawTimezones);
const cultureNames = mapCulturesToArray(cultures, i18n);
const {
isLoading,
const tooltipLanguageTimeSettings = (
<LanguageTimeSettingsTooltip
theme={theme}
t={t}
helpLink={helpLink}
organizationName={organizationName}
currentColorScheme={currentColorScheme}
/>
);
showReminder,
hasScroll,
isCustomizationView,
} = state;
const settingsBlock = !(language && timezone) ? null : (
<div className="settings-block">
<FieldContainer
id="fieldContainerLanguage"
labelText={`${t("Common:Language")}`}
isVertical={true}
>
<ComboBox
tabIndex={1}
id="comboBoxLanguage"
options={cultureNames}
selectedOption={language}
onSelect={this.onLanguageSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width combo-box-settings"
showDisabledItems={true}
/>
</FieldContainer>
<FieldContainer
id="fieldContainerTimezone"
labelText={`${t("TimeZone")}`}
isVertical={true}
>
<ComboBox
tabIndex={2}
id="comboBoxTimezone"
options={timezones}
selectedOption={timezone}
onSelect={this.onTimezoneSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width combo-box-settings"
showDisabledItems={true}
/>
</FieldContainer>
</div>
);
const timezones = mapTimezonesToArray(rawTimezones);
const cultureNamesNew = mapCulturesToArray(cultures, i18n);
return !isLoadedPage ? (
<LoaderCustomization lngTZSettings={true} />
) : (
<StyledSettingsComponent
hasScroll={hasScroll}
className="category-item-wrapper"
const tooltipLanguageTimeSettings = (
<LanguageTimeSettingsTooltip
theme={theme}
t={t}
helpLink={helpLink}
organizationName={organizationName}
currentColorScheme={currentColorScheme}
/>
);
const settingsBlock = !(state.language && state.timezone) ? null : (
<div className="settings-block">
<FieldContainer
id="fieldContainerLanguage"
labelText={`${t("Common:Language")}`}
isVertical={true}
>
{isCustomizationView && !isMobileView && (
<div className="category-item-heading">
<div className="category-item-title">
{t("StudioTimeLanguageSettings")}
</div>
<HelpButton
offsetRight={0}
iconName={CombinedShapeSvgUrl}
size={12}
tooltipContent={tooltipLanguageTimeSettings}
/>
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
<StyledScrollbar stype="mediumBlack">{settingsBlock}</StyledScrollbar>
) : (
<> {settingsBlock}</>
)}
<SaveCancelButtons
tabIndex={3}
className="save-cancel-buttons"
onSaveClick={this.onSaveLngTZSettings}
onCancelClick={this.onCancelClick}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:CancelButton")}
displaySettings={true}
hasScroll={hasScroll}
<ComboBox
tabIndex={1}
id="comboBoxLanguage"
options={cultureNamesNew}
selectedOption={state.language}
onSelect={onLanguageSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width combo-box-settings"
showDisabledItems={true}
/>
</StyledSettingsComponent>
);
}
}
</FieldContainer>
<FieldContainer
id="fieldContainerTimezone"
labelText={`${t("TimeZone")}`}
isVertical={true}
>
<ComboBox
tabIndex={2}
id="comboBoxTimezone"
options={timezones}
selectedOption={state.timezone}
onSelect={onTimezoneSelect}
isDisabled={isLoading}
noBorder={false}
scaled={true}
scaledOptions={true}
dropDownMaxHeight={300}
className="dropdown-item-width combo-box-settings"
showDisabledItems={true}
/>
</FieldContainer>
</div>
);
return !isLoadedPage ? (
<LoaderCustomization lngTZSettings={true} />
) : (
<StyledSettingsComponent
hasScroll={hasScroll}
className="category-item-wrapper"
>
{isCustomizationView && !isMobileView && (
<div className="category-item-heading">
<div className="category-item-title">
{t("StudioTimeLanguageSettings")}
</div>
<HelpButton
offsetRight={0}
iconName={CombinedShapeSvgUrl}
size={12}
tooltipContent={tooltipLanguageTimeSettings}
/>
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
<StyledScrollbar stype="mediumBlack">{settingsBlock}</StyledScrollbar>
) : (
<> {settingsBlock}</>
)}
<SaveCancelButtons
tabIndex={3}
className="save-cancel-buttons"
onSaveClick={onSaveLngTZSettings}
onCancelClick={onCancelClick}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:CancelButton")}
displaySettings={true}
hasScroll={hasScroll}
/>
</StyledSettingsComponent>
);
};
export default inject(({ auth, setup, common }) => {
const {
@ -549,12 +546,8 @@ export default inject(({ auth, setup, common }) => {
const { user } = auth.userStore;
const { setLanguageAndTime } = setup;
const {
isLoaded,
setIsLoadedLngTZSettings,
initSettings,
setIsLoaded,
} = common;
const { isLoaded, setIsLoadedLngTZSettings, initSettings, setIsLoaded } =
common;
return {
theme: auth.settingsStore.theme,
user,

View File

@ -9,7 +9,7 @@ import SaveCancelButtons from "@docspace/components/save-cancel-buttons";
import { inject, observer } from "mobx-react";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
import { useNavigate } from "react-router-dom";
import { isMobileOnly } from "react-device-detect";
import { isSmallTablet } from "@docspace/components/utils/device";
import checkScrollSettingsBlock from "../utils";
@ -36,11 +36,12 @@ const PortalRenaming = (props) => {
domain,
} = props;
const navigate = useNavigate();
const portalNameFromSessionStorage = getFromSessionStorage("portalName");
const portalNameDefaultFromSessionStorage = getFromSessionStorage(
"portalNameDefault"
);
const portalNameDefaultFromSessionStorage =
getFromSessionStorage("portalNameDefault");
const portalNameInitially =
portalNameFromSessionStorage === null ||
@ -98,9 +99,8 @@ const PortalRenaming = (props) => {
}
// TODO: Remove div with height 64 and remove settings-mobile class
const settingsMobile = document.getElementsByClassName(
"settings-mobile"
)[0];
const settingsMobile =
document.getElementsByClassName("settings-mobile")[0];
if (settingsMobile) {
settingsMobile.style.display = "none";
@ -129,7 +129,7 @@ const PortalRenaming = (props) => {
setPortalName(portalName);
setPortalNameDefault(portalName);
window.location.href = res;
navigate(res);
})
.catch((error) => {
let errorMessage = "";
@ -260,7 +260,7 @@ const PortalRenaming = (props) => {
if (newUrl === currentUrl) return;
history.push(newUrl);
navigate(newUrl);
} else {
setIsCustomizationView(false);
}
@ -340,12 +340,8 @@ const PortalRenaming = (props) => {
export default inject(({ auth, setup, common }) => {
const { theme, tenantAlias, baseDomain } = auth.settingsStore;
const { setPortalRename, getAllSettings } = setup;
const {
isLoaded,
setIsLoadedPortalRenaming,
initSettings,
setIsLoaded,
} = common;
const { isLoaded, setIsLoadedPortalRenaming, initSettings, setIsLoaded } =
common;
return {
theme,
setPortalRename,

View File

@ -12,7 +12,7 @@ import { inject, observer } from "mobx-react";
import { CustomTitlesTooltip } from "../sub-components/common-tooltips";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
import { useNavigate } from "react-router-dom";
import { isMobileOnly } from "react-device-detect";
import { isSmallTablet } from "@docspace/components/utils/device";
import checkScrollSettingsBlock from "../utils";
@ -24,12 +24,50 @@ let greetingTitleFromSessionStorage = "";
let greetingTitleDefaultFromSessionStorage = "";
const settingNames = ["greetingTitle"];
class WelcomePageSettings extends React.Component {
constructor(props) {
super(props);
const WelcomePageSettings = (props) => {
const {
t,
greetingSettings,
isLoaded,
setIsLoadedWelcomePageSettings,
tReady,
initSettings,
setIsLoaded,
setGreetingTitle,
restoreGreetingTitle,
isMobileView,
isLoadedPage,
greetingSettingsIsDefault,
const { t, greetingSettings /*, organizationName*/ } = props;
getSettings,
getGreetingSettingsIsDefault,
} = props;
const navigate = useNavigate();
const [state, setState] = React.useState({
isLoading: false,
greetingTitle: "",
greetingTitleDefault: "",
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false,
hasScroll: false,
isCustomizationView: false,
});
const prevState = React.useRef({
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
});
const prevProps = React.useRef({
isLoaded: "",
tReady: "",
greetingSettings: "",
});
React.useEffect(() => {
greetingTitleFromSessionStorage = getFromSessionStorage("greetingTitle");
greetingTitleDefaultFromSessionStorage = getFromSessionStorage(
@ -50,61 +88,35 @@ class WelcomePageSettings extends React.Component {
? greetingSettings
: greetingTitleDefaultFromSessionStorage;
this.state = {
isLoading: false,
greetingTitle,
greetingTitleDefault,
isLoadingGreetingSave: false,
isLoadingGreetingRestore: false,
hasChanged: false,
showReminder: false,
hasScroll: false,
isCustomizationView: false,
};
}
componentDidMount() {
const {
isLoaded,
setIsLoadedWelcomePageSettings,
tReady,
initSettings,
setIsLoaded,
} = this.props;
const { greetingTitleDefault, greetingTitle } = this.state;
if (!isLoaded) initSettings().then(() => setIsLoaded(true));
this.checkInnerWidth();
window.addEventListener("resize", this.checkInnerWidth);
checkInnerWidth();
window.addEventListener("resize", checkInnerWidth);
const isLoadedSetting = isLoaded && tReady;
if (isLoadedSetting) setIsLoadedWelcomePageSettings(isLoadedSetting);
if (greetingTitleDefault || greetingTitle) {
this.checkChanges();
checkChanges();
}
}
componentDidUpdate(prevProps, prevState) {
const {
isLoaded,
setIsLoadedWelcomePageSettings,
tReady,
greetingSettings,
getSettings,
getGreetingSettingsIsDefault,
} = this.props;
const {
hasScroll,
setState((val) => ({
...val,
greetingTitle,
isLoadingGreetingSave,
isLoadingGreetingRestore,
} = this.state;
greetingTitleDefault,
}));
if (isLoaded !== prevProps.isLoaded || tReady !== prevProps.tReady) {
return () => {
window.removeEventListener("resize", checkInnerWidth);
};
}, []);
React.useEffect(() => {
if (
isLoaded !== prevProps.current.isLoaded ||
tReady !== prevProps.current.tReady
) {
const isLoadedSetting = isLoaded && tReady;
if (isLoadedSetting) {
@ -117,110 +129,123 @@ class WelcomePageSettings extends React.Component {
window.addEventListener("resize", checkScroll);
const scrollLngTZSettings = checkScroll();
if (scrollLngTZSettings !== hasScroll) {
this.setState({
hasScroll: scrollLngTZSettings,
});
if (scrollLngTZSettings !== state.hasScroll) {
setState((val) => ({ ...val, hasScroll: scrollLngTZSettings }));
}
// TODO: Remove div with height 64 and remove settings-mobile class
const settingsMobile = document.getElementsByClassName(
"settings-mobile"
)[0];
const settingsMobile =
document.getElementsByClassName("settings-mobile")[0];
if (settingsMobile) {
settingsMobile.style.display = "none";
}
if (greetingSettings !== prevProps.greetingSettings) {
this.setState({
greetingTitle: greetingSettings,
});
setState((val) => ({ ...val, greetingTitle: greetingSettings }));
}
if (this.state.greetingTitleDefault || greetingTitle) {
this.checkChanges();
if (state.greetingTitleDefault || state.greetingTitle) {
checkChanges();
}
if (
(isLoadingGreetingSave !== prevState.isLoadingGreetingSave &&
isLoadingGreetingSave === false) ||
(isLoadingGreetingRestore !== prevState.isLoadingGreetingRestore &&
isLoadingGreetingRestore === false)
(state.isLoadingGreetingSave !== prevState.isLoadingGreetingSave &&
state.isLoadingGreetingSave === false) ||
(state.isLoadingGreetingRestore !== prevState.isLoadingGreetingRestore &&
state.isLoadingGreetingRestore === false)
) {
getSettings();
getGreetingSettingsIsDefault();
}
}
}, [
isLoaded,
setIsLoadedWelcomePageSettings,
tReady,
greetingSettings,
getSettings,
getGreetingSettingsIsDefault,
state.hasScroll,
state.greetingTitle,
state.isLoadingGreetingSave,
state.isLoadingGreetingRestore,
]);
componentWillUnmount() {
window.removeEventListener("resize", this.checkInnerWidth);
}
React.useEffect(() => {
prevProps.current = { isLoaded, tReady, greetingSettings };
}, [isLoaded, tReady, greetingSettings]);
onChangeGreetingTitle = (e) => {
this.setState({ greetingTitle: e.target.value });
React.useEffect(() => {
prevState.current = {
isLoadingGreetingSave: state.isLoadingGreetingSave,
isLoadingGreetingRestore: state.isLoadingGreetingRestore,
};
}, [state.isLoadingGreetingSave, state.isLoadingGreetingRestore]);
if (this.settingIsEqualInitialValue("greetingTitle", e.target.value)) {
const onChangeGreetingTitle = (e) => {
setState((val) => ({ ...val, greetingTitle: e.target.value }));
if (settingIsEqualInitialValue("greetingTitle", e.target.value)) {
saveToSessionStorage("greetingTitle", "none");
saveToSessionStorage("greetingTitleDefault", "none");
} else {
saveToSessionStorage("greetingTitle", e.target.value);
this.setState({
setState((val) => ({
...val,
showReminder: true,
});
}));
}
this.checkChanges();
checkChanges();
};
onSaveGreetingSettings = () => {
const { setGreetingTitle, t } = this.props;
const { greetingTitle } = this.state;
this.setState({ isLoadingGreetingSave: true }, function () {
setGreetingTitle(greetingTitle)
.then(() => {
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
})
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingSave: false }));
});
const onSaveGreetingSettings = () => {
const { greetingTitle } = state;
setState((val) => ({ ...val, isLoadingGreetingSave: true }));
setGreetingTitle(greetingTitle)
.then(() => {
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
})
.catch((error) => toastr.error(error))
.finally(() =>
setState((val) => ({ ...val, isLoadingGreetingSave: false }))
);
this.setState({
showReminder: false,
});
setState((val) => ({ ...val, showReminder: false }));
saveToSessionStorage("greetingTitle", greetingTitle);
saveToSessionStorage("greetingTitleDefault", greetingTitle);
};
onRestoreGreetingSettings = () => {
const { restoreGreetingTitle, t, greetingSettings } = this.props;
this.setState({ isLoadingGreetingRestore: true }, function () {
restoreGreetingTitle()
.then(() => {
this.setState({
greetingTitle: greetingSettings,
greetingTitleDefault: greetingSettings,
showReminder: false,
});
const onRestoreGreetingSettings = () => {
setState((val) => ({ ...val, isLoadingGreetingRestore: true }));
restoreGreetingTitle()
.then(() => {
setState((val) => ({
...val,
greetingTitle: greetingSettings,
greetingTitleDefault: greetingSettings,
showReminder: false,
}));
saveToSessionStorage("greetingTitle", "none");
saveToSessionStorage("greetingTitleDefault", "none");
saveToSessionStorage("greetingTitle", "none");
saveToSessionStorage("greetingTitleDefault", "none");
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
})
.catch((error) => toastr.error(error))
.finally(() => this.setState({ isLoadingGreetingRestore: false }));
});
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
})
.catch((error) => toastr.error(error))
.finally(() =>
setState((val) => ({ ...val, isLoadingGreetingRestore: false }))
);
};
settingIsEqualInitialValue = (stateName, value) => {
const defaultValue = JSON.stringify(this.state[stateName + "Default"]);
const settingIsEqualInitialValue = (stateName, value) => {
const defaultValue = JSON.stringify(state[stateName + "Default"]);
const currentValue = JSON.stringify(value);
return defaultValue === currentValue;
};
checkChanges = () => {
const checkChanges = () => {
let hasChanged = false;
settingNames.forEach((settingName) => {
@ -228,24 +253,23 @@ class WelcomePageSettings extends React.Component {
if (
valueFromSessionStorage !== "none" &&
valueFromSessionStorage !== null &&
!this.settingIsEqualInitialValue(settingName, valueFromSessionStorage)
!settingIsEqualInitialValue(settingName, valueFromSessionStorage)
)
hasChanged = true;
});
if (hasChanged !== this.state.hasChanged) {
this.setState({
if (hasChanged !== state.hasChanged) {
setState((val) => ({
...val,
hasChanged: hasChanged,
showReminder: hasChanged,
});
}));
}
};
checkInnerWidth = () => {
const checkInnerWidth = () => {
if (!isSmallTablet()) {
this.setState({
isCustomizationView: true,
});
setState((val) => ({ ...val, isCustomizationView: true }));
const currentUrl = window.location.href.replace(
window.location.origin,
@ -260,109 +284,86 @@ class WelcomePageSettings extends React.Component {
if (newUrl === currentUrl) return;
history.push(newUrl);
navigate(newUrl);
} else {
this.setState({
isCustomizationView: false,
});
setState((val) => ({ ...val, isCustomizationView: false }));
}
};
onClickLink = (e) => {
const onClickLink = (e) => {
e.preventDefault();
history.push(e.target.pathname);
navigate(e.target.pathname);
};
render() {
const {
t,
isMobileView,
isLoadedPage,
greetingSettingsIsDefault,
} = this.props;
const {
greetingTitle,
isLoadingGreetingSave,
isLoadingGreetingRestore,
showReminder,
hasScroll,
isCustomizationView,
} = this.state;
const tooltipCustomTitlesTooltip = <CustomTitlesTooltip t={t} />;
const tooltipCustomTitlesTooltip = <CustomTitlesTooltip t={t} />;
const settingsBlock = (
<div className="settings-block">
<FieldContainer
id="fieldContainerWelcomePage"
className="field-container-width"
labelText={`${t("Common:Title")}`}
isVertical={true}
>
<TextInput
tabIndex={5}
id="textInputContainerWelcomePage"
scale={true}
value={greetingTitle}
onChange={this.onChangeGreetingTitle}
isDisabled={isLoadingGreetingSave || isLoadingGreetingRestore}
placeholder={t("EnterTitle")}
/>
</FieldContainer>
</div>
);
return !isLoadedPage ? (
<LoaderCustomization welcomePage={true} />
) : (
<StyledSettingsComponent
hasScroll={hasScroll}
className="category-item-wrapper"
const settingsBlock = (
<div className="settings-block">
<FieldContainer
id="fieldContainerWelcomePage"
className="field-container-width"
labelText={`${t("Common:Title")}`}
isVertical={true}
>
{isCustomizationView && !isMobileView && (
<div className="category-item-heading">
<div className="category-item-title">
{t("CustomTitlesWelcome")}
</div>
<HelpButton
offsetRight={0}
iconName={CombinedShapeSvgUrl}
size={12}
tooltipContent={tooltipCustomTitlesTooltip}
/>
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
<StyledScrollbar stype="mediumBlack">{settingsBlock}</StyledScrollbar>
) : (
<> {settingsBlock}</>
)}
<SaveCancelButtons
tabIndex={6}
id="buttonsWelcomePage"
className="save-cancel-buttons"
onSaveClick={this.onSaveGreetingSettings}
onCancelClick={this.onRestoreGreetingSettings}
showReminder={showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:Restore")}
displaySettings={true}
hasScroll={hasScroll}
disableRestoreToDefault={greetingSettingsIsDefault}
<TextInput
tabIndex={5}
id="textInputContainerWelcomePage"
scale={true}
value={state.greetingTitle}
onChange={onChangeGreetingTitle}
isDisabled={
state.isLoadingGreetingSave || state.isLoadingGreetingRestore
}
placeholder={t("EnterTitle")}
/>
</StyledSettingsComponent>
);
}
}
</FieldContainer>
</div>
);
return !isLoadedPage ? (
<LoaderCustomization welcomePage={true} />
) : (
<StyledSettingsComponent
hasScroll={state.hasScroll}
className="category-item-wrapper"
>
{state.isCustomizationView && !isMobileView && (
<div className="category-item-heading">
<div className="category-item-title">{t("CustomTitlesWelcome")}</div>
<HelpButton
offsetRight={0}
iconName={CombinedShapeSvgUrl}
size={12}
tooltipContent={tooltipCustomTitlesTooltip}
/>
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
<StyledScrollbar stype="mediumBlack">{settingsBlock}</StyledScrollbar>
) : (
<> {settingsBlock}</>
)}
<SaveCancelButtons
tabIndex={6}
id="buttonsWelcomePage"
className="save-cancel-buttons"
onSaveClick={onSaveGreetingSettings}
onCancelClick={onRestoreGreetingSettings}
showReminder={state.showReminder}
reminderTest={t("YouHaveUnsavedChanges")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:Restore")}
displaySettings={true}
hasScroll={state.hasScroll}
disableRestoreToDefault={greetingSettingsIsDefault}
/>
</StyledSettingsComponent>
);
};
export default inject(({ auth, setup, common }) => {
const {
greetingSettings,
organizationName,
theme,
getSettings,
} = auth.settingsStore;
const { greetingSettings, organizationName, theme, getSettings } =
auth.settingsStore;
const { setGreetingTitle, restoreGreetingTitle } = setup;
const {
isLoaded,

View File

@ -1,7 +1,6 @@
import CheckWhiteSvgUrl from "PUBLIC_DIR/images/check.white.svg?url";
import React, { useState, useEffect, useCallback, useMemo } from "react";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import toastr from "@docspace/components/toast/toastr";
import { inject, observer } from "mobx-react";
import Button from "@docspace/components/button";
@ -50,19 +49,16 @@ const Appearance = (props) => {
const [showColorSchemeDialog, setShowColorSchemeDialog] = useState(false);
const [headerColorSchemeDialog, setHeaderColorSchemeDialog] = useState(
headerEditTheme
);
const [headerColorSchemeDialog, setHeaderColorSchemeDialog] =
useState(headerEditTheme);
const [currentColorAccent, setCurrentColorAccent] = useState(null);
const [currentColorButtons, setCurrentColorButtons] = useState(null);
const [openHexColorPickerAccent, setOpenHexColorPickerAccent] = useState(
false
);
const [openHexColorPickerButtons, setOpenHexColorPickerButtons] = useState(
false
);
const [openHexColorPickerAccent, setOpenHexColorPickerAccent] =
useState(false);
const [openHexColorPickerButtons, setOpenHexColorPickerButtons] =
useState(false);
const [appliedColorAccent, setAppliedColorAccent] = useState(
defaultAppliedColorAccent
@ -71,12 +67,10 @@ const Appearance = (props) => {
defaultAppliedColorButtons
);
const [changeCurrentColorAccent, setChangeCurrentColorAccent] = useState(
false
);
const [changeCurrentColorButtons, setChangeCurrentColorButtons] = useState(
false
);
const [changeCurrentColorAccent, setChangeCurrentColorAccent] =
useState(false);
const [changeCurrentColorButtons, setChangeCurrentColorButtons] =
useState(false);
const [viewMobile, setViewMobile] = useState(false);
@ -172,7 +166,7 @@ const Appearance = (props) => {
useEffect(() => {
if (!currentColorScheme) return;
setAppliedColorButtons(defaultAppliedColorButtons);
setAppliedColorAccent(defaultAppliedColorAccent);
}, [
@ -787,8 +781,4 @@ export default inject(({ auth }) => {
deleteAppearanceTheme,
theme,
};
})(
withTranslation(["Profile", "Common", "Settings"])(
withRouter(observer(Appearance))
)
);
})(withTranslation(["Profile", "Common", "Settings"])(observer(Appearance)));

View File

@ -7,11 +7,11 @@ import Link from "@docspace/components/link";
import { combineUrl } from "@docspace/common/utils";
import { inject, observer } from "mobx-react";
import withCultureNames from "@docspace/common/hoc/withCultureNames";
import history from "@docspace/common/history";
import { Base } from "@docspace/components/themes";
import LoaderCustomizationNavbar from "./sub-components/loaderCustomizationNavbar";
import { StyledArrowRightIcon } from "./Customization/StyledSettings";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import Badge from "@docspace/components/badge";
const StyledComponent = styled.div`
@ -73,13 +73,15 @@ const CustomizationNavbar = ({
currentColorScheme,
}) => {
const isLoadedSetting = isLoaded && tReady;
const navigate = useNavigate();
useEffect(() => {
if (isLoadedSetting) setIsLoadedCustomizationNavbar(isLoadedSetting);
}, [isLoadedSetting]);
const onClickLink = (e) => {
e.preventDefault();
history.push(e.target.pathname);
navigate(e.target.pathname);
};
return !isLoadedPage ? (
@ -200,11 +202,8 @@ const CustomizationNavbar = ({
};
export default inject(({ auth, common }) => {
const {
helpUrlCommonSettings,
theme,
currentColorScheme,
} = auth.settingsStore;
const { helpUrlCommonSettings, theme, currentColorScheme } =
auth.settingsStore;
const { isLoaded, setIsLoadedCustomizationNavbar } = common;
return {
theme,
@ -214,9 +213,7 @@ export default inject(({ auth, common }) => {
currentColorScheme,
};
})(
withRouter(
withCultureNames(
observer(withTranslation(["Settings", "Common"])(CustomizationNavbar))
)
withCultureNames(
observer(withTranslation(["Settings", "Common"])(CustomizationNavbar))
)
);

View File

@ -11,7 +11,6 @@ import CustomizationNavbar from "./customization-navbar";
import { Base } from "@docspace/components/themes";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import LoaderDescriptionCustomization from "./sub-components/loaderDescriptionCustomization";
import { withRouter } from "react-router";
import withLoading from "SRC_DIR/HOCs/withLoading";
import StyledSettingsSeparator from "SRC_DIR/pages/PortalSettings/StyledSettingsSeparator";
@ -115,7 +114,5 @@ export default inject(({ common }) => {
setIsLoadedCustomization,
};
})(
withLoading(
withRouter(withTranslation(["Settings", "Common"])(observer(Customization)))
)
withLoading(withTranslation(["Settings", "Common"])(observer(Customization)))
);

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import Submenu from "@docspace/components/submenu";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { withTranslation } from "react-i18next";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
@ -15,7 +15,7 @@ import { resetSessionStorage } from "../../utils";
const SubmenuCommon = (props) => {
const {
t,
history,
tReady,
setIsLoadedSubmenu,
loadBaseInfo,
@ -24,6 +24,8 @@ const SubmenuCommon = (props) => {
} = props;
const [currentTab, setCurrentTab] = useState(0);
const navigate = useNavigate();
useEffect(() => {
return () => {
resetSessionStorage();
@ -69,7 +71,7 @@ const SubmenuCommon = (props) => {
];
const onSelect = (e) => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -106,6 +108,4 @@ export default inject(({ common }) => {
isLoadedSubmenu,
getWhiteLabelLogoUrls,
};
})(
withLoading(withRouter(withTranslation("Settings")(observer(SubmenuCommon))))
);
})(withLoading(withTranslation("Settings")(observer(SubmenuCommon))));

View File

@ -1,6 +1,7 @@
import HelpReactSvgUrl from "PUBLIC_DIR/images/help.react.svg?url";
import React, { useEffect } from "react";
import { withTranslation, Trans } from "react-i18next";
import { useNavigate } from "react-router-dom";
import Submenu from "@docspace/components/submenu";
import Link from "@docspace/components/link";
import HelpButton from "@docspace/components/help-button";
@ -15,10 +16,12 @@ const Backup = ({
helpUrlCreatingBackup,
buttonSize,
t,
history,
isNotPaidPeriod,
currentColorScheme,
}) => {
const navigate = useNavigate();
const renderTooltip = (helpInfo) => {
return (
<>
@ -67,7 +70,7 @@ const Backup = ({
];
const onSelect = (e) => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -87,11 +90,8 @@ export default inject(({ auth }) => {
const { settingsStore, currentTariffStatusStore } = auth;
const { isNotPaidPeriod } = currentTariffStatusStore;
const {
helpUrlCreatingBackup,
isTabletView,
currentColorScheme,
} = settingsStore;
const { helpUrlCreatingBackup, isTabletView, currentColorScheme } =
settingsStore;
const buttonSize = isTabletView ? "normal" : "small";

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect, useCallback } from "react";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { getSettingsThirdParty } from "@docspace/common/api/files";
import {
getBackupStorage,
@ -48,7 +47,6 @@ const RestoreBackup = (props) => {
isEnableRestore,
setRestoreResource,
buttonSize,
history,
} = props;
const [radioButtonState, setRadioButtonState] = useState(LOCAL_FILE);
@ -236,7 +234,6 @@ const RestoreBackup = (props) => {
isVisibleDialog={isVisibleBackupListDialog}
onModalClose={onModalClose}
isNotify={checkboxState.notification}
history={history}
/>
)}
<Checkbox
@ -265,7 +262,6 @@ const RestoreBackup = (props) => {
radioButtonState={radioButtonState}
isCheckedThirdPartyStorage={radioButtonState === STORAGE_SPACE}
isCheckedLocalFile={radioButtonState === LOCAL_FILE}
history={history}
t={t}
buttonSize={buttonSize}
/>

View File

@ -1,7 +1,7 @@
import React, { useState } from "react";
import { inject, observer } from "mobx-react";
import config from "PACKAGE_FILE";
import { useNavigate } from "react-router-dom";
import Button from "@docspace/components/button";
import FloatingButton from "@docspace/common/components/FloatingButton";
import { TenantStatus } from "@docspace/common/constants";
@ -20,7 +20,7 @@ const ButtonContainer = (props) => {
restoreResource,
isCheckedThirdPartyStorage,
isCheckedLocalFile,
history,
isEnableRestore,
t,
buttonSize,
@ -30,6 +30,8 @@ const ButtonContainer = (props) => {
getStorageParams,
} = props;
const navigate = useNavigate();
const [isUploadingLocalFile, setIsUploadingLocalFile] = useState(false);
const [isLoading, setIsLoading] = useState(false);
@ -97,7 +99,7 @@ const ButtonContainer = (props) => {
command: "restore-backup",
});
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,

View File

@ -1,6 +1,7 @@
import HelpReactSvgUrl from "PUBLIC_DIR/images/help.react.svg?url";
import React from "react";
import { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import { withTranslation } from "react-i18next";
import ModalDialog from "@docspace/components/modal-dialog";
@ -56,246 +57,235 @@ const StyledModalDialog = styled(ModalDialog)`
}
`;
class BackupListModalDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
filesList: [],
selectedFileIndex: null,
selectedFileId: null,
isChecked: false,
};
}
componentDidMount() {
const BackupListModalDialog = (props) => {
const [state, setState] = React.useState({
isLoading: true,
filesList: [],
selectedFileIndex: null,
selectedFileId: null,
isChecked: false,
});
const navigate = useNavigate();
React.useEffect(() => {
getBackupHistory()
.then((filesList) =>
this.setState({
filesList,
isLoading: false,
})
setState((val) => ({ ...val, filesList, isLoading: false }))
)
.catch(() => this.setState({ isLoading: false }));
}
.catch(() => setState((val) => ({ ...val, isLoading: false })));
}, []);
onSelectFile = (e) => {
const onSelectFile = (e) => {
const fileInfo = e.target.name;
const fileArray = fileInfo.split("_");
const id = fileArray.pop();
const index = fileArray.shift();
this.setState({
setState((val) => ({
...val,
selectedFileIndex: +index,
selectedFileId: id,
});
}));
};
onCleanBackupList = () => {
this.setState({ isLoading: true }, function () {
deleteBackupHistory()
.then(() => getBackupHistory())
.then((filesList) => this.setState({ filesList, isLoading: false }))
.catch((error) => {
toastr.error(error);
this.setState({ isLoading: false });
});
});
const onCleanBackupList = () => {
setState((val) => ({ ...val, isLoading: true }));
deleteBackupHistory()
.then(() => getBackupHistory())
.then((filesList) =>
setState((val) => ({ ...val, filesList, isLoading: false }))
)
.catch((error) => {
toastr.error(error);
setState((val) => ({ ...val, isLoading: false }));
});
};
onDeleteBackup = (backupId) => {
const onDeleteBackup = (backupId) => {
if (!backupId) return;
this.setState({ isLoading: true }, function () {
deleteBackup(backupId)
.then(() => getBackupHistory())
.then((filesList) =>
this.setState({
filesList,
isLoading: false,
selectedFileIndex: null,
selectedFileId: null,
})
)
.catch((error) => {
toastr.error(error);
this.setState({ isLoading: false });
});
});
setState((val) => ({ ...val, isLoading: true }));
deleteBackup(backupId)
.then(() => getBackupHistory())
.then((filesList) =>
setState((val) => ({
...val,
filesList,
isLoading: false,
selectedFileIndex: null,
selectedFileId: null,
}))
)
.catch((error) => {
toastr.error(error);
setState((val) => ({ ...val, isLoading: false }));
});
};
onRestorePortal = () => {
const { selectedFileId } = this.state;
const { isNotify, history, socketHelper, t, setTenantStatus } = this.props;
const onRestorePortal = () => {
const { selectedFileId } = state;
const { isNotify, socketHelper, t, setTenantStatus } = props;
if (!selectedFileId) {
toastr.error(t("RecoveryFileNotSelected"));
return;
}
this.setState({ isLoading: true }, function () {
const backupId = selectedFileId;
const storageType = "0";
const storageParams = [
{
key: "fileId",
value: backupId,
},
];
setState((val) => ({ ...val, isLoading: true }));
const backupId = selectedFileId;
const storageType = "0";
const storageParams = [
{
key: "fileId",
value: backupId,
},
];
startRestore(backupId, storageType, storageParams, isNotify)
.then(() => setTenantStatus(TenantStatus.PortalRestore))
.then(() => {
socketHelper.emit({
command: "restore-backup",
});
})
.then(() =>
history.push(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
"/preparation-portal"
)
startRestore(backupId, storageType, storageParams, isNotify)
.then(() => setTenantStatus(TenantStatus.PortalRestore))
.then(() => {
socketHelper.emit({
command: "restore-backup",
});
})
.then(() =>
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
"/preparation-portal"
)
)
.catch((error) => toastr.error(error))
.finally(() =>
this.setState({
isLoading: false,
selectedFileIndex: null,
selectedFileId: null,
})
);
});
)
.catch((error) => toastr.error(error))
.finally(() =>
setState((val) => ({
...val,
isLoading: false,
selectedFileIndex: null,
selectedFileId: null,
}))
);
};
onChangeCheckbox = () => {
this.setState({
isChecked: !this.state.isChecked,
});
const onChangeCheckbox = () => {
setState((val) => ({ ...val, isChecked: !val.isChecked }));
};
render() {
const {
onModalClose,
isVisibleDialog,
t,
isCopyingToLocal,
theme,
} = this.props;
const { filesList, isLoading, selectedFileIndex, isChecked } = this.state;
const { onModalClose, isVisibleDialog, t, isCopyingToLocal, theme } = props;
const { filesList, isLoading, selectedFileIndex, isChecked } = state;
const helpContent = () => (
<>
<Text className="restore-backup_warning-description">
{t("RestoreBackupWarningText")}{" "}
<Text as="span" className="restore-backup_warning-link">
{t("RestoreBackupResetInfoWarningText")}
</Text>
const helpContent = () => (
<>
<Text className="restore-backup_warning-description">
{t("RestoreBackupWarningText")}{" "}
<Text as="span" className="restore-backup_warning-link">
{t("RestoreBackupResetInfoWarningText")}
</Text>
</>
);
</Text>
</>
);
return (
<StyledModalDialog
displayType="aside"
visible={isVisibleDialog}
onClose={onModalClose}
withFooterBorder
>
<ModalDialog.Header>
<Text fontSize="21px" fontWeight={700}>
{t("BackupList")}
</Text>
</ModalDialog.Header>
<ModalDialog.Body>
<StyledBackupList
isCopyingToLocal={isCopyingToLocal}
isEmpty={filesList?.length === 0}
theme={theme}
>
<div className="backup-list_content">
{filesList.length > 0 && (
<div className="backup-restore_dialog-header">
<Text fontSize="12px" style={{ marginBottom: "10px" }}>
{t("BackupListWarningText")}
</Text>
<Link
onClick={this.onCleanBackupList}
fontWeight={600}
style={{ textDecoration: "underline dotted" }}
return (
<StyledModalDialog
displayType="aside"
visible={isVisibleDialog}
onClose={onModalClose}
withFooterBorder
>
<ModalDialog.Header>
<Text fontSize="21px" fontWeight={700}>
{t("BackupList")}
</Text>
</ModalDialog.Header>
<ModalDialog.Body>
<StyledBackupList
isCopyingToLocal={isCopyingToLocal}
isEmpty={filesList?.length === 0}
theme={theme}
>
<div className="backup-list_content">
{filesList.length > 0 && (
<div className="backup-restore_dialog-header">
<Text fontSize="12px" style={{ marginBottom: "10px" }}>
{t("BackupListWarningText")}
</Text>
<Link
onClick={this.onCleanBackupList}
fontWeight={600}
style={{ textDecoration: "underline dotted" }}
>
{t("ClearBackupList")}
</Link>
</div>
)}
<div className="backup-restore_dialog-scroll-body">
{!isLoading ? (
filesList.length > 0 ? (
<BackupListBody
filesList={filesList}
onDeleteBackup={this.onDeleteBackup}
onSelectFile={this.onSelectFile}
selectedFileIndex={selectedFileIndex}
/>
) : (
<Text
fontSize="12px"
textAlign="center"
className="backup-restore_empty-list"
>
{t("ClearBackupList")}
</Link>
{t("EmptyBackupList")}
</Text>
)
) : (
<div className="loader" key="loader">
<Loaders.ListLoader count={7} />
</div>
)}
<div className="backup-restore_dialog-scroll-body">
{!isLoading ? (
filesList.length > 0 ? (
<BackupListBody
filesList={filesList}
onDeleteBackup={this.onDeleteBackup}
onSelectFile={this.onSelectFile}
selectedFileIndex={selectedFileIndex}
/>
) : (
<Text
fontSize="12px"
textAlign="center"
className="backup-restore_empty-list"
>
{t("EmptyBackupList")}
</Text>
)
) : (
<div className="loader" key="loader">
<Loaders.ListLoader count={7} />
</div>
)}
</div>
</div>
</StyledBackupList>
</ModalDialog.Body>
<ModalDialog.Footer>
<div className="restore_footer">
<div id="backup-list_help">
<Checkbox
truncate
className="backup-list_checkbox"
onChange={this.onChangeCheckbox}
isChecked={isChecked}
/>
<Text as="span" className="backup-list_agreement-text">
{t("UserAgreement")}
<HelpButton
className="backup-list_tooltip"
offsetLeft={100}
iconName={HelpReactSvgUrl}
getContent={helpContent}
tooltipMaxWidth={"286px"}
/>
</Text>
</div>
<div className="restore_dialog-button">
<Button
primary
size="normal"
label={t("Common:Restore")}
onClick={this.onRestorePortal}
isDisabled={isCopyingToLocal || !isChecked}
/>
<Button
size="normal"
label={t("Common:CloseButton")}
onClick={onModalClose}
/>
</div>
</div>
</ModalDialog.Footer>
</StyledModalDialog>
);
}
}
</StyledBackupList>
</ModalDialog.Body>
<ModalDialog.Footer>
<div className="restore_footer">
<div id="backup-list_help">
<Checkbox
truncate
className="backup-list_checkbox"
onChange={this.onChangeCheckbox}
isChecked={isChecked}
/>
<Text as="span" className="backup-list_agreement-text">
{t("UserAgreement")}
<HelpButton
className="backup-list_tooltip"
offsetLeft={100}
iconName={HelpReactSvgUrl}
getContent={helpContent}
tooltipMaxWidth={"286px"}
/>
</Text>
</div>
<div className="restore_dialog-button">
<Button
primary
size="normal"
label={t("Common:Restore")}
onClick={this.onRestorePortal}
isDisabled={isCopyingToLocal || !isChecked}
/>
<Button
size="normal"
label={t("Common:CloseButton")}
onClick={onModalClose}
/>
</div>
</div>
</ModalDialog.Footer>
</StyledModalDialog>
);
};
BackupListModalDialog.propTypes = {
onModalClose: PropTypes.func.isRequired,

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { withTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
@ -20,12 +20,14 @@ const DataManagementWrapper = (props) => {
helpUrlCreatingBackup,
buttonSize,
t,
history,
isNotPaidPeriod,
currentColorScheme,
toDefault,
} = props;
const navigate = useNavigate();
const [currentTab, setCurrentTab] = useState(0);
const [isLoading, setIsLoading] = useState(false);
@ -93,7 +95,7 @@ const DataManagementWrapper = (props) => {
}, []);
const onSelect = (e) => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -120,11 +122,8 @@ export default inject(({ auth, setup, backup }) => {
const { settingsStore, currentTariffStatusStore } = auth;
const { isNotPaidPeriod } = currentTariffStatusStore;
const { toDefault } = backup;
const {
helpUrlCreatingBackup,
isTabletView,
currentColorScheme,
} = settingsStore;
const { helpUrlCreatingBackup, isTabletView, currentColorScheme } =
settingsStore;
const buttonSize = isTabletView ? "normal" : "small";
return {
@ -137,8 +136,4 @@ export default inject(({ auth, setup, backup }) => {
currentColorScheme,
toDefault,
};
})(
withTranslation(["Settings", "Common"])(
withRouter(observer(DataManagementWrapper))
)
);
})(withTranslation(["Settings", "Common"])(observer(DataManagementWrapper)));

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { withTranslation } from "react-i18next";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import Submenu from "@docspace/components/submenu";
import { inject, observer } from "mobx-react";
import PortalDeactivationSection from "./portalDeactivation";
@ -10,7 +10,9 @@ import { combineUrl } from "@docspace/common/utils";
import config from "../../../../../package.json";
const DeleteData = (props) => {
const { t, history, isNotPaidPeriod, tReady } = props;
const { t, isNotPaidPeriod, tReady } = props;
const navigate = useNavigate();
const [currentTab, setCurrentTab] = useState(0);
const [isLoading, setIsLoading] = useState(false);
@ -36,7 +38,7 @@ const DeleteData = (props) => {
}, []);
const onSelect = (e) => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -64,4 +66,4 @@ export default inject(({ auth }) => {
return {
isNotPaidPeriod,
};
})(observer(withTranslation("Settings")(withRouter(DeleteData))));
})(observer(withTranslation("Settings")(DeleteData)));

View File

@ -1,5 +1,4 @@
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { inject } from "mobx-react";
import Text from "@docspace/components/text";
@ -13,13 +12,8 @@ import { isDesktop } from "@docspace/components/utils/device";
import { EmployeeActivationStatus } from "@docspace/common/constants";
const PortalDeactivation = (props) => {
const {
t,
getPortalOwner,
owner,
currentColorScheme,
sendActivationLink,
} = props;
const { t, getPortalOwner, owner, currentColorScheme, sendActivationLink } =
props;
const [isDesktopView, setIsDesktopView] = useState(false);
const fetchData = async () => {
@ -104,8 +98,4 @@ export default inject(({ auth }) => {
currentColorScheme,
sendActivationLink,
};
})(
withTranslation(["Settings", "MainBar", "People"])(
withRouter(PortalDeactivation)
)
);
})(withTranslation("Settings", "MainBar", "People")(PortalDeactivation));

View File

@ -1,5 +1,4 @@
import React, { useEffect, useState } from "react";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { inject } from "mobx-react";
import Text from "@docspace/components/text";
@ -17,13 +16,8 @@ import { isDesktop } from "@docspace/components/utils/device";
import { EmployeeActivationStatus } from "@docspace/common/constants";
const PortalDeletion = (props) => {
const {
t,
getPortalOwner,
owner,
currentColorScheme,
sendActivationLink,
} = props;
const { t, getPortalOwner, owner, currentColorScheme, sendActivationLink } =
props;
const [isDialogVisible, setIsDialogVisible] = useState(false);
const [stripeUrl, setStripeUrl] = useState(null);
const [isDesktopView, setIsDesktopView] = useState(false);
@ -123,7 +117,5 @@ export default inject(({ auth }) => {
sendActivationLink,
};
})(
withTranslation(["Settings", "MainBar", "People", "Common"])(
withRouter(PortalDeletion)
)
withTranslation(["Settings", "MainBar", "People", "Common"])(PortalDeletion)
);

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import Submenu from "@docspace/components/submenu";
import { withRouter } from "react-router";
import { useNavigate } from "react-router-dom";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { combineUrl } from "@docspace/common/utils";
@ -15,9 +15,10 @@ import AppLoader from "@docspace/common/components/AppLoader";
import SSOLoader from "./sub-components/ssoLoader";
const IntegrationWrapper = (props) => {
const { t, tReady, history, loadBaseInfo, enablePlugins, toDefault } = props;
const { t, tReady, loadBaseInfo, enablePlugins, toDefault } = props;
const [currentTab, setCurrentTab] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
useEffect(() => {
return () => {
@ -62,7 +63,7 @@ const IntegrationWrapper = (props) => {
}, []);
const onSelect = (e) => {
history.push(
navigate(
combineUrl(
window.DocSpaceConfig?.proxy?.url,
config.homepage,
@ -91,6 +92,6 @@ export default inject(({ setup, auth, ssoStore }) => {
};
})(
withTranslation(["Settings", "SingleSignOn", "Translations"])(
withRouter(observer(IntegrationWrapper))
observer(IntegrationWrapper)
)
);

View File

@ -1,6 +1,5 @@
import React from "react";
import styled from "styled-components";
import { withRouter } from "react-router";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { ColorTheme, ThemeType } from "@docspace/common/components/ColorTheme";
@ -40,4 +39,4 @@ export default inject(({ payments, auth }) => {
salesEmail,
theme: auth.settingsStore.theme,
};
})(withRouter(observer(ContactContainer)));
})(observer(ContactContainer));

Some files were not shown because too many files have changed in this diff Show More