Merge branch 'feature/webhooks-page' of github.com:ONLYOFFICE/DocSpace into feature/webhooks-page

This commit is contained in:
pavelbannov 2023-06-07 21:23:54 +03:00
commit 6e7e3ef07e
104 changed files with 2926 additions and 2309 deletions

View File

@ -1,6 +1,6 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { useLocation, Navigate, Route, Outlet } from "react-router-dom";
import { useLocation, Outlet } from "react-router-dom";
import { withTranslation } from "react-i18next";
import Article from "@docspace/common/components/Article";
@ -22,23 +22,31 @@ import {
ArticleMainButtonContent,
} from "./components/Article";
const ClientArticle = React.memo(({ withMainButton }) => {
return (
<Article withMainButton={withMainButton}>
<Article.Header>
<ArticleHeaderContent />
</Article.Header>
const ClientArticle = React.memo(
({ withMainButton, setIsHeaderLoading, setIsFilterLoading }) => {
return (
<Article
withMainButton={withMainButton}
onLogoClickAction={() => {
setIsFilterLoading(true, false);
setIsHeaderLoading(true, false);
}}
>
<Article.Header>
<ArticleHeaderContent />
</Article.Header>
<Article.MainButton>
<ArticleMainButtonContent />
</Article.MainButton>
<Article.MainButton>
<ArticleMainButtonContent />
</Article.MainButton>
<Article.Body>
<ArticleBodyContent />
</Article.Body>
</Article>
);
});
<Article.Body>
<ArticleBodyContent />
</Article.Body>
</Article>
);
}
);
const ClientContent = (props) => {
const {
@ -55,8 +63,10 @@ const ClientContent = (props) => {
isFrame,
withMainButton,
t,
setFirstLoad,
isLoading,
setIsFilterLoading,
setIsHeaderLoading,
} = props;
const location = useLocation();
@ -114,10 +124,6 @@ const ClientContent = (props) => {
isDesktopInit,
]);
React.useEffect(() => {
setFirstLoad(false);
}, [setFirstLoad]);
React.useEffect(() => {
if (isLoading) {
showLoader();
@ -134,7 +140,11 @@ const ClientContent = (props) => {
isFrame ? (
showMenu && <ClientArticle />
) : (
<ClientArticle withMainButton={withMainButton} />
<ClientArticle
withMainButton={withMainButton}
setIsHeaderLoading={setIsHeaderLoading}
setIsFilterLoading={setIsFilterLoading}
/>
)
) : (
<></>
@ -144,45 +154,49 @@ const ClientContent = (props) => {
);
};
const Client = inject(({ auth, filesStore, peopleStore }) => {
const {
frameConfig,
isFrame,
isDesktopClient,
encryptionKeys,
setEncryptionKeys,
isEncryptionSupport,
} = auth.settingsStore;
const Client = inject(
({ auth, clientLoadingStore, filesStore, peopleStore }) => {
const {
frameConfig,
isFrame,
isDesktopClient,
encryptionKeys,
setEncryptionKeys,
isEncryptionSupport,
} = auth.settingsStore;
if (!auth.userStore.user) return;
if (!auth.userStore.user) return;
const { isVisitor } = auth.userStore.user;
const { isVisitor } = auth.userStore.user;
const { setFirstLoad, isLoading } = filesStore;
const { isLoading, setIsSectionFilterLoading, setIsSectionHeaderLoading } =
clientLoadingStore;
const withMainButton = !isVisitor;
const withMainButton = !isVisitor;
return {
isDesktop: isDesktopClient,
isFrame,
showMenu: frameConfig?.showMenu,
user: auth.userStore.user,
isAuthenticated: auth.isAuthenticated,
encryptionKeys: encryptionKeys,
isEncryption: isEncryptionSupport,
isLoaded: auth.isLoaded && filesStore.isLoaded,
setIsLoaded: filesStore.setIsLoaded,
withMainButton,
setFirstLoad,
isLoading,
setEncryptionKeys: setEncryptionKeys,
loadClientInfo: async () => {
const actions = [];
actions.push(filesStore.initFiles());
actions.push(peopleStore.init());
await Promise.all(actions);
},
};
})(withTranslation("Common")(observer(ClientContent)));
return {
isDesktop: isDesktopClient,
isFrame,
showMenu: frameConfig?.showMenu,
user: auth.userStore.user,
isAuthenticated: auth.isAuthenticated,
encryptionKeys: encryptionKeys,
isEncryption: isEncryptionSupport,
isLoaded: auth.isLoaded && clientLoadingStore.isLoaded,
setIsLoaded: clientLoadingStore.setIsLoaded,
withMainButton,
setIsFilterLoading: setIsSectionFilterLoading,
setIsHeaderLoading: setIsSectionHeaderLoading,
isLoading,
setEncryptionKeys: setEncryptionKeys,
loadClientInfo: async () => {
const actions = [];
actions.push(filesStore.initFiles());
actions.push(peopleStore.init());
await Promise.all(actions);
},
};
}
)(withTranslation("Common")(observer(ClientContent)));
export default () => <Client />;

View File

@ -1,13 +1,13 @@
import React, { useEffect, useState } from "react";
import { observer, inject } from "mobx-react";
import { isMobile } from "react-device-detect";
import { useLocation } from "react-router-dom";
import Loaders from "@docspace/common/components/Loaders";
const pathname = window.location.pathname.toLowerCase();
const isEditor = pathname.indexOf("doceditor") !== -1;
const isGallery = pathname.indexOf("form-gallery") !== -1;
let loadTimeout = null;
const withLoader = (WrappedComponent) => (Loader) => {
const withLoader = (props) => {
const {
@ -15,55 +15,30 @@ const withLoader = (WrappedComponent) => (Loader) => {
tReady,
firstLoad,
isLoaded,
isLoading,
viewAs,
setIsBurgerLoading,
showBodyLoader,
isLoadingFilesFind,
accountsViewAs,
} = props;
const [inLoad, setInLoad] = useState(false);
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
const location = useLocation();
useEffect(() => {
if (isLoading) {
cleanTimer();
loadTimeout = setTimeout(() => {
//console.log("inLoad", true);
setInLoad(true);
}, 500);
} else {
cleanTimer();
//console.log("inLoad", false);
setInLoad(false);
}
return () => {
cleanTimer();
};
}, [isLoading]);
useEffect(() => {
if ((!isEditor && firstLoad) || !isLoaded || (isMobile && inLoad)) {
setIsBurgerLoading(true);
} else {
setIsBurgerLoading(false);
}
}, [isEditor, firstLoad, isLoaded, isMobile, inLoad]);
const currentViewAs = location.pathname.includes("/accounts/filter")
? accountsViewAs
: viewAs;
return (!isEditor && firstLoad && !isGallery) ||
!isLoaded ||
(isMobile && inLoad && !firstLoad) ||
showBodyLoader ||
(isLoadingFilesFind && !Loader) ||
!tReady ||
!isInit ? (
Loader ? (
Loader
) : viewAs === "tile" ? (
) : currentViewAs === "tile" ? (
<Loaders.Tiles />
) : viewAs === "table" ? (
) : currentViewAs === "table" ? (
<Loaders.TableLoader />
) : (
<Loaders.Rows />
@ -73,14 +48,11 @@ const withLoader = (WrappedComponent) => (Loader) => {
);
};
return inject(({ auth, filesStore }) => {
const {
firstLoad,
isLoading,
viewAs,
isLoadingFilesFind,
isInit,
} = filesStore;
return inject(({ auth, filesStore, peopleStore, clientLoadingStore }) => {
const { viewAs, isLoadingFilesFind, isInit } = filesStore;
const { viewAs: accountsViewAs } = peopleStore;
const { firstLoad, isLoading, showBodyLoader } = clientLoadingStore;
const { settingsStore } = auth;
const { setIsBurgerLoading } = settingsStore;
return {
@ -91,6 +63,8 @@ const withLoader = (WrappedComponent) => (Loader) => {
setIsBurgerLoading,
isLoadingFilesFind,
isInit,
showBodyLoader,
accountsViewAs,
};
})(observer(withLoader));
};

View File

@ -1,105 +0,0 @@
import React, { useEffect, useState } from "react";
import { observer, inject } from "mobx-react";
let loadTimeout = null;
const delayLoader = 300;
const withLoader = (WrappedComponent) => (Loader) => {
const withLoader = (props) => {
const {
tReady,
isLoaded,
isLoading,
firstLoad,
profileLoaded,
setIsBurgerLoading,
isLoadedProfileSectionBody,
setIsLoadedProfileSectionBody,
} = props;
const [inLoad, setInLoad] = useState(true);
const isProfileViewLoader = Loader.props.isProfileView;
const isProfileFooterLoader = Loader.props.isProfileFooter;
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
useEffect(() => {
if (isLoading) {
cleanTimer();
loadTimeout = setTimeout(() => {
//console.log("inLoad", true);
setInLoad(true);
}, delayLoader);
} else {
cleanTimer();
//console.log("inLoad", false);
setInLoad(false);
}
return () => {
cleanTimer();
};
}, [isLoading]);
useEffect(() => {
if (!isLoaded) {
setIsBurgerLoading(true);
} else {
setIsBurgerLoading(false);
}
}, [isLoaded]);
useEffect(() => {
if (!isProfileViewLoader) return;
if (!(firstLoad || !isLoaded || inLoad || !tReady || !profileLoaded)) {
setIsLoadedProfileSectionBody(true);
} else {
setIsLoadedProfileSectionBody(false);
}
}, [
firstLoad,
isLoaded,
inLoad,
tReady,
profileLoaded,
setIsLoadedProfileSectionBody,
isProfileViewLoader,
]);
return firstLoad ||
!isLoaded ||
inLoad ||
!tReady ||
!profileLoaded ||
(isProfileFooterLoader && !isLoadedProfileSectionBody) ? (
Loader
) : (
<WrappedComponent {...props} />
);
};
return inject(({ auth, peopleStore }) => {
const { isLoaded, settingsStore } = auth;
const {
loadingStore,
isLoadedProfileSectionBody,
setIsLoadedProfileSectionBody,
} = peopleStore;
const { isLoading, firstLoad, profileLoaded } = loadingStore;
const { setIsBurgerLoading } = settingsStore;
return {
isLoaded,
isLoading,
firstLoad,
profileLoaded,
setIsBurgerLoading,
isLoadedProfileSectionBody,
setIsLoadedProfileSectionBody,
};
})(observer(withLoader));
};
export default withLoader;

View File

@ -262,7 +262,6 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
}, [userId]);
useEffect(() => {
console.log(window.DocSpaceConfig.imageThumbnails);
if (!userId || !window.DocSpaceConfig.imageThumbnails) return;
initIndexedDb();

View File

@ -1,63 +1,37 @@
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import React from "react";
import { useNavigate } from "react-router-dom";
import CatalogItem from "@docspace/components/catalog-item";
import React from "react";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import CatalogItem from "@docspace/components/catalog-item";
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import withLoader from "../../../HOCs/withLoader";
const iconUrl = CatalogAccountsReactSvgUrl;
const PureAccountsItem = ({
showText,
setSelectedFolder,
selectedTreeNode,
setSelectedNode,
toggleArticleOpen,
t,
}) => {
const navigate = useNavigate();
const onClick = React.useCallback(() => {
setSelectedFolder(null);
setSelectedNode(["accounts", "filter"]);
navigate("/accounts/filter");
toggleArticleOpen();
}, [setSelectedFolder, setSelectedNode, history]);
const isActive = selectedTreeNode[0] === "accounts";
const PureAccountsItem = ({ showText, isActive, onClick, t }) => {
const onClickAction = React.useCallback(() => {
onClick && onClick("accounts");
}, [onClick]);
return (
<CatalogItem
key="accounts"
text={t("Common:Accounts")}
icon={iconUrl}
text={t("Accounts")}
icon={CatalogAccountsReactSvgUrl}
showText={showText}
onClick={onClick}
onClick={onClickAction}
isActive={isActive}
folderId="document_catalog-accounts"
/>
);
};
const AccountsItem = withTranslation(["FilesSettings", "Common"])(
withLoader(PureAccountsItem)(<></>)
);
const AccountsItem = withTranslation(["Common"])(PureAccountsItem);
export default inject(({ auth, treeFoldersStore, selectedFolderStore }) => {
const { setSelectedFolder } = selectedFolderStore;
const { selectedTreeNode, setSelectedNode } = treeFoldersStore;
const { toggleArticleOpen, showText } = auth.settingsStore;
export default inject(({ auth }) => {
const { showText } = auth.settingsStore;
return {
showText,
setSelectedFolder,
selectedTreeNode,
setSelectedNode,
toggleArticleOpen,
};
})(observer(AccountsItem));

View File

@ -8,7 +8,7 @@ import CatalogFavoritesReactSvgUrl from "PUBLIC_DIR/images/catalog.favorites.rea
import CatalogRecentReactSvgUrl from "PUBLIC_DIR/images/catalog.recent.react.svg?url";
import CatalogPrivateReactSvgUrl from "PUBLIC_DIR/images/catalog.private.react.svg?url";
import CatalogTrashReactSvgUrl from "PUBLIC_DIR/images/catalog.trash.react.svg?url";
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
@ -104,6 +104,13 @@ const Item = ({
setIsDragActive(false);
}, []);
const onClickAction = React.useCallback(
(folderId) => {
onClick && onClick(folderId, item.title, item.rootFolderType);
},
[onClick, item.title, item.rootFolderType]
);
return (
<StyledDragAndDrop
key={item.id}
@ -113,17 +120,18 @@ const Item = ({
dragging={dragging && isDragging}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
className={"document-catalog"}
>
<CatalogItem
key={item.id}
id={item.id}
folderId={folderId}
className={`tree-drag ${item.folderClassName}`}
className={`tree-drag ${item.folderClassName} document-catalog`}
icon={getFolderIcon(item)}
showText={showText}
text={item.title}
isActive={isActive(item)}
onClick={onClick}
isActive={isActive}
onClick={onClickAction}
onDrop={onMoveTo}
isEndOfBlock={getEndOfBlock(item)}
isDragging={isDragging}
@ -139,14 +147,11 @@ const Item = ({
);
};
let dataMainTree = [];
const Items = ({
t,
data,
showText,
pathParts,
rootFolderType,
selectedTreeNode,
onClick,
onBadgeClick,
@ -173,45 +178,12 @@ const Items = ({
firstLoad,
deleteAction,
startDrag,
activeItemId,
emptyTrashInProgress,
}) => {
useEffect(() => {
data.forEach((elem) => {
const elemId = elem.id;
dataMainTree.push(elemId.toString());
});
}, [data]);
const isActive = React.useCallback(
(item) => {
if (selectedTreeNode.length > 0) {
const isMainFolder = dataMainTree.indexOf(selectedTreeNode[0]) !== -1;
if (
rootFolderType === FolderType.Rooms &&
item.rootFolderType === FolderType.Rooms
) {
return true;
}
if (pathParts && pathParts.includes(item.id) && !isMainFolder)
return true;
if (
(selectedTreeNode[0] === "@my" || selectedTreeNode[0] === "@rooms") &&
item.key === "0-0"
) {
return true;
}
return `${item.id}` === selectedTreeNode[0];
}
},
[selectedTreeNode, pathParts, docSpace, rootFolderType]
);
const getEndOfBlock = React.useCallback(
(item) => {
if (docSpace) return false;
switch (item.key) {
case "0-3":
case "0-5":
@ -360,7 +332,7 @@ const Items = ({
item={item}
dragging={dragging}
getFolderIcon={getFolderIcon}
isActive={isActive}
isActive={item.id === activeItemId}
getEndOfBlock={getEndOfBlock}
showText={showText}
onClick={onClick}
@ -376,9 +348,25 @@ const Items = ({
});
if (!firstLoad && !isVisitor)
items.splice(3, 0, <SettingsItem key="settings-item" />);
items.splice(
3,
0,
<SettingsItem
key="settings-item"
onClick={onClick}
isActive={activeItemId === "settings"}
/>
);
if (!isVisitor && !isCollaborator)
items.splice(3, 0, <AccountsItem key="accounts-item" />);
items.splice(
3,
0,
<AccountsItem
key="accounts-item"
onClick={onClick}
isActive={activeItemId === "accounts"}
/>
);
if (!isVisitor) items.splice(3, 0, <CatalogDivider key="other-header" />);
else items.splice(2, 0, <CatalogDivider key="other-header" />);
@ -389,7 +377,6 @@ const Items = ({
t,
dragging,
getFolderIcon,
isActive,
onClick,
onMoveTo,
getEndOfBlock,
@ -403,6 +390,7 @@ const Items = ({
isAdmin,
isVisitor,
firstLoad,
activeItemId,
emptyTrashInProgress,
]
);
@ -413,7 +401,6 @@ const Items = ({
Items.propTypes = {
data: PropTypes.array,
showText: PropTypes.bool,
selectedTreeNode: PropTypes.array,
onClick: PropTypes.func,
onClickBadge: PropTypes.func,
onHide: PropTypes.func,
@ -428,6 +415,7 @@ export default inject(
filesActionsStore,
uploadDataStore,
dialogsStore,
clientLoadingStore,
}) => {
const {
selection,
@ -435,21 +423,18 @@ export default inject(
dragging,
setDragging,
trashIsEmpty,
firstLoad,
startDrag,
} = filesStore;
const { firstLoad } = clientLoadingStore;
const { startUpload } = uploadDataStore;
const {
selectedTreeNode,
treeFolders,
myFolderId,
commonFolderId,
isPrivacyFolder,
} = treeFoldersStore;
const { treeFolders, myFolderId, commonFolderId, isPrivacyFolder } =
treeFoldersStore;
const { id, pathParts, rootFolderType } = selectedFolderStore;
const { id } = selectedFolderStore;
const {
moveDragItems,
uploadEmptyFolders,
@ -468,9 +453,9 @@ export default inject(
currentId: id,
showText: auth.settingsStore.showText,
docSpace: auth.settingsStore.docSpace,
pathParts,
data: treeFolders,
selectedTreeNode,
draggableItems: dragging
? bufferSelection
? [bufferSelection]
@ -484,7 +469,7 @@ export default inject(
uploadEmptyFolders,
setEmptyTrashDialogVisible,
trashIsEmpty,
rootFolderType,
firstLoad,
startDrag,
emptyTrashInProgress,

View File

@ -1,59 +1,23 @@
import CatalogSettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
import React from "react";
import { useNavigate, useParams } from "react-router-dom";
import CatalogItem from "@docspace/components/catalog-item";
import React from "react";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import withLoader from "../../../HOCs/withLoader";
import { isMobile } from "@docspace/components/utils/device";
import { isMobileOnly } from "react-device-detect";
const iconUrl = CatalogSettingsReactSvgUrl;
import CatalogItem from "@docspace/components/catalog-item";
const PureSettingsItem = ({
expandedSetting,
setSelectedNode,
setExpandSettingsTree,
setSelectedFolder,
import CatalogSettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
t,
showText,
toggleArticleOpen,
}) => {
const { setting } = useParams();
const navigate = useNavigate();
React.useEffect(() => {
setSelectedNode([setting]);
}, [setting, setSelectedNode]);
React.useEffect(() => {
if (setting && !expandedSetting) setExpandSettingsTree(["settings"]);
}, [expandedSetting, setExpandSettingsTree]);
const onClick = React.useCallback(() => {
setSelectedFolder(null);
setSelectedNode(["common"]);
setExpandSettingsTree(["common"]);
if (isMobile() || isMobileOnly) toggleArticleOpen();
navigate("/settings/common");
}, [
setSelectedFolder,
setSelectedNode,
setExpandSettingsTree,
toggleArticleOpen,
]);
const isActive = window.location.pathname.includes("settings");
const PureSettingsItem = ({ t, showText, isActive, onClick }) => {
const onClickAction = React.useCallback(() => {
onClick && onClick("settings");
}, [onClick]);
return (
<CatalogItem
key="settings"
text={t("Common:Settings")}
icon={iconUrl}
icon={CatalogSettingsReactSvgUrl}
showText={showText}
onClick={onClick}
onClick={onClickAction}
isActive={isActive}
folderId="document_catalog-settings"
/>
@ -61,22 +25,11 @@ const PureSettingsItem = ({
};
const SettingsItem = withTranslation(["FilesSettings", "Common"])(
withLoader(PureSettingsItem)(<></>)
PureSettingsItem
);
export default inject(
({ auth, settingsStore, treeFoldersStore, selectedFolderStore }) => {
const { setSelectedFolder } = selectedFolderStore;
const { setSelectedNode } = treeFoldersStore;
const { expandedSetting, setExpandSettingsTree } = settingsStore;
return {
expandedSetting,
setSelectedFolder,
setSelectedNode,
setExpandSettingsTree,
showText: auth.settingsStore.showText,
toggleArticleOpen: auth.settingsStore.toggleArticleOpen,
};
}
)(observer(SettingsItem));
export default inject(({ auth }) => {
return {
showText: auth.settingsStore.showText,
};
})(observer(SettingsItem));

View File

@ -1,23 +1,23 @@
import React from "react";
import styled from "styled-components";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { isDesktop, isTablet, isMobileOnly } from "react-device-detect";
import { useNavigate, useLocation } from "react-router-dom";
import { setDocumentTitle } from "@docspace/client/src/helpers/filesUtils";
import config from "PACKAGE_FILE";
import { RoomSearchArea } from "@docspace/common/constants";
import Items from "./Items";
import { isMobile, tablet } from "@docspace/components/utils/device";
import FilesFilter from "@docspace/common/api/files/filter";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { combineUrl } from "@docspace/common/utils";
import { isDesktop, isTablet, isMobileOnly } from "react-device-detect";
import AccountsFilter from "@docspace/common/api/people/filter";
import DownloadAppList from "./DownloadAppList";
import Banner from "./Banner";
import { showLoader, hideLoader } from "@docspace/common/utils";
import Loaders from "@docspace/common/components/Loaders";
import withLoader from "../../../HOCs/withLoader";
import { withTranslation } from "react-i18next";
import toastr from "@docspace/components/toast/toastr";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
@ -31,93 +31,135 @@ const StyledBlock = styled.div`
const ArticleBodyContent = (props) => {
const {
personal,
docSpace,
firstLoad,
showText,
isDesktopClient,
// enableThirdParty,
isVisitor,
firstLoad,
FirebaseHelper,
theme,
showText,
toggleArticleOpen,
categoryType,
isAdmin,
filesIsLoading,
roomsFolderId,
archiveFolderId,
myFolderId,
recycleBinFolderId,
rootFolderId,
isVisitor,
setIsLoading,
clearFiles,
selectedFolderId,
showArticleLoader,
setIsBurgerLoading,
} = props;
const [disableBadgeClick, setDisableBadgeClick] = React.useState(false);
const navigate = useNavigate();
const location = useLocation();
let loadTimeout = null;
const [disableBadgeClick, setDisableBadgeClick] = React.useState(false);
const [activeItemId, setActiveItemId] = React.useState(null);
const campaigns = (localStorage.getItem("campaigns") || "")
.split(",")
.filter((campaign) => campaign.length > 0);
const cleanTimer = () => {
loadTimeout && clearTimeout(loadTimeout);
loadTimeout = null;
};
const isAccounts = location.pathname.includes("accounts/filter");
const onClick = React.useCallback(
(folderId) => {
const {
toggleArticleOpen,
setIsLoading,
fetchFiles,
(folderId, title, rootFolderType) => {
const { toggleArticleOpen } = props;
fetchRooms,
setAlreadyFetchingRooms,
} = props;
let params = null;
let path = ``;
if (filesIsLoading) return;
const filesSection = window.location.pathname.indexOf("/filter") > 0;
const state = {
title,
isRoot: true,
rootFolderType,
};
if (filesSection) {
// loadTimeout = setTimeout(() => {
setIsLoading(true);
// }, 200);
} else {
showLoader();
}
let withTimer = !!selectedFolderId;
if (folderId === roomsFolderId || folderId === archiveFolderId) {
setAlreadyFetchingRooms(true);
switch (folderId) {
case myFolderId:
const myFilter = FilesFilter.getDefault();
myFilter.folder = folderId;
params = myFilter.toUrlParams();
const filter = RoomsFilter.getDefault();
filter.searchArea =
folderId === archiveFolderId
? RoomSearchArea.Archive
: RoomSearchArea.Active;
path = getCategoryUrl(CategoryType.Personal);
fetchRooms(folderId, filter).finally(() => {
if (filesSection) {
cleanTimer();
setIsLoading(false);
} else {
hideLoader();
if (activeItemId === myFolderId && folderId === selectedFolderId)
return;
break;
case archiveFolderId:
const archiveFilter = RoomsFilter.getDefault();
archiveFilter.searchArea = RoomSearchArea.Archive;
params = archiveFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Archive);
if (activeItemId === archiveFolderId && folderId === selectedFolderId)
return;
break;
case recycleBinFolderId:
const recycleBinFilter = FilesFilter.getDefault();
recycleBinFilter.folder = folderId;
params = recycleBinFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Trash);
if (
activeItemId === recycleBinFolderId &&
folderId === selectedFolderId
)
return;
break;
case "accounts":
clearFiles();
const accountsFilter = AccountsFilter.getDefault();
params = accountsFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Accounts);
if (activeItemId === "accounts" && isAccounts) return;
break;
case "settings":
clearFiles();
path = getCategoryUrl(CategoryType.Settings);
navigate(path);
if (isMobileOnly || isMobile()) {
toggleArticleOpen();
}
});
} else {
fetchFiles(folderId, null, true, false)
.catch((err) => toastr.error(err))
.finally(() => {
if (filesSection) {
cleanTimer();
setIsLoading(false);
} else {
hideLoader();
}
});
return;
case roomsFolderId:
default:
const roomsFilter = RoomsFilter.getDefault();
roomsFilter.searchArea = RoomSearchArea.Active;
params = roomsFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Shared);
if (activeItemId === roomsFolderId && folderId === selectedFolderId)
return;
break;
}
setIsLoading(true, withTimer);
path += `?${params}`;
navigate(path, { state });
if (isMobileOnly || isMobile()) {
toggleArticleOpen();
}
},
[categoryType, roomsFolderId, archiveFolderId]
[
roomsFolderId,
archiveFolderId,
myFolderId,
recycleBinFolderId,
activeItemId,
selectedFolderId,
isAccounts,
]
);
const onShowNewFilesPanel = React.useCallback(
@ -133,6 +175,69 @@ const ArticleBodyContent = (props) => {
[disableBadgeClick]
);
React.useEffect(() => {
if (
location.pathname.includes("/rooms/shared") &&
activeItemId !== roomsFolderId
)
return setActiveItemId(roomsFolderId);
if (
location.pathname.includes("/rooms/archived") &&
activeItemId !== archiveFolderId
)
return setActiveItemId(archiveFolderId);
if (
location.pathname.includes("/rooms/personal") &&
activeItemId !== myFolderId
)
return setActiveItemId(myFolderId);
if (
location.pathname.includes("/files/trash") &&
activeItemId !== recycleBinFolderId
)
return setActiveItemId(recycleBinFolderId);
if (
location.pathname.includes("/accounts/filter") &&
activeItemId !== "accounts"
)
return setActiveItemId("accounts");
if (location.pathname.includes("/settings") && activeItemId !== "settings")
return setActiveItemId("settings");
if (location.pathname.includes("/accounts/view/@self")) {
if (isVisitor) {
if (activeItemId) return;
return setActiveItemId(rootFolderId);
}
if (activeItemId !== "accounts") return setActiveItemId("accounts");
}
if (location.pathname.includes("/products/files/#preview")) {
setActiveItemId(rootFolderId);
}
}, [
location.pathname,
activeItemId,
roomsFolderId,
archiveFolderId,
myFolderId,
recycleBinFolderId,
isVisitor,
rootFolderId,
]);
React.useEffect(() => {
setIsBurgerLoading(showArticleLoader);
}, [showArticleLoader]);
if (showArticleLoader) return <Loaders.ArticleFolder />;
return (
<>
<Items
@ -140,17 +245,17 @@ const ArticleBodyContent = (props) => {
onBadgeClick={onShowNewFilesPanel}
showText={showText}
onHide={toggleArticleOpen}
activeItemId={activeItemId}
/>
{!isDesktopClient && showText && !docSpace && (
{/* {!isDesktopClient && showText && (
<StyledBlock showText={showText}>
<DownloadAppList theme={theme} />
{(isDesktop || isTablet) &&
personal &&
!firstLoad &&
campaigns.length > 0 && <Banner FirebaseHelper={FirebaseHelper} />}
{(isDesktop || isTablet) && !firstLoad && campaigns.length > 0 && (
<Banner FirebaseHelper={FirebaseHelper} />
)}
</StyledBlock>
)}
)} */}
</>
);
};
@ -160,68 +265,50 @@ export default inject(
auth,
filesStore,
treeFoldersStore,
selectedFolderStore,
dialogsStore,
settingsStore,
selectedFolderStore,
clientLoadingStore,
}) => {
const { clearFiles } = filesStore;
const {
fetchFiles,
fetchRooms,
setAlreadyFetchingRooms,
setIsLoading,
setFirstLoad,
firstLoad,
isLoading,
isLoaded,
categoryType,
filesIsLoading,
} = filesStore;
showArticleLoader,
const { roomsFolderId, archiveFolderId } = treeFoldersStore;
setIsSectionFilterLoading,
firstLoad,
} = clientLoadingStore;
const setIsLoading = (param, withTimer) => {
setIsSectionFilterLoading(param, withTimer);
};
const { roomsFolderId, archiveFolderId, myFolderId, recycleBinFolderId } =
treeFoldersStore;
const { setNewFilesPanelVisible } = dialogsStore;
const isArticleLoading = (!isLoaded || isLoading) && firstLoad;
const selectedFolderId = selectedFolderStore.id;
const rootFolderId = selectedFolderStore.rootFolderId;
const {
showText,
articleOpen,
toggleArticleOpen,
personal,
docSpace,
isDesktopClient,
FirebaseHelper,
theme,
setIsBurgerLoading,
} = auth.settingsStore;
const selectedFolderTitle = selectedFolderStore.title;
selectedFolderTitle
? setDocumentTitle(selectedFolderTitle)
: setDocumentTitle();
return {
toggleArticleOpen,
showText,
articleOpen,
enableThirdParty: settingsStore.enableThirdParty,
showArticleLoader,
isVisitor: auth.userStore.user.isVisitor,
isAdmin: auth.userStore.user.isAdmin,
homepage: config.homepage,
fetchRooms,
setAlreadyFetchingRooms,
personal,
docSpace,
isArticleLoading,
setIsLoading,
setFirstLoad,
fetchFiles,
setNewFilesPanelVisible,
firstLoad,
isDesktopClient,
FirebaseHelper,
@ -229,13 +316,15 @@ export default inject(
roomsFolderId,
archiveFolderId,
myFolderId,
recycleBinFolderId,
rootFolderId,
categoryType,
filesIsLoading,
setIsLoading,
clearFiles,
selectedFolderId,
setIsBurgerLoading,
};
}
)(
withTranslation([])(
withLoader(observer(ArticleBodyContent))(<Loaders.ArticleFolder />)
)
);
)(withTranslation([])(observer(ArticleBodyContent)));

View File

@ -23,9 +23,7 @@ import { encryptionUploadDialog } from "../../../helpers/desktop";
import { useNavigate, useLocation } from "react-router-dom";
import MobileView from "./MobileView";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import withLoader from "../../../HOCs/withLoader";
import { Events, EmployeeType } from "@docspace/common/constants";
import { getMainButtonItems } from "SRC_DIR/helpers/plugins";
@ -89,6 +87,7 @@ const StyledButton = styled(Button)`
const ArticleMainButtonContent = (props) => {
const {
t,
tReady,
isMobileArticle,
isPrivacy,
@ -97,7 +96,7 @@ const ArticleMainButtonContent = (props) => {
startUpload,
setAction,
setSelectFileDialogVisible,
isArticleLoading,
showArticleLoader,
isFavoritesFolder,
isRecentFolder,
isRecycleBinFolder,
@ -106,8 +105,6 @@ const ArticleMainButtonContent = (props) => {
isRoomsFolder,
isArchiveFolder,
selectedTreeNode,
enablePlugins,
currentColorScheme,
@ -124,7 +121,11 @@ const ArticleMainButtonContent = (props) => {
setInviteUsersWarningDialogVisible,
} = props;
const isAccountsPage = selectedTreeNode[0] === "accounts";
const navigate = useNavigate();
const location = useLocation();
const isAccountsPage = location.pathname.includes("/accounts/filter");
const isSettingsPage = location.pathname.includes("settings");
const inputFilesElement = React.useRef(null);
const inputFolderElement = React.useRef(null);
@ -134,9 +135,6 @@ 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;
@ -227,16 +225,12 @@ const ArticleMainButtonContent = (props) => {
}, [resendInvitesAgain]);
React.useEffect(() => {
const isSettingFolder =
location.pathname.endsWith("/settings/common") ||
location.pathname.endsWith("/settings/admin");
const isFolderHiddenDropdown =
isArchiveFolder ||
isFavoritesFolder ||
isRecentFolder ||
isRecycleBinFolder ||
isSettingFolder;
isSettingsPage;
if (isFolderHiddenDropdown) {
setIsDropdownMainButton(false);
@ -248,11 +242,11 @@ const ArticleMainButtonContent = (props) => {
isFavoritesFolder,
isRecentFolder,
isRecycleBinFolder,
location.pathname,
isSettingsPage,
]);
React.useEffect(() => {
if (isRoomsFolder) return;
if (isRoomsFolder || isSettingsPage) return;
const formActions = [
{
@ -439,6 +433,7 @@ const ArticleMainButtonContent = (props) => {
isPrivacy,
currentFolderId,
isAccountsPage,
isSettingsPage,
enablePlugins,
isRoomsFolder,
isOwner,
@ -452,35 +447,36 @@ const ArticleMainButtonContent = (props) => {
onUploadFolderClick,
]);
const canInvite =
isAccountsPage &&
selectedTreeNode.length > 1 &&
selectedTreeNode[1] === "filter";
const mainButtonText = isAccountsPage
? t("Common:Invite")
: t("Common:Actions");
const isDisabled = isAccountsPage ? !canInvite : !security?.Create;
const isDisabled = isSettingsPage
? isSettingsPage
: isAccountsPage
? !isAccountsPage
: !security?.Create;
const isProfile = location.pathname === "/accounts/view/@self";
if (showArticleLoader)
return isMobileArticle ? null : <Loaders.ArticleButton height="32px" />;
return (
<>
{isMobileArticle ? (
<>
{!isArticleLoading &&
!isProfile &&
(security?.Create || canInvite) && (
<MobileView
t={t}
titleProp={t("Upload")}
actionOptions={actions}
buttonOptions={uploadActions}
isRooms={isRoomsFolder}
mainButtonMobileVisible={mainButtonMobileVisible}
onMainButtonClick={onCreateRoom}
/>
)}
{!isProfile && (security?.Create || isAccountsPage) && (
<MobileView
t={t}
titleProp={t("Upload")}
actionOptions={actions}
buttonOptions={uploadActions}
isRooms={isRoomsFolder}
mainButtonMobileVisible={mainButtonMobileVisible}
onMainButtonClick={onCreateRoom}
/>
)}
</>
) : isRoomsFolder ? (
<StyledButton
@ -543,15 +539,10 @@ export default inject(
uploadDataStore,
treeFoldersStore,
selectedFolderStore,
accessRightsStore,
clientLoadingStore,
}) => {
const {
isLoaded,
firstLoad,
isLoading,
mainButtonMobileVisible,
} = filesStore;
const { showArticleLoader } = clientLoadingStore;
const { mainButtonMobileVisible } = filesStore;
const {
isPrivacyFolder,
isFavoritesFolder,
@ -568,8 +559,6 @@ export default inject(
setInviteUsersWarningDialogVisible,
} = dialogsStore;
const isArticleLoading = (!isLoaded || isLoading) && firstLoad;
const { enablePlugins, currentColorScheme } = auth.settingsStore;
const security = selectedFolderStore.security;
@ -585,7 +574,7 @@ export default inject(
showText: auth.settingsStore.showText,
isMobileArticle: auth.settingsStore.isMobileArticle,
isArticleLoading,
showArticleLoader,
isPrivacy: isPrivacyFolder,
isFavoritesFolder,
isRecentFolder,
@ -600,9 +589,6 @@ export default inject(
setSelectFileDialogVisible,
setInvitePanelOptions,
isLoading,
isLoaded,
firstLoad,
currentFolderId,
enablePlugins,
@ -623,9 +609,5 @@ export default inject(
"Files",
"People",
"PeopleTranslations",
])(
withLoader(observer(ArticleMainButtonContent))(
<Loaders.ArticleButton height="28px" />
)
)
])(observer(ArticleMainButtonContent))
);

View File

@ -2,6 +2,7 @@
import EmptyScreenFilterAltDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_filter_alt_dark.svg?url";
import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url";
import React from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import EmptyContainer from "./EmptyContainer";
@ -15,8 +16,7 @@ const EmptyFilterContainer = ({
t,
selectedFolderId,
setIsLoading,
fetchFiles,
fetchRooms,
linkStyles,
isRooms,
isArchiveFolder,
@ -24,6 +24,9 @@ const EmptyFilterContainer = ({
setClearSearch,
theme,
}) => {
const navigate = useNavigate();
const location = useLocation();
const subheadingText = t("EmptyFilterSubheadingText");
const descriptionText = isRooms
? t("Common:SearchEmptyRoomsDescription")
@ -39,14 +42,14 @@ const EmptyFilterContainer = ({
if (isRoomsFolder) {
const newFilter = RoomsFilter.getDefault();
fetchRooms(selectedFolderId, newFilter)
.catch((err) => toastr.error(err))
.finally(() => setIsLoading(false));
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
} else {
const newFilter = FilesFilter.getDefault();
fetchFiles(selectedFolderId, newFilter)
.catch((err) => toastr.error(err))
.finally(() => setIsLoading(false));
newFilter.folder = selectedFolderId;
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
}
};
@ -80,16 +83,20 @@ const EmptyFilterContainer = ({
};
export default inject(
({ auth, filesStore, selectedFolderStore, treeFoldersStore }) => {
({
auth,
filesStore,
selectedFolderStore,
treeFoldersStore,
clientLoadingStore,
}) => {
const { isRoomsFolder, isArchiveFolder } = treeFoldersStore;
const isRooms = isRoomsFolder || isArchiveFolder;
return {
fetchFiles: filesStore.fetchFiles,
fetchRooms: filesStore.fetchRooms,
selectedFolderId: selectedFolderStore.id,
setIsLoading: filesStore.setIsLoading,
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
isRooms,
isArchiveFolder,
isRoomsFolder,

View File

@ -6,60 +6,102 @@ import EmptyScreenCorporateSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate
import EmptyScreenCorporateDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
import { inject, observer } from "mobx-react";
import React, { useEffect } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { withTranslation } from "react-i18next";
import EmptyContainer from "./EmptyContainer";
import Link from "@docspace/components/link";
import Box from "@docspace/components/box";
import { Text } from "@docspace/components";
import { ReactSVG } from "react-svg";
import FilesFilter from "@docspace/common/api/files/filter";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import Loaders from "@docspace/common/components/Loaders";
import { showLoader, hideLoader } from "./EmptyFolderContainerUtils";
import { FolderType, RoomSearchArea } from "@docspace/common/constants";
import { getCategoryUrl, getCategoryType } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
const EmptyFolderContainer = ({
t,
onCreate,
fetchFiles,
fetchRooms,
setIsLoading,
parentId,
linkStyles,
isRooms,
editAccess,
sectionWidth,
canCreateFiles,
canInviteUsers,
onClickInviteUsers,
folderId,
tReady,
isLoadedFetchFiles,
viewAs,
setIsLoadedEmptyPage,
theme,
navigationPath,
rootFolderType,
roomType,
isLoading,
}) => {
const navigate = useNavigate();
const location = useLocation();
const isRoom =
isLoading && location?.state?.isRoom ? location?.state?.isRoom : !!roomType;
const canInviteUsers = isRoom && editAccess;
const onBackToParentFolder = () => {
setIsLoading(true);
isRooms
? fetchRooms(parentId).finally(() => setIsLoading(false))
: fetchFiles(parentId).finally(() => setIsLoading(false));
if (isRoom) {
const path =
rootFolderType === FolderType.Archive
? getCategoryUrl(CategoryType.Archive)
: getCategoryUrl(CategoryType.Shared);
const newFilter = RoomsFilter.getDefault();
newFilter.searchArea =
rootFolderType === FolderType.Archive
? RoomSearchArea.Archive
: RoomSearchArea.Active;
const state = {
title: navigationPath[0].title,
isRoot: true,
rootFolderType,
};
navigate(`${path}?${newFilter.toUrlParams()}`, {
state,
});
} else {
const categoryType = getCategoryType(location);
const newFilter = FilesFilter.getDefault();
newFilter.folder = parentId;
const parentIdx = navigationPath.findIndex((v) => v.id === parentId);
const parentItem = navigationPath[parentIdx];
const state = {
title: parentItem.title,
isRoot: navigationPath.length === 1,
rootFolderType,
};
const path = getCategoryUrl(categoryType, parentId);
navigate(`${path}?${newFilter.toUrlParams()}`, {
state,
});
}
};
useEffect(() => {
if (isLoadedFetchFiles && tReady) {
setIsLoadedEmptyPage(true);
} else {
setIsLoadedEmptyPage(false);
}
}, [isLoadedFetchFiles, tReady]);
useEffect(() => {
return () => {
setIsLoadedEmptyPage(false);
};
}, []);
const onInviteUsersClick = () => {
if (!isRooms) return;
if (!isRoom) return;
onClickInviteUsers && onClickInviteUsers(folderId);
};
@ -100,7 +142,7 @@ const EmptyFolderContainer = ({
</Link>
</div>
{isRooms ? (
{isRoom ? (
canInviteUsers ? (
<>
<div className="empty-folder_container-links second-description">
@ -147,31 +189,16 @@ const EmptyFolderContainer = ({
? EmptyScreenAltSvgUrl
: EmptyScreenAltSvgDarkUrl;
useEffect(
() => (!isLoadedFetchFiles || !tReady ? showLoader() : hideLoader()),
[isLoadedFetchFiles, tReady]
);
if (!isLoadedFetchFiles || !tReady) {
return (
<Loaders.EmptyContainerLoader
style={{ display: "none", marginTop: 32 }}
id="empty-container-loader"
viewAs={viewAs}
/>
);
}
return (
<EmptyContainer
headerText={isRooms ? t("RoomCreated") : t("EmptyScreenFolder")}
headerText={isRoom ? t("RoomCreated") : t("EmptyScreenFolder")}
style={{ gridColumnGap: "39px", marginTop: 32 }}
descriptionText={
canCreateFiles
? t("EmptyFolderDecription")
: t("EmptyFolderDescriptionUser")
}
imageSrc={isRooms ? emptyScreenCorporateSvg : emptyScreenAltSvg}
imageSrc={isRoom ? emptyScreenCorporateSvg : emptyScreenAltSvg}
buttons={buttons}
sectionWidth={sectionWidth}
isEmptyFolderContainer={true}
@ -183,25 +210,20 @@ export default inject(
({
auth,
accessRightsStore,
filesStore,
selectedFolderStore,
contextOptionsStore,
clientLoadingStore,
}) => {
const {
fetchFiles,
fetchRooms,
isLoadedFetchFiles,
viewAs,
setIsLoadedEmptyPage,
} = filesStore;
const {
navigationPath,
parentId,
access,
id: folderId,
roomType,
security,
rootFolderType,
roomType,
} = selectedFolderStore;
let id;
@ -210,28 +232,30 @@ export default inject(
id = elem.id;
}
const isRooms = !!roomType;
const { canCreateFiles } = accessRightsStore;
const { onClickInviteUsers } = contextOptionsStore;
const canInviteUsers = isRooms && security?.EditAccess; // skip sub-folders
const { setIsSectionFilterLoading, isLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
return {
fetchFiles,
fetchRooms,
setIsLoading: filesStore.setIsLoading,
setIsLoading,
isLoading,
parentId: id ?? parentId,
isRooms,
roomType,
canCreateFiles,
canInviteUsers,
navigationPath,
rootFolderType,
editAccess: security?.EditAccess,
onClickInviteUsers,
folderId,
isLoadedFetchFiles,
viewAs,
setIsLoadedEmptyPage,
theme: auth.settingsStore.theme,
};
}

View File

@ -12,15 +12,14 @@ import Link from "@docspace/components/link";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
const RoomNoAccessContainer = (props) => {
const {
t,
setIsLoading,
linkStyles,
fetchRooms,
setAlreadyFetchingRooms,
categoryType,
isEmptyPage,
sectionWidth,
theme,
@ -39,22 +38,13 @@ const RoomNoAccessContainer = (props) => {
const onGoToShared = () => {
setIsLoading(true);
setAlreadyFetchingRooms(true);
fetchRooms(null, null)
.then(() => {
const filter = RoomsFilter.getDefault();
const filter = RoomsFilter.getDefault();
const filterParamsStr = filter.toUrlParams();
const filterParamsStr = filter.toUrlParams();
const url = getCategoryUrl(categoryType, filter.folder);
const path = getCategoryUrl(CategoryType.Shared);
const pathname = `${url}?${filterParamsStr}`;
navigate(pathname);
})
.finally(() => {
setIsLoading(false);
});
navigate(`${path}?${filterParamsStr}`);
};
const goToButtons = (
@ -91,19 +81,16 @@ const RoomNoAccessContainer = (props) => {
);
};
export default inject(({ auth, filesStore }) => {
const {
setIsLoading,
fetchRooms,
categoryType,
setAlreadyFetchingRooms,
isEmptyPage,
} = filesStore;
export default inject(({ auth, filesStore, clientLoadingStore }) => {
const { setIsSectionFilterLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const { isEmptyPage } = filesStore;
return {
setIsLoading,
fetchRooms,
categoryType,
setAlreadyFetchingRooms,
isEmptyPage,
theme: auth.settingsStore.theme,
};

View File

@ -3,20 +3,22 @@ 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 { useNavigate, useLocation } from "react-router-dom";
import styled from "styled-components";
import { FolderType } from "@docspace/common/constants";
import { FolderType, RoomSearchArea } from "@docspace/common/constants";
import { inject, observer } from "mobx-react";
import { withTranslation, Trans } from "react-i18next";
import EmptyContainer from "./EmptyContainer";
import Link from "@docspace/components/link";
import Text from "@docspace/components/text";
import Box from "@docspace/components/box";
import Loaders from "@docspace/common/components/Loaders";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { combineUrl } from "@docspace/common/utils";
import FilesFilter from "@docspace/common/api/files/filter";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import config from "PACKAGE_FILE";
import { CategoryType } from "SRC_DIR/helpers/constants";
import PlusIcon from "PUBLIC_DIR/images/plus.react.svg";
import EmptyScreenPersonalUrl from "PUBLIC_DIR/images/empty_screen_personal.svg?url";
import EmptyScreenPersonalDarkUrl from "PUBLIC_DIR/images/empty_screen_personal_dark.svg?url";
@ -54,27 +56,26 @@ const RootFolderContainer = (props) => {
onCreate,
onCreateRoom,
myFolderId,
filter,
fetchFiles,
setIsLoading,
rootFolderType,
linkStyles,
isLoading,
viewAs,
fetchRooms,
setAlreadyFetchingRooms,
categoryType,
isEmptyPage,
isVisitor,
isCollaborator,
sectionWidth,
setIsLoadedEmptyPage,
security,
myFolder,
roomsFolder,
} = props;
const personalDescription = t("EmptyFolderDecription");
const navigate = useNavigate();
const location = useLocation();
const emptyScreenHeader = t("EmptyScreenFolder");
const archiveHeader = t("ArchiveEmptyScreenHeader");
@ -103,45 +104,44 @@ const RootFolderContainer = (props) => {
const roomHeader = t("EmptyRootRoomHeader");
useEffect(() => {
return () => {
setIsLoadedEmptyPage(false);
};
}, []);
useEffect(() => {
setIsLoadedEmptyPage(!isLoading);
}, [isLoading]);
const onGoToPersonal = () => {
const newFilter = filter.clone();
const newFilter = FilesFilter.getDefault();
newFilter.folder = myFolderId;
const state = {
title: myFolder.title,
isRoot: true,
rootFolderType: myFolder.rootFolderType,
};
const path = getCategoryUrl(CategoryType.Personal);
setIsLoading(true);
fetchFiles(myFolderId, newFilter).finally(() => setIsLoading(false));
navigate(`${path}?${newFilter.toUrlParams()}`, { state });
};
const onGoToShared = () => {
const newFilter = RoomsFilter.getDefault();
newFilter.searchArea = RoomSearchArea.Active;
const state = {
title: roomsFolder.title,
isRoot: true,
rootFolderType: roomsFolder.rootFolderType,
};
setIsLoading(true);
setAlreadyFetchingRooms(true);
fetchRooms(null, null)
.then(() => {
const filter = RoomsFilter.getDefault();
const path = getCategoryUrl(CategoryType.Shared);
const filterParamsStr = filter.toUrlParams();
const url = getCategoryUrl(categoryType, filter.folder);
const pathname = `${url}?${filterParamsStr}`;
navigate(pathname);
})
.finally(() => {
setIsLoading(false);
});
navigate(`${path}?${newFilter.toUrlParams()}`, { state });
};
const getEmptyFolderProps = () => {
switch (rootFolderType) {
switch (rootFolderType || location?.state?.rootFolderType) {
case FolderType.USER:
return {
headerText: emptyScreenHeader,
@ -342,8 +342,6 @@ const RootFolderContainer = (props) => {
const headerText = isPrivacyFolder ? privateRoomHeader : title;
const emptyFolderProps = getEmptyFolderProps();
useEffect(() => (isLoading ? showLoader() : hideLoader()), [isLoading]);
// if (isLoading) {
// return (
// <Loaders.EmptyContainerLoader
@ -355,37 +353,45 @@ const RootFolderContainer = (props) => {
// }
return (
<EmptyContainer
headerText={headerText}
isEmptyPage={isEmptyPage}
sectionWidth={sectionWidth}
style={{ marginTop: 32 }}
{...emptyFolderProps}
/>
emptyFolderProps && (
<EmptyContainer
headerText={headerText}
isEmptyPage={isEmptyPage}
sectionWidth={sectionWidth}
style={{ marginTop: 32 }}
{...emptyFolderProps}
/>
)
);
};
export default inject(
({ auth, filesStore, treeFoldersStore, selectedFolderStore }) => {
({
auth,
filesStore,
treeFoldersStore,
selectedFolderStore,
clientLoadingStore,
}) => {
const { isDesktopClient, isEncryptionSupport, organizationName, theme } =
auth.settingsStore;
const { setIsSectionFilterLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const {
filter,
fetchFiles,
privacyInstructions,
isLoading,
setIsLoading,
viewAs,
fetchRooms,
categoryType,
setAlreadyFetchingRooms,
isEmptyPage,
setIsLoadedEmptyPage,
privacyInstructions,
isEmptyPage,
} = filesStore;
const { title, rootFolderType, security } = selectedFolderStore;
const { isPrivacyFolder, myFolderId } = treeFoldersStore;
const { isPrivacyFolder, myFolderId, myFolder, roomsFolder } =
treeFoldersStore;
return {
theme,
@ -399,18 +405,16 @@ export default inject(
title,
myFolderId,
filter,
fetchFiles,
isLoading,
setIsLoading,
rootFolderType,
viewAs,
fetchRooms,
categoryType,
setAlreadyFetchingRooms,
isEmptyPage,
setIsLoadedEmptyPage,
security,
myFolder,
roomsFolder,
};
}
)(withTranslation(["Files"])(observer(RootFolderContainer)));

View File

@ -1,5 +1,7 @@
import React from "react";
import { observer, inject } from "mobx-react";
import { useLocation } from "react-router-dom";
import RootFolderContainer from "./RootFolderContainer";
import EmptyFilterContainer from "./EmptyFilterContainer";
import EmptyFolderContainer from "./EmptyFolderContainer";
@ -18,14 +20,17 @@ const linkStyles = {
const EmptyContainer = ({
isFiltered,
isLoading,
parentId,
theme,
setCreateRoomDialogVisible,
sectionWidth,
isRoomNotFoundOrMoved,
isGracePeriod,
setInviteUsersWarningDialogVisible,
}) => {
const location = useLocation();
linkStyles.color = theme.filesEmptyContainer.linkColor;
const onCreate = (e) => {
@ -61,9 +66,12 @@ const EmptyContainer = ({
);
}
const isRootEmptyPage =
isLoading && location?.state ? location.state?.isRoot : parentId === 0;
return isFiltered ? (
<EmptyFilterContainer linkStyles={linkStyles} />
) : parentId === 0 ? (
) : isRootEmptyPage ? (
<RootFolderContainer
onCreate={onCreate}
linkStyles={linkStyles}
@ -86,13 +94,14 @@ export default inject(
dialogsStore,
selectedFolderStore,
clientLoadingStore,
}) => {
const { isErrorRoomNotAvailable, isFiltered } = filesStore;
const { isLoading } = clientLoadingStore;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { setCreateRoomDialogVisible, setInviteUsersWarningDialogVisible } =
dialogsStore;
const { setInviteUsersWarningDialogVisible } = dialogsStore;
const isRoomNotFoundOrMoved =
isFiltered === null &&
@ -102,7 +111,7 @@ export default inject(
return {
theme: auth.settingsStore.theme,
isFiltered,
setCreateRoomDialogVisible,
isLoading,
parentId: selectedFolderStore.parentId,
isRoomNotFoundOrMoved,

View File

@ -86,13 +86,16 @@ FolderTreeBody.defaultProps = {
};
export default inject(
({ filesStore, treeFoldersStore, selectedFolderStore }) => {
const { filter, isLoading } = filesStore;
const {
expandedPanelKeys,
isLoadingNodes,
setIsLoadingNodes,
} = treeFoldersStore;
({
filesStore,
treeFoldersStore,
selectedFolderStore,
clientLoadingStore,
}) => {
const { filter } = filesStore;
const { isLoading } = clientLoadingStore;
const { expandedPanelKeys, isLoadingNodes, setIsLoadingNodes } =
treeFoldersStore;
const expandedKeysProp = expandedPanelKeys
? expandedPanelKeys
: selectedFolderStore.pathParts;

View File

@ -301,9 +301,15 @@ export default inject(
dialogsStore,
oformsStore,
settingsStore,
clientLoadingStore,
}) => {
const { setIsSectionBodyLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionBodyLoading(param);
};
const {
setIsLoading,
createFile,
createFolder,
addActiveItems,

View File

@ -79,9 +79,8 @@ const CreateRoomEvent = ({
export default inject(
({
auth,
createEditRoomStore,
filesStore,
tagsStore,
dialogsStore,
settingsStore,

View File

@ -10,7 +10,6 @@ const RenameEvent = ({
item,
onClose,
setIsLoading,
addActiveItems,
updateFile,
@ -135,8 +134,7 @@ export default inject(
uploadDataStore,
dialogsStore,
}) => {
const { setIsLoading, addActiveItems, updateFile, renameFolder } =
filesStore;
const { addActiveItems, updateFile, renameFolder } = filesStore;
const { id, setSelectedFolder } = selectedFolderStore;
@ -146,7 +144,6 @@ export default inject(
const { setEventDialogVisible, eventDialogVisible } = dialogsStore;
return {
setIsLoading,
addActiveItems,
updateFile,
renameFolder,

View File

@ -61,15 +61,16 @@ const MainBar = ({
);
};
export default inject(({ auth, filesStore }) => {
export default inject(({ auth, clientLoadingStore, filesStore }) => {
const { currentTariffStatusStore, settingsStore } = auth;
const { checkedMaintenance, setMaintenanceExist, snackbarExist } =
settingsStore;
const { isNotPaidPeriod } = currentTariffStatusStore;
const { firstLoad } = filesStore;
const { firstLoad } = clientLoadingStore;
const { isInit } = filesStore;
return {
firstLoad,
firstLoad: firstLoad && isInit,
checkedMaintenance,
snackbarExist,
setMaintenanceExist,

View File

@ -4,6 +4,8 @@ import Button from "@docspace/components/button";
import { withTranslation } from "react-i18next";
import toastr from "@docspace/components/toast/toastr";
import { inject, observer } from "mobx-react";
import { useNavigate, useLocation } from "react-router-dom";
import FilesFilter from "@docspace/common/api/files/filter";
const DeleteThirdPartyDialog = (props) => {
const {
@ -12,8 +14,9 @@ const DeleteThirdPartyDialog = (props) => {
visible,
providers,
removeItem,
fetchFiles,
currentFolderId,
deleteThirdParty,
setThirdPartyProviders,
setDeleteThirdPartyDialogVisible,
@ -23,6 +26,9 @@ const DeleteThirdPartyDialog = (props) => {
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const location = useLocation();
const onClose = () => setDeleteThirdPartyDialogVisible(false);
const onDeleteThirdParty = () => {
@ -46,8 +52,13 @@ const DeleteThirdPartyDialog = (props) => {
deleteThirdParty(+removeItem.id)
.then(() => {
setThirdPartyProviders(newProviders);
if (currentFolderId) fetchFiles(currentFolderId, null, true, true);
else {
if (currentFolderId) {
const filter = FilesFilter.getDefault();
filter.folder = currentFolderId;
navigate(`${location.pathname}?${filter.toUrlParams()}`);
} else {
toastr.success(
t("SuccessDeleteThirdParty", { service: removeItem.title })
);
@ -105,7 +116,7 @@ export default inject(
}) => {
const { providers, setThirdPartyProviders, deleteThirdParty } =
settingsStore.thirdPartyStore;
const { fetchFiles } = filesStore;
const { setIsLoading } = filesStore;
const { selectedThirdPartyAccount: backupConnectionItem } = backup;
const {
deleteThirdPartyDialogVisible: visible,
@ -115,13 +126,17 @@ export default inject(
const removeItem = backupConnectionItem ?? storeItem;
const { id } = selectedFolderStore;
return {
currentFolderId: selectedFolderStore.id,
currentFolderId: id,
setIsLoadingStore: setIsLoading,
providers,
visible,
removeItem,
fetchFiles,
setThirdPartyProviders,
deleteThirdParty,
setDeleteThirdPartyDialogVisible,

View File

@ -130,30 +130,31 @@ const ChangeOwnerPanel = withTranslation(["ChangeOwnerPanel", "Common"])(
withLoader(ChangeOwnerComponent)(<Loaders.DialogAsideLoader isPanel />)
);
export default inject(({ auth, filesStore, dialogsStore }) => {
const {
selection,
bufferSelection,
setFile,
setFolder,
setFilesOwner,
setIsLoading,
isLoading,
setBufferSelection,
} = filesStore;
const { ownerPanelVisible, setChangeOwnerPanelVisible } = dialogsStore;
export default inject(
({ auth, filesStore, dialogsStore, clientLoadingStore }) => {
const {
selection,
bufferSelection,
setFile,
setFolder,
setFilesOwner,
return {
theme: auth.settingsStore.theme,
selection: selection.length ? selection : [bufferSelection],
isLoading,
visible: ownerPanelVisible,
setBufferSelection,
} = filesStore;
const { ownerPanelVisible, setChangeOwnerPanelVisible } = dialogsStore;
setFile,
setFolder,
setIsLoading,
setChangeOwnerPanelVisible,
setFilesOwner,
setBufferSelection,
};
})(observer(ChangeOwnerPanel));
return {
theme: auth.settingsStore.theme,
selection: selection.length ? selection : [bufferSelection],
isLoading: clientLoadingStore.isLoading,
visible: ownerPanelVisible,
setFile,
setFolder,
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
setChangeOwnerPanelVisible,
setFilesOwner,
setBufferSelection,
};
}
)(observer(ChangeOwnerPanel));

View File

@ -23,6 +23,11 @@ import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import Loaders from "@docspace/common/components/Loaders";
import withLoader from "../../../HOCs/withLoader";
import {
getCategoryTypeByFolderType,
getCategoryUrl,
} from "SRC_DIR/helpers/utils";
import FilesFilter from "@docspace/common/api/files/filter";
const SharingBodyStyle = { height: `calc(100vh - 156px)` };
@ -81,8 +86,9 @@ class NewFilesPanel extends React.Component {
})
.catch((err) => toastr.error(err))
.finally(() => {
this.setState({ inProgress: false });
this.onClose();
this.setState({ inProgress: false }, () => {
this.onClose();
});
});
};
@ -123,21 +129,42 @@ class NewFilesPanel extends React.Component {
};
onFileClick = (item) => {
const { id, fileExst, webUrl, fileType, providerKey } = item;
const {
filter,
id,
fileExst,
webUrl,
fileType,
providerKey,
rootFolderType,
title,
} = item;
const {
setMediaViewerData,
fetchFiles,
addFileToRecentlyViewed,
playlist,
setCurrentItem,
currentFolderId,
setIsLoading,
} = this.props;
if (!fileExst) {
fetchFiles(id, filter)
.catch((err) => toastr.error(err))
.finally(() => this.onClose());
const categoryType = getCategoryTypeByFolderType(rootFolderType, id);
const state = { title, rootFolderType, isRoot: false };
setIsLoading(true);
const url = getCategoryUrl(categoryType, id);
const filter = FilesFilter.getDefault();
filter.folder = id;
window.DocSpace.navigate(`${url}?${filter.toUrlParams()}`, { state });
this.setState({ inProgress: false }, () => {
this.onClose();
});
} else {
const canEdit = [5, 6, 7].includes(fileType); //TODO: maybe dirty
@ -165,13 +192,32 @@ class NewFilesPanel extends React.Component {
if (isMedia) {
if (currentFolderId !== item.folderId) {
fetchFiles(item.folderId, null)
.then(() => {
const mediaItem = { visible: true, id };
setMediaViewerData(mediaItem);
})
.catch((err) => toastr.error(err))
.finally(() => this.onClose());
const categoryType = getCategoryTypeByFolderType(
rootFolderType,
item.folderId
);
const state = {
title: "",
rootFolderType,
isRoot: false,
};
setIsLoading(true);
const url = getCategoryUrl(categoryType, item.folderId);
const filter = FilesFilter.getDefault();
filter.folder = id;
window.DocSpace.navigate(`${url}?${filter.toUrlParams()}`, { state });
const mediaItem = { visible: true, id };
setMediaViewerData(mediaItem);
this.setState({ inProgress: false }, () => {
this.onClose();
});
} else {
const mediaItem = { visible: true, id };
setMediaViewerData(mediaItem);
@ -316,17 +362,18 @@ export default inject(
settingsStore,
}) => {
const {
fetchFiles,
filter,
addFileToRecentlyViewed,
//setIsLoading,
isLoading,
//updateFilesBadge,
//updateFolderBadge,
//updateFoldersBadge,
hasNew,
refreshFiles,
} = filesStore;
const { setIsSectionFilterLoading, isLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
//const { updateRootBadge } = treeFoldersStore;
const { playlist, setMediaViewerData, setCurrentItem } =
mediaViewerDataStore;
@ -342,7 +389,6 @@ export default inject(
} = dialogsStore;
return {
filter,
pathParts,
visible,
newFiles,
@ -353,22 +399,18 @@ export default inject(
setCurrentItem,
currentFolderId,
//setIsLoading,
fetchFiles,
setMediaViewerData,
addFileToRecentlyViewed,
getIcon,
getFolderIcon,
markAsRead,
setNewFilesPanelVisible,
// updateRootBadge,
// updateFolderBadge,
// updateFoldersBadge,
// updateFilesBadge,
theme: auth.settingsStore.theme,
hasNew,
refreshFiles,
setIsLoading,
};
}
)(

View File

@ -11,12 +11,8 @@ class SelectFileInput extends React.PureComponent {
}
componentWillUnmount() {
const {
setExpandedPanelKeys,
setFolderId,
setFile,
onSelectFile,
} = this.props;
const { setExpandedPanelKeys, setFolderId, setFile, onSelectFile } =
this.props;
setExpandedPanelKeys(null);
setFolderId(null);
@ -75,8 +71,8 @@ SelectFileInput.defaultProps = {
};
export default inject(
({ filesStore, treeFoldersStore, selectFileDialogStore }) => {
const { setFirstLoad } = filesStore;
({ clientLoadingStore, treeFoldersStore, selectFileDialogStore }) => {
const { setFirstLoad } = clientLoadingStore;
const { folderId, setFolderId, setFile, fileInfo } = selectFileDialogStore;
const fileName = fileInfo?.title;
const { setExpandedPanelKeys } = treeFoldersStore;

View File

@ -199,14 +199,14 @@ SelectFolderInput.defaultProps = {
export default inject(
({
filesStore,
clientLoadingStore,
treeFoldersStore,
selectFolderDialogStore,
selectedFolderStore,
backup,
}) => {
const { clearLocalStorage } = backup;
const { setFirstLoad } = filesStore;
const { setFirstLoad } = clientLoadingStore;
const { setExpandedPanelKeys } = treeFoldersStore;
const {
isLoading,

View File

@ -99,9 +99,9 @@ VersionHistoryPanel.propTypes = {
fileId: PropTypes.string,
};
export default inject(({ auth, filesStore, versionHistoryStore }) => {
export default inject(({ auth, clientLoadingStore, versionHistoryStore }) => {
const { isTabletView } = auth.settingsStore;
const { isLoading } = filesStore;
const { isLoading } = clientLoadingStore;
const {
fileId,
versions,

View File

@ -176,7 +176,7 @@ export const getCategoryUrl = (categoryType, folderId = null) => {
return "/rooms/archived/filter";
case CategoryType.ArchivedRoom:
return "/rooms/archived/${folderId}/filter";
return `/rooms/archived/${folderId}/filter`;
case CategoryType.Favorite:
return "/files/favorite/filter";
@ -187,6 +187,12 @@ export const getCategoryUrl = (categoryType, folderId = null) => {
case CategoryType.Trash:
return "/files/trash/filter";
case CategoryType.Accounts:
return "/accounts/filter";
case CategoryType.Settings:
return "/settings/common";
default:
throw new Error("Unknown category type");
}

View File

@ -0,0 +1,5 @@
export { default as useFiles } from "./useFiles";
export { default as useSDK } from "./useSDK";
export { default as useOperations } from "./useOperations";
export { default as useAccounts } from "./useAccounts";
export { default as useSettings } from "./useSettings";

View File

@ -0,0 +1,37 @@
import React from "react";
import AccountsFilter from "@docspace/common/api/people/filter";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
const useAccounts = ({
t,
isAccountsPage,
location,
setIsLoading,
setSelectedNode,
fetchPeople,
setPortalTariff,
}) => {
React.useEffect(() => {
if (!isAccountsPage) return;
setIsLoading(true);
setSelectedNode(["accounts", "filter"]);
const newFilter = AccountsFilter.getFilter(location);
setDocumentTitle(t("Common:Accounts"));
fetchPeople(newFilter, true)
.catch((err) => {
if (err?.response?.status === 402) setPortalTariff();
})
.finally(() => {
setIsLoading(false);
});
}, [isAccountsPage, location.pathname, location.search]);
};
export default useAccounts;

View File

@ -0,0 +1,272 @@
import React from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import FilesFilter from "@docspace/common/api/files/filter";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import { getGroup } from "@docspace/common/api/groups";
import { getUserById } from "@docspace/common/api/people";
import { Events, RoomSearchArea } from "@docspace/common/constants";
import { getObjectByLocation } from "@docspace/common/utils";
import { getCategoryType, getCategoryUrl } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
const useFiles = ({
t,
dragging,
setDragging,
disableDrag,
uploadEmptyFolders,
startUpload,
fetchFiles,
fetchRooms,
setIsLoading,
isAccountsPage,
isSettingsPage,
location,
playlist,
getFileInfo,
setToPreviewFile,
setIsPreview,
setIsUpdatingRowItem,
gallerySelected,
removeFirstUrl,
}) => {
const navigate = useNavigate();
const fetchDefaultFiles = () => {
const filter = FilesFilter.getDefault();
const url = getCategoryUrl(CategoryType.personal);
navigate(`${url}?${filter.toUrlParams()}`);
};
const fetchDefaultRooms = () => {
const filter = RoomsFilter.getDefault();
const categoryType = getCategoryType(location);
const url = getCategoryUrl(categoryType);
filter.searchArea =
categoryType === CategoryType.Shared
? RoomSearchArea.Active
: RoomSearchArea.Archive;
navigate(`${url}?${filter.toUrlParams()}`);
};
const onDrop = (files, uploadToFolder) => {
dragging && setDragging(false);
if (disableDrag) return;
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
if (emptyFolders.length > 0) {
uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => {
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t);
});
} else {
startUpload(files, uploadToFolder, t);
}
};
React.useEffect(() => {
if (isAccountsPage || isSettingsPage) return;
setIsLoading(true);
if (!window.location.href.includes("#preview")) {
// localStorage.removeItem("isFirstUrl");
// Media viewer
removeFirstUrl();
}
const categoryType = getCategoryType(location);
let filterObj = null;
let isRooms = false;
if (window.location.href.indexOf("/#preview") > 1 && playlist.length < 1) {
const pathname = window.location.href;
const fileId = pathname.slice(pathname.indexOf("#preview") + 9);
setTimeout(() => {
getFileInfo(fileId)
.then((data) => {
const canOpenPlayer =
data.viewAccessability.ImageView ||
data.viewAccessability.MediaView;
const file = { ...data, canOpenPlayer };
setToPreviewFile(file, true);
setIsPreview(true);
})
.catch((err) => {
toastr.error(err);
fetchDefaultFiles();
});
}, 1);
return setIsLoading(false);
}
if (window.location.href.indexOf("/#preview") > 1)
return setIsLoading(false);
const isRoomFolder = getObjectByLocation(window.location)?.folder;
if (
(categoryType == CategoryType.Shared ||
categoryType == CategoryType.SharedRoom ||
categoryType == CategoryType.Archive) &&
!isRoomFolder
) {
filterObj = RoomsFilter.getFilter(window.location);
isRooms = true;
if (!filterObj) {
fetchDefaultRooms();
return;
}
} else {
filterObj = FilesFilter.getFilter(window.location);
if (!filterObj) {
fetchDefaultFiles();
return;
}
}
if (!filterObj) return;
let dataObj = { filter: filterObj };
if (filterObj && filterObj.authorType) {
const authorType = filterObj.authorType;
const indexOfUnderscore = authorType.indexOf("_");
const type = authorType.slice(0, indexOfUnderscore);
const itemId = authorType.slice(indexOfUnderscore + 1);
if (itemId) {
dataObj = {
type,
itemId,
filter: filterObj,
};
} else {
filterObj.authorType = null;
dataObj = { filter: filterObj };
}
}
if (filterObj && filterObj.subjectId) {
const type = "user";
const itemId = filterObj.subjectId;
if (itemId) {
dataObj = {
type,
itemId,
filter: filterObj,
};
} else {
filterObj.subjectId = null;
dataObj = { filter: filterObj };
}
}
if (!dataObj) return;
const { filter, itemId, type } = dataObj;
const newFilter = filter
? filter.clone()
: isRooms
? RoomsFilter.getDefault()
: FilesFilter.getDefault();
const requests = [Promise.resolve(newFilter)];
if (type === "group") {
requests.push(getGroup(itemId));
} else if (type === "user") {
requests.push(getUserById(itemId));
}
axios
.all(requests)
.catch((err) => {
if (isRooms) {
Promise.resolve(RoomsFilter.getDefault());
} else {
Promise.resolve(FilesFilter.getDefault());
}
//console.warn("Filter restored by default", err);
})
.then((data) => {
const filter = data[0];
const result = data[1];
if (result) {
const type = result.displayName ? "user" : "group";
const selectedItem = {
key: result.id,
label: type === "user" ? result.displayName : result.name,
type,
};
if (!isRooms) {
filter.selectedItem = selectedItem;
}
}
if (filter) {
if (isRooms) {
return fetchRooms(null, filter);
} else {
const folderId = filter.folder;
return fetchFiles(folderId, filter);
}
}
return Promise.resolve();
})
.then(() => {
if (gallerySelected) {
setIsUpdatingRowItem(false);
const event = new Event(Events.CREATE);
const payload = {
extension: "docxf",
id: -1,
fromTemplate: true,
title: gallerySelected.attributes.name_form,
};
event.payload = payload;
window.dispatchEvent(event);
}
})
.finally(() => {
setIsLoading(false);
});
}, [location.pathname, location.search, isAccountsPage, isSettingsPage]);
return { onDrop };
};
export default useFiles;

View File

@ -0,0 +1,110 @@
import React from "react";
import { Trans } from "react-i18next";
import toastr from "@docspace/components/toast/toastr";
const useOperations = ({
t,
setUploadPanelVisible,
primaryProgressDataVisible,
uploaded,
converted,
clearPrimaryProgressData,
isProgressFinished,
refreshFiles,
itemsSelectionTitle,
secondaryProgressDataStoreIcon,
itemsSelectionLength,
isAccountsPage,
isSettingsPage,
setItemsSelectionTitle,
}) => {
const prevProps = React.useRef({
isProgressFinished: isProgressFinished,
});
React.useEffect(() => {
if (
isProgressFinished &&
itemsSelectionTitle &&
isProgressFinished !== prevProps.current.isProgressFinished
) {
showOperationToast(
secondaryProgressDataStoreIcon,
itemsSelectionLength,
itemsSelectionTitle
);
setItemsSelectionTitle(null);
}
}, [
isProgressFinished,
itemsSelectionTitle,
showOperationToast,
setItemsSelectionTitle,
]);
React.useEffect(() => {
prevProps.current.isProgressFinished = isProgressFinished;
}, [isProgressFinished]);
const showUploadPanel = () => {
setUploadPanelVisible(true);
if (primaryProgressDataVisible && uploaded && converted)
clearPrimaryProgressData();
};
const showOperationToast = React.useCallback(
(type, qty, title) => {
switch (type) {
case "move":
if (qty > 1) {
return (
toastr.success(
<Trans t={t} i18nKey="MoveItems" ns="Files">
{{ qty }} elements has been moved
</Trans>
),
refreshFiles()
);
}
return (
toastr.success(
<Trans t={t} i18nKey="MoveItem" ns="Files">
{{ title }} moved
</Trans>
),
refreshFiles()
);
case "duplicate":
if (qty > 1) {
return (
toastr.success(
<Trans t={t} i18nKey="CopyItems" ns="Files">
{{ qty }} elements copied
</Trans>
),
refreshFiles()
);
}
return (
toastr.success(
<Trans t={t} i18nKey="CopyItem" ns="Files">
{{ title }} copied
</Trans>
),
refreshFiles()
);
default:
break;
}
},
[t]
);
return { showUploadPanel };
};
export default useOperations;

View File

@ -0,0 +1,124 @@
import React from "react";
import { Events } from "@docspace/common/constants";
import { frameCallbackData, frameCallCommand } from "@docspace/common/utils";
const useSDK = ({
frameConfig,
setFrameConfig,
selectedFolderStore,
folders,
files,
filesList,
selection,
user,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
}) => {
const handleMessage = async (e) => {
const eventData = typeof e.data === "string" ? JSON.parse(e.data) : e.data;
if (eventData.data) {
const { data, methodName } = eventData.data;
let res;
switch (methodName) {
case "setConfig":
res = await setFrameConfig(data);
break;
case "getFolderInfo":
res = selectedFolderStore;
break;
case "getFolders":
res = folders;
break;
case "getFiles":
res = files;
break;
case "getList":
res = filesList;
break;
case "getSelection":
res = selection;
break;
case "getUserInfo":
res = user;
break;
case "openModal": {
const { type, options } = data;
if (type === "CreateFile" || type === "CreateFolder") {
const item = new Event(Events.CREATE);
const payload = {
extension: options,
id: -1,
};
item.payload = payload;
window.dispatchEvent(item);
}
if (type === "CreateRoom") {
const room = new Event(Events.ROOM_CREATE);
window.dispatchEvent(room);
}
break;
}
case "createFile":
{
const { folderId, title, templateId, formId } = data;
res = await createFile(folderId, title, templateId, formId);
refreshFiles();
}
break;
case "createFolder":
{
const { parentFolderId, title } = data;
res = await createFolder(parentFolderId, title);
refreshFiles();
}
break;
case "createRoom":
{
const { title, type } = data;
res = await createRoom(title, type);
refreshFiles();
}
break;
case "setListView":
{
setViewAs(data);
}
break;
default:
res = "Wrong method";
}
frameCallbackData(res);
}
};
if (window.parent && !frameConfig) {
frameCallCommand("setConfig");
}
React.useEffect(() => {
window.addEventListener("message", handleMessage, false);
return () => {
window.removeEventListener("message", handleMessage, false);
};
}, []);
};
export default useSDK;

View File

@ -0,0 +1,15 @@
import React from "react";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
const useSettings = ({ t, isSettingsPage, setIsLoading }) => {
React.useEffect(() => {
if (!isSettingsPage) return;
setDocumentTitle(t("Common:Settings"));
setIsLoading(false);
}, [isSettingsPage]);
};
export default useSettings;

View File

@ -22,18 +22,18 @@ const FilesMediaViewer = (props) => {
previewFile,
fetchFiles,
setIsLoading,
setFirstLoad,
setToPreviewFile,
setScrollToItem,
setCurrentId,
setAlreadyFetchingRooms,
setBufferSelection,
isFavoritesFolder,
archiveRoomsId,
onClickFavorite,
onShowInfoPanel,
onClickDownload,
onClickDownloadAs,
onClickLinkEdit,
onPreviewClick,
onCopyLink,
@ -55,6 +55,7 @@ const FilesMediaViewer = (props) => {
setSelection,
activeFiles,
activeFolders,
onClickDownloadAs,
} = props;
const navigate = useNavigate();
@ -80,8 +81,6 @@ const FilesMediaViewer = (props) => {
// fetch file after preview with
fetchFiles(previewFile.folderId).finally(() => {
setIsLoading(false);
setFirstLoad(false);
setAlreadyFetchingRooms(false);
});
}
}, [previewFile]);
@ -181,8 +180,6 @@ const FilesMediaViewer = (props) => {
return;
}
console.log(url);
const targetFile = files.find((item) => item.id === currentMediaFileId);
if (targetFile) setBufferSelection(targetFile);
@ -238,14 +235,23 @@ export default inject(
dialogsStore,
treeFoldersStore,
contextOptionsStore,
clientLoadingStore,
}) => {
const {
firstLoad,
setIsSectionFilterLoading,
} = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const {
files,
userAccess,
fetchFiles,
setIsLoading,
firstLoad,
setFirstLoad,
setScrollToItem,
setBufferSelection,
setIsPreview,
@ -307,7 +313,7 @@ export default inject(
previewFile,
setIsLoading,
firstLoad,
setFirstLoad,
setToPreviewFile,
setIsPreview,
resetUrl,

View File

@ -2,6 +2,7 @@ import React from "react";
import { inject, observer } from "mobx-react";
import styled from "styled-components";
import { withTranslation } from "react-i18next";
import { useNavigate, useLocation } from "react-router-dom";
import { PaymentsType, AccountLoginType } from "@docspace/common/constants";
@ -44,21 +45,25 @@ const Badges = ({
withoutPaid,
isPaid = false,
filter,
getUsersList,
isSSO = false,
}) => {
const navigate = useNavigate();
const location = useLocation();
const onClickPaid = () => {
if (filter.payments === PaymentsType.Paid) return;
const newFilter = filter.clone();
newFilter.payments = PaymentsType.Paid;
getUsersList(newFilter, true);
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
const onClickSSO = () => {
if (filter.accountLoginType === AccountLoginType.SSO) return;
const newFilter = filter.clone();
newFilter.accountLoginType = AccountLoginType.SSO;
getUsersList(newFilter, true);
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
return (
@ -99,10 +104,9 @@ const Badges = ({
};
export default inject(({ peopleStore }) => {
const { filterStore, usersStore } = peopleStore;
const { filterStore } = peopleStore;
const { filter } = filterStore;
const { getUsersList } = usersStore;
return { filter, getUsersList };
return { filter };
})(withTranslation(["Common"])(observer(Badges)));

View File

@ -11,7 +11,7 @@ import Link from "@docspace/components/link";
import Box from "@docspace/components/box";
import Grid from "@docspace/components/grid";
const EmptyScreen = ({ resetFilter, isEmptyGroup, setIsLoading, theme }) => {
const EmptyScreen = ({ resetFilter, setIsLoading, theme }) => {
const { t } = useTranslation(["People", "Common"]);
const title = t("NotFoundUsers");
@ -19,7 +19,7 @@ const EmptyScreen = ({ resetFilter, isEmptyGroup, setIsLoading, theme }) => {
const onResetFilter = () => {
setIsLoading(true);
resetFilter().finally(() => setIsLoading(false));
resetFilter();
};
const imageSrc = theme.isBase
@ -68,13 +68,17 @@ const EmptyScreen = ({ resetFilter, isEmptyGroup, setIsLoading, theme }) => {
);
};
export default inject(({ auth, peopleStore, filesStore }) => {
const { resetFilter, selectedGroupStore } = peopleStore;
const { isEmptyGroup } = selectedGroupStore;
const { setIsLoading } = filesStore;
export default inject(({ auth, peopleStore, clientLoadingStore }) => {
const { resetFilter } = peopleStore;
const { setIsSectionBodyLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionBodyLoading(param);
};
return {
resetFilter,
isEmptyGroup,
setIsLoading,
theme: auth.settingsStore.theme,
};

View File

@ -8,6 +8,7 @@ import RowContainer from "@docspace/components/row-container";
import EmptyScreen from "../EmptyScreen";
import SimpleUserRow from "./SimpleUserRow";
import withLoader from "SRC_DIR/HOCs/withLoader";
const marginStyles = css`
margin-left: -24px;
@ -100,7 +101,6 @@ const PeopleRowContainer = ({
hasMoreAccounts,
filterTotal,
withPaging,
isLoading,
}) => {
useEffect(() => {
const width = window.innerWidth;
@ -123,8 +123,6 @@ const PeopleRowContainer = ({
}
}, [sectionWidth]);
if (isLoading) return <></>;
return peopleList.length !== 0 || !isFiltered ? (
<StyledRowContainer
className="people-row-container"
@ -162,8 +160,6 @@ export default inject(({ peopleStore, auth, filesStore }) => {
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
const { isLoading } = filesStore;
return {
peopleList,
accountsViewAs,
@ -171,7 +167,7 @@ export default inject(({ peopleStore, auth, filesStore }) => {
theme,
infoPanelVisible,
withPaging,
isLoading,
fetchMoreAccounts,
hasMoreAccounts,
filterTotal,

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef } from "react";
import styled, { css } from "styled-components";
import { inject, observer } from "mobx-react";
import { isMobile } from "react-device-detect";
import { useNavigate, useLocation } from "react-router-dom";
import TableContainer from "@docspace/components/table-container";
import TableBody from "@docspace/components/table-container/TableBody";
@ -103,7 +104,6 @@ const Table = ({
userId,
infoPanelVisible,
isLoading,
fetchMoreAccounts,
hasMoreAccounts,
filterTotal,
@ -113,6 +113,10 @@ const Table = ({
}) => {
const ref = useRef(null);
const [hideColumns, setHideColumns] = React.useState(false);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
const width = window.innerWidth;
@ -138,8 +142,6 @@ const Table = ({
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
// if (isLoading) return <></>;
return peopleList.length !== 0 || !isFiltered ? (
<StyledTableContainer useReactWindow={!withPaging} forwardedRef={ref}>
<TableHeader
@ -148,6 +150,8 @@ const Table = ({
sectionWidth={sectionWidth}
containerRef={ref}
setHideColumns={setHideColumns}
navigate={navigate}
location={location}
/>
<TableBody
infoPanelVisible={infoPanelVisible}
@ -198,8 +202,6 @@ export default inject(
const { canChangeUserType } = accessRightsStore;
const { isLoading } = filesStore;
return {
peopleList,
accountsViewAs,
@ -211,7 +213,7 @@ export default inject(
userId,
infoPanelVisible,
withPaging,
isLoading,
fetchMoreAccounts,
hasMoreAccounts,
filterTotal,

View File

@ -92,7 +92,7 @@ class PeopleTableHeader extends React.Component {
};
onFilter = (sortBy) => {
const { filter, setIsLoading, fetchPeople } = this.props;
const { filter, setIsLoading, navigate, location } = this.props;
const newFilter = filter.clone();
if (newFilter.sortBy === sortBy && sortBy !== "AZ") {
@ -118,18 +118,20 @@ class PeopleTableHeader extends React.Component {
}
setIsLoading(true);
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
onIconClick = () => {
const { filter, setIsLoading, fetchPeople } = this.props;
const { filter, setIsLoading, navigate, location } = this.props;
const newFilter = filter.clone();
newFilter.sortOrder =
newFilter.sortOrder === "ascending" ? "descending" : "ascending";
setIsLoading(true);
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
render() {
@ -170,20 +172,18 @@ class PeopleTableHeader extends React.Component {
}
}
export default inject(({ auth, peopleStore, filesStore }) => {
const { filterStore, usersStore } = peopleStore;
export default inject(({ auth, peopleStore, clientLoadingStore }) => {
const { filterStore } = peopleStore;
const { filter } = filterStore;
const { getUsersList } = usersStore;
const { setIsLoading } = filesStore;
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
const { withPaging } = auth.settingsStore;
return {
filter,
fetchPeople: getUsersList,
setIsLoading,
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
userId: auth.userStore.user.id,
infoPanelVisible,
withPaging,

View File

@ -2,6 +2,7 @@ import React, { useEffect, useRef, useCallback, useMemo } from "react";
import elementResizeDetectorMaker from "element-resize-detector";
import TableContainer from "@docspace/components/table-container";
import { inject, observer } from "mobx-react";
import { useNavigate, useLocation } from "react-router-dom";
import TableRow from "./TableRow";
import TableHeader from "./TableHeader";
import TableBody from "@docspace/components/table-container/TableBody";
@ -128,6 +129,9 @@ const Table = ({
const ref = useRef(null);
const tagRef = useRef(null);
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
const width = window.innerWidth;
@ -223,6 +227,8 @@ const Table = ({
containerRef={ref}
tagRef={onSetTagRef}
setHideColumns={setHideColumns}
navigate={navigate}
location={location}
/>
<TableBody

View File

@ -337,7 +337,7 @@ class FilesTableHeader extends React.Component {
};
onFilter = (sortBy) => {
const { filter, selectedFolderId, setIsLoading, fetchFiles } = this.props;
const { filter, setIsLoading } = this.props;
const newFilter = filter.clone();
if (newFilter.sortBy !== sortBy) {
@ -348,16 +348,14 @@ class FilesTableHeader extends React.Component {
}
setIsLoading(true);
fetchFiles(selectedFolderId, newFilter).finally(() => setIsLoading(false));
window.DocSpace.navigate(
`${window.DocSpace.location.pathname}?${newFilter.toUrlParams}`
);
};
onRoomsFilter = (sortBy) => {
const {
roomsFilter,
selectedFolderId,
setIsLoading,
fetchRooms,
} = this.props;
const { roomsFilter, setIsLoading, navigate, location } = this.props;
const newFilter = roomsFilter.clone();
if (newFilter.sortBy !== sortBy) {
@ -368,7 +366,8 @@ class FilesTableHeader extends React.Component {
}
setIsLoading(true);
fetchRooms(selectedFolderId, newFilter).finally(() => setIsLoading(false));
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
render() {
@ -423,26 +422,28 @@ class FilesTableHeader extends React.Component {
}
export default inject(
({ auth, filesStore, selectedFolderStore, treeFoldersStore, tableStore }) => {
({
auth,
filesStore,
selectedFolderStore,
treeFoldersStore,
tableStore,
clientLoadingStore,
}) => {
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
const {
isHeaderChecked,
setIsLoading,
filter,
fetchFiles,
canShare,
firstElemChecked,
headerBorder,
roomsFilter,
fetchRooms,
} = filesStore;
const {
isRecentFolder,
isRoomsFolder,
isArchiveFolder,
isTrashFolder,
} = treeFoldersStore;
const { isRecentFolder, isRoomsFolder, isArchiveFolder, isTrashFolder } =
treeFoldersStore;
const isRooms = isRoomsFolder || isArchiveFolder;
const withContent = canShare;
const sortingVisible = !isRecentFolder;
@ -484,11 +485,9 @@ export default inject(
withContent,
sortingVisible,
setIsLoading,
fetchFiles,
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
roomsFilter,
fetchRooms,
firstElemChecked,
headerBorder,

View File

@ -197,29 +197,32 @@ const InfiniteGrid = (props) => {
);
};
export default inject(({ filesStore, treeFoldersStore }) => {
const {
filesList,
hasMoreFiles,
filterTotal,
fetchMoreFiles,
getCountTilesInRow,
roomsFilterTotal,
isLoading,
} = filesStore;
export default inject(
({ filesStore, treeFoldersStore, clientLoadingStore }) => {
const {
filesList,
hasMoreFiles,
filterTotal,
fetchMoreFiles,
getCountTilesInRow,
roomsFilterTotal,
} = filesStore;
const { isRoomsFolder, isArchiveFolder } = treeFoldersStore;
const { showBodyLoader } = clientLoadingStore;
const filesLength = filesList.length;
const isRooms = isRoomsFolder || isArchiveFolder;
const { isRoomsFolder, isArchiveFolder } = treeFoldersStore;
return {
filesList,
hasMoreFiles,
filterTotal: isRooms ? roomsFilterTotal : filterTotal,
fetchMoreFiles,
filesLength,
getCountTilesInRow,
isLoading,
};
})(observer(InfiniteGrid));
const filesLength = filesList.length;
const isRooms = isRoomsFolder || isArchiveFolder;
return {
filesList,
hasMoreFiles,
filterTotal: isRooms ? roomsFilterTotal : filterTotal,
fetchMoreFiles,
filesLength,
getCountTilesInRow,
isLoading: showBodyLoader,
};
}
)(observer(InfiniteGrid));

View File

@ -278,15 +278,14 @@ TileContainer.defaultProps = {
export default inject(({ auth, filesStore, treeFoldersStore }) => {
const { personal } = auth.settingsStore;
const { fetchFiles, filter, setIsLoading } = filesStore;
const { filter } = filesStore;
const { isFavoritesFolder, isRecentFolder } = treeFoldersStore;
const isDesc = filter?.sortOrder === "desc";
return {
personal,
fetchFiles,
setIsLoading,
isFavoritesFolder,
isRecentFolder,
isDesc,

View File

@ -1,5 +1,6 @@
import React, { useEffect } from "react";
import { withTranslation } from "react-i18next";
import { useLocation } from "react-router-dom";
import { isMobile, isMobileOnly } from "react-device-detect";
import { observer, inject } from "mobx-react";
@ -40,6 +41,7 @@ const SectionBodyContent = (props) => {
filesList,
uploaded,
onClickBack,
movingInProgress,
} = props;
@ -123,7 +125,8 @@ const SectionBodyContent = (props) => {
!e.target.closest(".files-item") &&
!e.target.closest(".not-selectable") &&
!e.target.closest(".info-panel") &&
!e.target.closest(".table-container_group-menu")) ||
!e.target.closest(".table-container_group-menu") &&
!e.target.closest(".document-catalog")) ||
e.target.closest(".files-main-button") ||
e.target.closest(".add-button") ||
e.target.closest(".search-input-block")
@ -250,10 +253,12 @@ const SectionBodyContent = (props) => {
if (isEmptyFilesList && movingInProgress) return <></>;
const isEmptyPage = isEmptyFilesList;
return (
<Consumer>
{(context) =>
isEmptyFilesList ? (
isEmptyPage ? (
<>
<EmptyContainer sectionWidth={context.sectionWidth} />
</>
@ -303,6 +308,7 @@ export default inject(
scrollToItem,
setScrollToItem,
filesList,
movingInProgress,
} = filesStore;
return {
@ -333,6 +339,6 @@ export default inject(
}
)(
withTranslation(["Files", "Common", "Translations"])(
withHotkeys(observer(SectionBodyContent))
withHotkeys(withLoader(observer(SectionBodyContent))())
)
);

View File

@ -1,6 +1,6 @@
import React, { useCallback, useEffect } from "react";
import { inject, observer } from "mobx-react";
import { useLocation } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { isMobile, isMobileOnly } from "react-device-detect";
import { withTranslation } from "react-i18next";
import find from "lodash/find";
@ -11,6 +11,8 @@ import Loaders from "@docspace/common/components/Loaders";
import { withLayoutSize } from "@docspace/common/utils";
import { getUser } from "@docspace/common/api/people";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import AccountsFilter from "@docspace/common/api/people/filter";
import FilesFilter from "@docspace/common/api/files/filter";
import {
FilterGroups,
FilterKeys,
@ -27,7 +29,7 @@ import {
} from "@docspace/common/constants";
import { getDefaultRoomName } from "SRC_DIR/helpers/filesUtils";
import withLoader from "SRC_DIR/HOCs/withLoader";
import {
TableVersions,
SortByFieldName,
@ -37,7 +39,6 @@ import {
import ViewRowsReactSvgUrl from "PUBLIC_DIR/images/view-rows.react.svg?url";
import ViewTilesReactSvgUrl from "PUBLIC_DIR/images/view-tiles.react.svg?url";
import { showLoader, hideLoader } from "./FilterUtils";
import { getRoomInfo } from "@docspace/common/api/rooms";
const getAccountLoginType = (filterValues) => {
@ -226,29 +227,28 @@ const SectionFilterContent = ({
createThumbnails,
setViewAs,
setIsLoading,
selectedFolderId,
fetchFiles,
fetchRooms,
fetchTags,
infoPanelVisible,
isRooms,
isTrash,
userId,
isPersonalRoom,
setCurrentRoomsFilter,
providers,
isLoadedEmptyPage,
isEmptyPage,
clearSearch,
setClearSearch,
setMainButtonMobileVisible,
isArchiveFolder,
accountsViewAs,
groups,
fetchPeople,
accountsFilter,
showFilterLoader,
}) => {
const location = useLocation();
const navigate = useNavigate();
const isAccountsPage = location.pathname.includes("accounts");
@ -256,8 +256,8 @@ const SectionFilterContent = ({
const onFilter = React.useCallback(
(data) => {
setIsLoading(true);
if (isAccountsPage) {
setIsLoading(true);
const status = getStatus(data);
const role = getRole(data);
@ -290,7 +290,7 @@ const SectionFilterContent = ({
//console.log(newFilter);
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`accounts/filter?${newFilter.toUrlParams()}`);
} else if (isRooms) {
const type = getType(data) || null;
@ -301,13 +301,6 @@ const SectionFilterContent = ({
const providerType = getProviderType(data) || null;
const tags = getTags(data) || null;
// const withSubfolders =
// getFilterFolders(data) === FilterKeys.withSubfolders;
// const withContent = getFilterContent(data) === FilterKeys.withContent;
setIsLoading(true);
const newFilter = roomsFilter.clone();
newFilter.page = 0;
@ -342,12 +335,12 @@ const SectionFilterContent = ({
newFilter.withoutTags = false;
}
// newFilter.withSubfolders = withSubfolders;
// newFilter.searchInContent = withContent;
const path =
newFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
const filterType = getFilterType(data) || null;
@ -375,29 +368,25 @@ const SectionFilterContent = ({
withSubfolders === FilterKeys.excludeSubfolders ? "false" : "true";
newFilter.searchInContent = withContent === "true" ? "true" : null;
const path = location.pathname.split("/filter")[0];
if (isTrash) {
newFilter.roomId = roomId;
}
setIsLoading(true);
fetchFiles(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
},
[
isRooms,
isAccountsPage,
isTrash,
fetchFiles,
fetchRooms,
fetchPeople,
setIsLoading,
roomsFilter,
accountsFilter,
filter,
selectedFolderId,
isAccountsPage,
location.pathname,
]
);
@ -405,82 +394,78 @@ const SectionFilterContent = ({
if (isAccountsPage) {
return;
}
setIsLoading(true);
if (isRooms) {
const newFilter = RoomsFilter.getDefault();
newFilter.searchArea = roomsFilter.searchArea;
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
const path =
roomsFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
const newFilter = filter.clone();
newFilter.page = 0;
newFilter.filterValue = "";
setIsLoading(true);
const path = location.pathname.split("/filter")[0];
fetchFiles(selectedFolderId, newFilter).finally(() => {
setIsLoading(false);
});
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
}, [
isRooms,
setIsLoading,
fetchFiles,
fetchRooms,
selectedFolderId,
filter,
roomsFilter,
isAccountsPage,
location.pathname,
]);
const onSearch = React.useCallback(
(data = "") => {
setIsLoading(true);
if (isAccountsPage) {
const newFilter = accountsFilter.clone();
newFilter.page = 0;
newFilter.search = data;
setIsLoading(true);
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`accounts/filter?${newFilter.toUrlParams()}`);
} else if (isRooms) {
const newFilter = roomsFilter.clone();
newFilter.page = 0;
newFilter.filterValue = data;
setIsLoading(true);
const path =
newFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
const newFilter = filter.clone();
newFilter.page = 0;
newFilter.search = data;
setIsLoading(true);
const path = location.pathname.split("/filter")[0];
fetchFiles(selectedFolderId, newFilter).finally(() => {
setIsLoading(false);
});
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
},
[
isRooms,
isAccountsPage,
setIsLoading,
fetchFiles,
fetchRooms,
fetchPeople,
selectedFolderId,
filter,
roomsFilter,
accountsFilter,
location.pathname,
]
);
@ -501,29 +486,21 @@ const SectionFilterContent = ({
setIsLoading(true);
if (isAccountsPage) {
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`accounts/filter?${newFilter.toUrlParams()}`);
} else if (isRooms) {
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
const path =
newFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
fetchFiles(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
const path = location.pathname.split("/filter")[0];
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
},
[
isRooms,
isAccountsPage,
setIsLoading,
fetchFiles,
fetchRooms,
fetchPeople,
selectedFolderId,
filter,
roomsFilter,
accountsFilter,
]
[isRooms, isAccountsPage, setIsLoading, filter, roomsFilter, accountsFilter]
);
const onChangeViewAs = React.useCallback(
@ -1863,6 +1840,7 @@ const SectionFilterContent = ({
const removeSelectedItem = React.useCallback(
({ key, group }) => {
setIsLoading(true);
if (isAccountsPage) {
const newFilter = accountsFilter.clone();
newFilter.page = 0;
@ -1888,11 +1866,8 @@ const SectionFilterContent = ({
newFilter.accountLoginType = null;
}
setIsLoading(true);
fetchPeople(newFilter, true).finally(() => setIsLoading(false));
navigate(`accounts/filter?${newFilter.toUrlParams()}`);
} else if (isRooms) {
setIsLoading(true);
const newFilter = roomsFilter.clone();
if (group === FilterGroups.roomFilterProviderType) {
@ -1938,9 +1913,12 @@ const SectionFilterContent = ({
newFilter.page = 0;
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
const path =
newFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
const newFilter = filter.clone();
@ -1963,25 +1941,12 @@ const SectionFilterContent = ({
newFilter.page = 0;
setIsLoading(true);
const path = location.pathname.split("/filter")[0];
fetchFiles(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
},
[
isRooms,
isAccountsPage,
fetchFiles,
fetchRooms,
fetchPeople,
setIsLoading,
roomsFilter,
filter,
accountsFilter,
selectedFolderId,
]
[isRooms, isAccountsPage, setIsLoading, roomsFilter, filter, accountsFilter]
);
const onSortButtonClick = (isOpen) => {
@ -1991,28 +1956,35 @@ const SectionFilterContent = ({
};
const clearAll = () => {
setIsLoading(true);
if (isAccountsPage) {
setIsLoading(true);
fetchPeople(null, true).finally(() => setIsLoading(false));
} else if (isRooms) {
setIsLoading(true);
const newFilter = AccountsFilter.getDefault();
navigate(`accounts/filter?${newFilter.toUrlParams()}`);
} else if (isRooms) {
const newFilter = RoomsFilter.getDefault();
if (isArchiveFolder) {
newFilter.searchArea = RoomSearchArea.Archive;
}
fetchRooms(selectedFolderId, newFilter).finally(() =>
setIsLoading(false)
);
} else {
setIsLoading(true);
const path =
newFilter.searchArea === RoomSearchArea.Active
? "rooms/shared"
: "rooms/archived";
fetchFiles(selectedFolderId).finally(() => setIsLoading(false));
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
} else {
const newFilter = FilesFilter.getDefault();
const path = location.pathname.split("/filter")[0];
navigate(`${path}/filter?${newFilter.toUrlParams()}`);
}
};
if (showFilterLoader) return <Loaders.Filter />;
return (
<FilterInput
t={t}
@ -2052,16 +2024,15 @@ export default inject(
auth,
filesStore,
treeFoldersStore,
selectedFolderStore,
clientLoadingStore,
tagsStore,
peopleStore,
}) => {
const {
fetchFiles,
filter,
fetchRooms,
roomsFilter,
setIsLoading,
setViewAs,
viewAs,
createThumbnails,
@ -2071,7 +2042,6 @@ export default inject(
clearSearch,
setClearSearch,
isLoadedEmptyPage,
isEmptyPage,
} = filesStore;
const { providers } = thirdPartyStore;
@ -2095,20 +2065,19 @@ export default inject(
const {
filterStore,
usersStore,
groupsStore,
viewAs: accountsViewAs,
} = peopleStore;
const { groups } = groupsStore;
const { getUsersList: fetchPeople } = usersStore;
const { filter: accountsFilter } = filterStore;
return {
user,
userId: user.id,
selectedFolderId: selectedFolderStore.id,
selectedItem: filter.selectedItem,
filter,
roomsFilter,
@ -2120,9 +2089,9 @@ export default inject(
isTrash,
isArchiveFolder,
setIsLoading,
fetchFiles,
fetchRooms,
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
showFilterLoader: clientLoadingStore.showFilterLoader,
fetchTags,
setViewAs,
createThumbnails,
@ -2134,7 +2103,6 @@ export default inject(
providers,
isLoadedEmptyPage,
isEmptyPage,
clearSearch,
setClearSearch,
@ -2145,7 +2113,7 @@ export default inject(
accountsViewAs,
groups,
fetchPeople,
accountsFilter,
};
}
@ -2161,6 +2129,6 @@ export default inject(
"PeopleTranslations",
"ConnectDialog",
"SmartBanner",
])(withLoader(observer(SectionFilterContent))(<Loaders.Filter />))
])(observer(SectionFilterContent))
)
);

View File

@ -39,8 +39,8 @@ import { useNavigate, useLocation } from "react-router-dom";
import Loaders from "@docspace/common/components/Loaders";
import Navigation from "@docspace/common/components/Navigation";
import TrashWarning from "@docspace/common/components/Navigation/sub-components/trash-warning";
import { Events, EmployeeType } from "@docspace/common/constants";
import { Events, EmployeeType, FolderType } from "@docspace/common/constants";
import FilesFilter from "@docspace/common/api/files/filter";
import { resendInvitesAgain } from "@docspace/common/api/people";
import DropDownItem from "@docspace/components/drop-down-item";
@ -48,9 +48,14 @@ import { tablet, mobile } from "@docspace/components/utils/device";
import { Consumer } from "@docspace/components/utils/context";
import toastr from "@docspace/components/toast/toastr";
import TableGroupMenu from "@docspace/components/table-container/TableGroupMenu";
import { getCategoryType } from "SRC_DIR/helpers/utils";
import { getMainButtonItems } from "SRC_DIR/helpers/plugins";
import { CategoryType } from "SRC_DIR/helpers/constants";
import withLoader from "../../../../HOCs/withLoader";
import {
getCategoryTypeByFolderType,
getCategoryUrl,
} from "SRC_DIR/helpers/utils";
const StyledContainer = styled.div`
width: 100%;
@ -120,7 +125,7 @@ const SectionHeaderContent = (props) => {
isInfoPanelVisible,
isRootFolder,
title,
showHeaderLoader,
isDesktop,
isTabletView,
personal,
@ -179,7 +184,7 @@ const SectionHeaderContent = (props) => {
getCheckboxItemId,
setSelectedNode,
setIsLoading,
fetchFiles,
moveToRoomsPage,
setIsInfoPanelVisible,
@ -195,8 +200,11 @@ const SectionHeaderContent = (props) => {
isAdmin,
setInvitePanelOptions,
isEmptyPage,
isLoading,
pathParts,
emptyTrashInProgress
emptyTrashInProgress,
categoryType,
} = props;
const navigate = useNavigate();
@ -749,10 +757,30 @@ const SectionHeaderContent = (props) => {
}
setSelectedNode(id);
const rootFolderType = selectedFolder.rootFolderType;
const path = getCategoryUrl(
getCategoryTypeByFolderType(rootFolderType, id),
id
);
const filter = FilesFilter.getDefault();
filter.folder = id;
const itemIdx = selectedFolder.navigationPath.findIndex((v) => v.id === id);
const state = {
title: selectedFolder.navigationPath[itemIdx]?.title || "",
isRoot: itemIdx === 0,
rootFolderType: rootFolderType,
};
setIsLoading(true);
fetchFiles(id, null, true, false)
.catch((err) => toastr.error(err))
.finally(() => setIsLoading(false));
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });
};
const onInvite = (e) => {
@ -782,6 +810,7 @@ const SectionHeaderContent = (props) => {
const headerMenu = isAccountsPage
? getAccountsHeaderMenu(t)
: getHeaderMenu(t);
const menuItems = getMenuItems();
let tableGroupMenuVisible = headerMenu.length;
@ -809,19 +838,30 @@ const SectionHeaderContent = (props) => {
tableGroupMenuProps.isBlocked = isGroupMenuBlocked;
}
const fromAccounts = location?.state?.fromAccounts;
const fromSettings = location?.state?.fromSettings;
const stateTitle = location?.state?.title;
const stateIsRoot = location?.state?.isRoot;
const stateIsRoom = location?.state?.isRoom;
const isRoot =
pathParts === null && (fromAccounts || fromSettings)
? true
isLoading && stateIsRoot
? stateIsRoot
: isRootFolder || isAccountsPage || isSettingsPage;
const currentTitle =
isSettingsPage || (!title && fromSettings)
? t("Common:Settings")
: isAccountsPage || (!title && fromAccounts)
? t("Common:Accounts")
: title;
const currentTitle = isSettingsPage
? t("Common:Settings")
: isAccountsPage
? t("Common:Accounts")
: isLoading && stateTitle
? stateTitle
: title;
const isCurrentRoom = isLoading && stateIsRoom ? stateIsRoom : isRoom;
if (showHeaderLoader) return <Loaders.SectionHeader />;
const insideTheRoom =
categoryType === CategoryType.SharedRoom ||
categoryType === CategoryType.Archive;
return (
<Consumer key="header">
@ -873,8 +913,9 @@ const SectionHeaderContent = (props) => {
withMenu={!isRoomsFolder}
onPlusClick={onCreateRoom}
isEmptyPage={isEmptyPage}
isRoom={isRoom}
isRoom={isCurrentRoom}
hideInfoPanel={isSettingsPage}
showRootFolderTitle={insideTheRoom}
/>
</div>
)}
@ -894,7 +935,7 @@ export default inject(
treeFoldersStore,
filesActionsStore,
settingsStore,
clientLoadingStore,
contextOptionsStore,
}) => {
const { isOwner, isAdmin } = auth.userStore.user;
@ -912,20 +953,26 @@ export default inject(
isEmptyFilesList,
getFolderInfo,
setBufferSelection,
setIsLoading,
fetchFiles,
fetchRooms,
activeFiles,
activeFolders,
setAlreadyFetchingRooms,
roomsForRestore,
roomsForDelete,
isEmptyPage,
clearFiles,
categoryType,
} = filesStore;
const { setIsSectionFilterLoading, showHeaderLoader, isLoading } =
clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const {
setSharingPanelVisible,
setMoveToPanelVisible,
@ -1013,7 +1060,8 @@ export default inject(
setInviteUsersWarningDialogVisible,
showText: auth.settingsStore.showText,
isDesktop: auth.settingsStore.isDesktopClient,
showHeaderLoader,
isLoading,
isRootFolder: pathParts?.length === 1,
isPersonalRoom,
title,
@ -1060,16 +1108,12 @@ export default inject(
hideContextMenuInsideArchiveRoom,
setIsLoading,
fetchFiles,
fetchRooms,
activeFiles,
activeFolders,
isRoomsFolder,
setAlreadyFetchingRooms,
enablePlugins,
setRestoreAllPanelVisible,
@ -1105,7 +1149,10 @@ export default inject(
isAdmin,
setInvitePanelOptions,
isEmptyPage,
clearFiles,
emptyTrashInProgress,
categoryType,
};
}
)(
@ -1119,5 +1166,5 @@ export default inject(
"People",
"PeopleTranslations",
"ChangeUserTypeDialog",
])(withLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />))
])(observer(SectionHeaderContent))
);

View File

@ -34,8 +34,8 @@ const SettingsView = ({
);
};
export default inject(({ auth, filesStore, settingsStore }) => {
const { isLoading } = filesStore;
export default inject(({ auth, clientLoadingStore, settingsStore }) => {
const { isLoading } = clientLoadingStore;
const { isLoadedSettingsTree } = settingsStore;

View File

@ -2,30 +2,13 @@ import React from "react";
import { useLocation, Outlet } from "react-router-dom";
import { isMobile } from "react-device-detect";
import { observer, inject } from "mobx-react";
import { withTranslation, Trans } from "react-i18next";
import axios from "axios";
import { withTranslation } from "react-i18next";
import {
showLoader,
hideLoader,
frameCallbackData,
frameCallCommand,
getObjectByLocation,
} from "@docspace/common/utils";
import { showLoader, hideLoader } from "@docspace/common/utils";
import FilesFilter from "@docspace/common/api/files/filter";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import AccountsFilter from "@docspace/common/api/people/filter";
import { getGroup } from "@docspace/common/api/groups";
import { getUserById } from "@docspace/common/api/people";
import { Events } from "@docspace/common/constants";
import Section from "@docspace/common/components/Section";
import toastr from "@docspace/components/toast/toastr";
import DragTooltip from "SRC_DIR/components/DragTooltip";
import { getCategoryType, setDocumentTitle } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
import {
SectionFilterContent,
@ -39,23 +22,30 @@ import SelectionArea from "./SelectionArea";
import { InfoPanelBodyContent, InfoPanelHeaderContent } from "./InfoPanel";
import { RoomSearchArea } from "@docspace/common/constants";
const PureHome = (props) => {
const {
fetchFiles,
fetchRooms,
alreadyFetchingRooms,
setAlreadyFetchingRooms,
//homepage,
setIsLoading,
setFirstLoad,
setToPreviewFile,
playlist,
import {
useFiles,
useSDK,
useOperations,
useAccounts,
useSettings,
} from "./Hooks";
getFileInfo,
gallerySelected,
setIsUpdatingRowItem,
setIsPreview,
selectedFolderStore,
const PureHome = (props) => {
const {
fetchFiles,
fetchRooms,
//homepage,
setIsLoading,
setToPreviewFile,
playlist,
getFileInfo,
gallerySelected,
setIsUpdatingRowItem,
setIsPreview,
selectedFolderStore,
t,
startUpload,
setDragging,
@ -73,8 +63,7 @@ const PureHome = (props) => {
itemsSelectionTitle,
setItemsSelectionTitle,
refreshFiles,
isHeaderVisible,
setHeaderVisible,
setFrameConfig,
user,
folders,
@ -113,7 +102,6 @@ const PureHome = (props) => {
frameConfig,
withPaging,
isEmptyPage,
isLoadedEmptyPage,
setPortalTariff,
@ -121,451 +109,89 @@ const PureHome = (props) => {
fetchPeople,
setSelectedNode,
onClickBack,
showFilterLoader,
} = props;
const location = useLocation();
const isAccountsPage = location.pathname.includes("accounts");
const isAccountsPage = location.pathname.includes("/accounts/filter");
const isSettingsPage = location.pathname.includes("settings");
React.useEffect(() => {
if (isAccountsPage || isSettingsPage) return;
const { onDrop } = useFiles({
t,
dragging,
setDragging,
disableDrag,
uploadEmptyFolders,
startUpload,
fetchFiles,
fetchRooms,
setIsLoading,
if (!window.location.href.includes("#preview")) {
// localStorage.removeItem("isFirstUrl");
// Media viewer
removeFirstUrl();
}
isAccountsPage,
isSettingsPage,
const categoryType = getCategoryType(location);
location,
let filterObj = null;
let isRooms = false;
playlist,
if (window.location.href.indexOf("/#preview") > 1 && playlist.length < 1) {
const pathname = window.location.href;
const fileId = pathname.slice(pathname.indexOf("#preview") + 9);
getFileInfo,
setToPreviewFile,
setIsPreview,
setTimeout(() => {
getFileInfo(fileId)
.then((data) => {
const canOpenPlayer =
data.viewAccessability.ImageView ||
data.viewAccessability.MediaView;
const file = { ...data, canOpenPlayer };
setToPreviewFile(file, true);
setIsPreview(true);
})
.catch((err) => {
toastr.error(err);
fetchDefaultFiles();
});
}, 1);
setIsUpdatingRowItem,
removeFirstUrl,
return;
}
const isRoomFolder = getObjectByLocation(window.location)?.folder;
if (
(categoryType == CategoryType.Shared ||
categoryType == CategoryType.SharedRoom ||
categoryType == CategoryType.Archive) &&
!isRoomFolder
) {
filterObj = RoomsFilter.getFilter(window.location);
isRooms = true;
if (!filterObj) {
setIsLoading(true);
if (window.location.pathname.indexOf("/rooms/archived") !== -1) {
fetchArchiveDefaultRooms();
return;
}
fetchDefaultRooms();
return;
}
} else {
filterObj = FilesFilter.getFilter(window.location);
if (!filterObj) {
setIsLoading(true);
fetchDefaultFiles();
return;
}
}
if (!filterObj) return;
if (isRooms && alreadyFetchingRooms && selectedFolderStore.title)
return setAlreadyFetchingRooms(false);
let dataObj = { filter: filterObj };
if (filterObj && filterObj.authorType) {
const authorType = filterObj.authorType;
const indexOfUnderscore = authorType.indexOf("_");
const type = authorType.slice(0, indexOfUnderscore);
const itemId = authorType.slice(indexOfUnderscore + 1);
if (itemId) {
dataObj = {
type,
itemId,
filter: filterObj,
};
} else {
filterObj.authorType = null;
dataObj = { filter: filterObj };
}
}
if (filterObj && filterObj.subjectId) {
const type = "user";
const itemId = filterObj.subjectId;
if (itemId) {
dataObj = {
type,
itemId,
filter: filterObj,
};
} else {
filterObj.subjectId = null;
dataObj = { filter: filterObj };
}
}
if (!dataObj) return;
const { filter, itemId, type } = dataObj;
const newFilter = filter
? filter.clone()
: isRooms
? RoomsFilter.getDefault()
: FilesFilter.getDefault();
const requests = [Promise.resolve(newFilter)];
if (type === "group") {
requests.push(getGroup(itemId));
} else if (type === "user") {
requests.push(getUserById(itemId));
}
setIsLoading(true);
axios
.all(requests)
.catch((err) => {
if (isRooms) {
Promise.resolve(RoomsFilter.getDefault());
} else {
Promise.resolve(FilesFilter.getDefault());
}
//console.warn("Filter restored by default", err);
})
.then((data) => {
const filter = data[0];
const result = data[1];
if (result) {
const type = result.displayName ? "user" : "group";
const selectedItem = {
key: result.id,
label: type === "user" ? result.displayName : result.name,
type,
};
if (!isRooms) {
filter.selectedItem = selectedItem;
}
}
if (filter) {
if (isRooms) {
return fetchRooms(null, filter);
} else {
const folderId = filter.folder;
return fetchFiles(folderId, filter);
}
}
return Promise.resolve();
})
.then(() => {
if (gallerySelected) {
setIsUpdatingRowItem(false);
const event = new Event(Events.CREATE);
const payload = {
extension: "docxf",
id: -1,
fromTemplate: true,
title: gallerySelected.attributes.name_form,
};
event.payload = payload;
window.dispatchEvent(event);
}
})
.finally(() => {
setIsLoading(false);
setFirstLoad(false);
setAlreadyFetchingRooms(false);
});
window.addEventListener("message", handleMessage, false);
return () => {
window.removeEventListener("message", handleMessage, false);
};
}, []);
const fetchDefaultFiles = () => {
const filterObj = FilesFilter.getDefault();
const folderId = filterObj.folder;
fetchFiles(folderId).finally(() => {
setIsLoading(false);
setFirstLoad(false);
});
};
const fetchDefaultRooms = () => {
fetchRooms().finally(() => {
setIsLoading(false);
setFirstLoad(false);
});
};
const fetchArchiveDefaultRooms = () => {
const { fetchRooms, setIsLoading, setFirstLoad } = this.props;
const filter = RoomsFilter.getDefault();
filter.searchArea = RoomSearchArea.Archive;
fetchRooms(null, filter).finally(() => {
setIsLoading(false);
setFirstLoad(false);
});
};
const onDrop = (files, uploadToFolder) => {
const {
t,
startUpload,
setDragging,
dragging,
uploadEmptyFolders,
disableDrag,
} = this.props;
dragging && setDragging(false);
if (disableDrag) return;
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
if (emptyFolders.length > 0) {
uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => {
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t);
});
} else {
startUpload(files, uploadToFolder, t);
}
};
const showOperationToast = (type, qty, title) => {
switch (type) {
case "move":
if (qty > 1) {
return (
toastr.success(
<Trans t={t} i18nKey="MoveItems" ns="Files">
{{ qty }} elements has been moved
</Trans>
),
refreshFiles()
);
}
return (
toastr.success(
<Trans t={t} i18nKey="MoveItem" ns="Files">
{{ title }} moved
</Trans>
),
refreshFiles()
);
case "duplicate":
if (qty > 1) {
return (
toastr.success(
<Trans t={t} i18nKey="CopyItems" ns="Files">
{{ qty }} elements copied
</Trans>
),
refreshFiles()
);
}
return (
toastr.success(
<Trans t={t} i18nKey="CopyItem" ns="Files">
{{ title }} copied
</Trans>
),
refreshFiles()
);
default:
break;
}
};
const showUploadPanel = () => {
setUploadPanelVisible(true);
if (primaryProgressDataVisible && uploaded && converted)
clearPrimaryProgressData();
};
const prevProps = React.useRef({
isHeaderVisible: isHeaderVisible,
isProgressFinished: isProgressFinished,
gallerySelected,
});
React.useEffect(() => {
if (isHeaderVisible !== prevProps.current.isHeaderVisible) {
setHeaderVisible(isHeaderVisible);
}
if (
isProgressFinished &&
itemsSelectionTitle &&
isProgressFinished !== prevProps.current.isProgressFinished
) {
showOperationToast(
secondaryProgressDataStoreIcon,
itemsSelectionLength,
itemsSelectionTitle
);
setItemsSelectionTitle(null);
}
}, [
isAccountsPage,
isHeaderVisible,
setHeaderVisible,
const { showUploadPanel } = useOperations({
t,
setUploadPanelVisible,
primaryProgressDataVisible,
uploaded,
converted,
clearPrimaryProgressData,
isProgressFinished,
refreshFiles,
itemsSelectionTitle,
showOperationToast,
secondaryProgressDataStoreIcon,
itemsSelectionLength,
isAccountsPage,
isSettingsPage,
setItemsSelectionTitle,
]);
});
React.useEffect(() => {
prevProps.current.isHeaderVisible = isHeaderVisible;
prevProps.current.isProgressFinished = isProgressFinished;
}, [isHeaderVisible, isProgressFinished]);
useAccounts({
t,
isAccountsPage,
location,
const handleMessage = async (e) => {
const eventData = typeof e.data === "string" ? JSON.parse(e.data) : e.data;
setIsLoading,
if (eventData.data) {
const { data, methodName } = eventData.data;
setSelectedNode,
fetchPeople,
setPortalTariff,
});
let res;
useSettings({ t, isSettingsPage, setIsLoading });
switch (methodName) {
case "setConfig":
res = await setFrameConfig(data);
break;
case "getFolderInfo":
res = selectedFolderStore;
break;
case "getFolders":
res = folders;
break;
case "getFiles":
res = files;
break;
case "getList":
res = filesList;
break;
case "getSelection":
res = selection;
break;
case "getUserInfo":
res = user;
break;
case "openModal": {
const { type, options } = data;
if (type === "CreateFile" || type === "CreateFolder") {
const item = new Event(Events.CREATE);
const payload = {
extension: options,
id: -1,
};
item.payload = payload;
window.dispatchEvent(item);
}
if (type === "CreateRoom") {
const room = new Event(Events.ROOM_CREATE);
window.dispatchEvent(room);
}
break;
}
case "createFile":
{
const { folderId, title, templateId, formId } = data;
res = await createFile(folderId, title, templateId, formId);
refreshFiles();
}
break;
case "createFolder":
{
const { parentFolderId, title } = data;
res = await createFolder(parentFolderId, title);
refreshFiles();
}
break;
case "createRoom":
{
const { title, type } = data;
res = await createRoom(title, type);
refreshFiles();
}
break;
case "setListView":
{
setViewAs(data);
}
break;
default:
res = "Wrong method";
}
frameCallbackData(res);
}
};
if (window.parent && !frameConfig && !isAccountsPage && !isSettingsPage) {
frameCallCommand("setConfig");
}
useSDK({
frameConfig,
setFrameConfig,
selectedFolderStore,
folders,
files,
filesList,
selection,
user,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
});
React.useEffect(() => {
window.addEventListener("popstate", onClickBack);
@ -575,24 +201,6 @@ const PureHome = (props) => {
};
}, []);
React.useEffect(() => {
if (!isAccountsPage) return;
if (location.pathname.indexOf("/accounts/filter") > -1) {
setSelectedNode(["accounts", "filter"]);
const newFilter = AccountsFilter.getFilter(location);
//console.log("PEOPLE URL changed", pathname, newFilter);
fetchPeople(newFilter, true).catch((err) => {
if (err?.response?.status === 402) setPortalTariff();
});
}
}, [isAccountsPage, location, setSelectedNode]);
React.useEffect(() => {
if (!isSettingsPage) return;
setDocumentTitle(t("Common:Settings"));
}, [t, tReady, isSettingsPage]);
let sectionProps = {};
if (isSettingsPage) {
@ -618,7 +226,6 @@ const PureHome = (props) => {
sectionProps.viewAs = viewAs;
sectionProps.hideAside =
primaryProgressDataVisible || secondaryProgressDataStoreVisible;
sectionProps.isHeaderVisible = isHeaderVisible;
sectionProps.isEmptyPage = isEmptyPage;
}
@ -634,31 +241,32 @@ const PureHome = (props) => {
sectionProps.secondaryProgressBarIcon = secondaryProgressDataStoreIcon;
sectionProps.showSecondaryButtonAlert = secondaryProgressDataStoreAlert;
return (
<>
return (
<>
{isSettingsPage ? (
<></>
) : isAccountsPage ? (
<AccountsDialogs />
) : (
<>
<DragTooltip />
<SelectionArea />
<DragTooltip />
<SelectionArea />
</>
)}
<MediaViewer />
<Section {...sectionProps}>
{(!isErrorRoomNotAvailable || isAccountsPage || isSettingsPage) && (
<Section.SectionHeader>
{isFrame ? (
showTitle && <SectionHeaderContent />
) : (
<SectionHeaderContent />
)}
</Section.SectionHeader>
)}
<Section.SectionHeader>
{isFrame ? (
showTitle && <SectionHeaderContent />
) : (
<SectionHeaderContent />
)}
</Section.SectionHeader>
)}
{((!isEmptyPage && !isErrorRoomNotAvailable) || isAccountsPage) &&
{(((!isEmptyPage || showFilterLoader) && !isErrorRoomNotAvailable) ||
isAccountsPage) &&
!isSettingsPage && (
<Section.SectionFilter>
{isFrame ? (
@ -669,25 +277,25 @@ const PureHome = (props) => {
</Section.SectionFilter>
)}
<Section.SectionBody>
<Section.SectionBody>
<Outlet />
</Section.SectionBody>
</Section.SectionBody>
<Section.InfoPanelHeader>
<InfoPanelHeaderContent />
</Section.InfoPanelHeader>
<Section.InfoPanelBody>
<InfoPanelBodyContent />
</Section.InfoPanelBody>
<Section.InfoPanelHeader>
<InfoPanelHeaderContent />
</Section.InfoPanelHeader>
<Section.InfoPanelBody>
<InfoPanelBodyContent />
</Section.InfoPanelBody>
{withPaging && !isSettingsPage && (
<Section.SectionPaging>
<SectionPagingContent tReady={tReady} />
</Section.SectionPaging>
)}
</Section>
</>
);
<Section.SectionPaging>
<SectionPagingContent tReady={tReady} />
</Section.SectionPaging>
)}
</Section>
</>
);
};
const Home = withTranslation(["Files", "People"])(PureHome);
@ -702,24 +310,37 @@ export default inject(
peopleStore,
filesActionsStore,
oformsStore,
selectedFolderStore,
clientLoadingStore,
}) => {
const {
secondaryProgressDataStore,
primaryProgressDataStore,
clearUploadedFilesHistory,
} = uploadDataStore;
const {
firstLoad,
setFirstLoad,
setIsSectionBodyLoading,
setIsSectionFilterLoading,
isLoading,
showFilterLoader,
} = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
setIsSectionBodyLoading(param);
};
const {
fetchFiles,
fetchRooms,
alreadyFetchingRooms,
setAlreadyFetchingRooms,
selection,
dragging,
setDragging,
setIsLoading,
isLoading,
viewAs,
getFileInfo,
setIsUpdatingRowItem,
@ -727,14 +348,14 @@ export default inject(
folders,
files,
filesList,
selectedFolderStore,
createFile,
createFolder,
createRoom,
refreshFiles,
setViewAs,
isEmptyPage,
isLoadedEmptyPage,
disableDrag,
isErrorRoomNotAvailable,
setIsPreview,
@ -746,7 +367,6 @@ export default inject(
isRecycleBinFolder,
isPrivacyFolder,
expandedKeys,
setExpandedKeys,
isRoomsFolder,
isArchiveFolder,
@ -788,15 +408,8 @@ export default inject(
const { setPortalTariff } = currentTariffStatusStore;
const {
isHeaderVisible,
setHeaderVisible,
setFrameConfig,
frameConfig,
isFrame,
withPaging,
showCatalog,
} = settingsStore;
const { setFrameConfig, frameConfig, isFrame, withPaging, showCatalog } =
settingsStore;
const {
usersStore,
@ -852,18 +465,16 @@ export default inject(
disableDrag,
setExpandedKeys,
setFirstLoad,
setDragging,
setIsLoading,
fetchFiles,
fetchRooms,
alreadyFetchingRooms,
setAlreadyFetchingRooms,
setUploadPanelVisible,
startUpload,
uploadEmptyFolders,
isHeaderVisible,
setHeaderVisible,
setToPreviewFile,
setIsPreview,
playlist,
@ -891,13 +502,15 @@ export default inject(
setViewAs,
withPaging,
isEmptyPage,
isLoadedEmptyPage,
setPortalTariff,
accountsViewAs,
fetchPeople,
setSelectedNode,
onClickBack,
showFilterLoader,
};
}
)(observer(Home));

View File

@ -1,39 +0,0 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { getCookie } from "@docspace/common/utils";
import { loadLanguagePath } from "SRC_DIR/helpers/utils";
const newInstance = i18n.createInstance();
newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === "lowercase") return value.toLowerCase();
return value;
},
},
backend: {
loadPath: loadLanguagePath(config.homepage),
},
ns: ["Profile", "ProfileAction", "Common"],
defaultNS: "Profile",
react: {
useSuspense: false,
},
});
export default newInstance;

View File

@ -1,116 +0,0 @@
import React from "react";
import MyProfileI18n from "./i18n";
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 { Provider as PeopleProvider, inject, observer } from "mobx-react";
import { I18nextProvider, withTranslation } from "react-i18next";
import {
SectionBodyContent as ViewBodyContent,
SectionHeaderContent as ViewHeaderContent,
} from "../Profile/Section";
import EditBodyContent from "../ProfileAction/Section/Body";
import Link from "@docspace/components/link";
import { Trans } from "react-i18next";
class My extends React.Component {
componentDidMount() {
const {
fetchProfile,
profile,
location,
t,
setDocumentTitle,
setLoadedProfile,
setIsLoading,
setFirstLoad,
} = this.props;
setDocumentTitle(t("Common:Profile"));
setFirstLoad(false);
const queryString = ((location && location.search) || "").slice(1);
const queryParams = queryString.split("&");
const arrayOfQueryParams = queryParams.map((queryParam) =>
queryParam.split("=")
);
const linkParams = Object.fromEntries(arrayOfQueryParams);
if (linkParams.email_change && linkParams.email_change === "success") {
toastr.success(t("ChangeEmailSuccess"));
}
if (!profile) {
setIsLoading(true);
setLoadedProfile(false);
fetchProfile("@self").finally(() => {
setIsLoading(false);
setLoadedProfile(true);
});
}
}
componentWillUnmount() {
this.props.resetProfile();
}
render() {
const { tReady, location } = this.props;
const isEdit = (location && location.search === "?action=edit") || false;
//console.log("My Profile render", this.props, isEdit);
return (
<Section withBodyAutoFocus>
<Section.SectionHeader>
{isEdit ? (
<SectionHeaderContent isMy={true} tReady={tReady} />
) : (
<ViewHeaderContent isMy={true} tReady={tReady} />
)}
</Section.SectionHeader>
<Section.SectionBody>
{isEdit ? (
<EditBodyContent isMy={true} tReady={tReady} />
) : (
<ViewBodyContent isMy={true} tReady={tReady} />
)}
</Section.SectionBody>
</Section>
);
}
}
My.propTypes = {
fetchProfile: PropTypes.func.isRequired,
match: PropTypes.object.isRequired,
profile: PropTypes.object,
language: PropTypes.string,
};
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 }) => {
return (
<PeopleProvider peopleStore={peopleStore}>
<I18nextProvider i18n={MyProfileI18n}>
<MyProfile {...rest} />
</I18nextProvider>
</PeopleProvider>
);
};

View File

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

View File

@ -7,6 +7,7 @@ import Section from "@docspace/common/components/Section";
import withLoading from "SRC_DIR/HOCs/withLoading";
//import commonIconsStyles from "@docspace/components/utils/common-icons-style";
import { useParams } from "react-router-dom";
import HistoryHeader from "../categories/developer-tools/Webhooks/WebhookHistory/sub-components/HistoryHeader";
import DetailsNavigationHeader from "../categories/developer-tools/Webhooks/WebhookEventDetails/sub-components/DetailsNavigationHeader";
@ -24,29 +25,25 @@ const ArticleSettings = React.memo(() => {
);
});
const Layout = ({
currentProductId,
setCurrentProductId,
language,
children,
addUsers,
titleType,
}) => {
const Layout = ({ currentProductId, setCurrentProductId, language, children, addUsers }) => {
useEffect(() => {
currentProductId !== "settings" && setCurrentProductId("settings");
}, [language, currentProductId, setCurrentProductId]);
const isTitleHistory = titleType === "history";
const isTitleDetails = titleType === "details";
const { id, eventId } = useParams();
const webhookHistoryPath = `/portal-settings/developer-tools/webhooks/${id}`;
const webhookDetailsPath = `/portal-settings/developer-tools/webhooks/${id}/${eventId}`;
const currentPath = window.location.pathname;
return (
<>
<ArticleSettings />
<Section withBodyScroll={true} settingsStudio={true}>
<Section.SectionHeader>
{isTitleHistory ? (
{currentPath === webhookHistoryPath ? (
<HistoryHeader />
) : isTitleDetails ? (
) : currentPath === webhookDetailsPath ? (
<DetailsNavigationHeader />
) : (
<SectionHeaderContent />
@ -64,15 +61,13 @@ const Layout = ({
);
};
export default inject(({ auth, setup, webhooksStore }) => {
export default inject(({ auth, setup }) => {
const { language, settingsStore } = auth;
const { addUsers } = setup.headerAction;
const { titleType } = webhooksStore;
return {
language,
setCurrentProductId: settingsStore.setCurrentProductId,
addUsers,
titleType,
};
})(withLoading(observer(Layout)));

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useEffect, useTransition, Suspense } from "react";
import styled from "styled-components";
import { useParams } from "react-router-dom";
@ -6,8 +6,8 @@ import { inject, observer } from "mobx-react";
import Text from "@docspace/components/text";
import { DetailsBar } from "./sub-components/DetailsBar";
import { MessagesDetails } from "./sub-components/MessagesDetails";
import DetailsBar from "./sub-components/DetailsBar";
import MessagesDetails from "./sub-components/MessagesDetails";
import { WebhookDetailsLoader } from "../sub-components/Loaders";
const DetailsWrapper = styled.div`
@ -19,46 +19,34 @@ const EventDetailsHeader = styled.header`
`;
const WebhookEventDetails = (props) => {
const { getEvent, setTitleDetails, setTitleDefault } = props;
const { fetchEventData } = props;
const { id, eventId } = useParams();
const [isLoading, setIsLoading] = useState(false);
const [webhookDetails, setWebhookDetails] = useState({});
const [isPending, startTransition] = useTransition();
useEffect(() => {
setTitleDetails();
(async () => {
const timer = setTimeout(() => {
webhookDetails.status === undefined && setIsLoading(true);
}, 300);
const webhookDetailsData = await getEvent(eventId);
setWebhookDetails(webhookDetailsData);
clearTimeout(timer);
setIsLoading(false);
})();
return setTitleDefault;
startTransition(() => {
fetchEventData(eventId);
});
}, []);
return (
<DetailsWrapper>
{isLoading && <WebhookDetailsLoader />}
{webhookDetails.status !== undefined && (
<Suspense fallback={WebhookDetailsLoader}>
<DetailsWrapper>
<main>
<EventDetailsHeader>
<Text fontWeight={600}>Webhook {id}</Text>
<DetailsBar webhookDetails={webhookDetails} />
<DetailsBar />
</EventDetailsHeader>
<MessagesDetails webhookDetails={webhookDetails} />
<MessagesDetails />
</main>
)}
</DetailsWrapper>
</DetailsWrapper>
</Suspense>
);
};
export default inject(({ webhooksStore }) => {
const { getEvent, setTitleDetails, setTitleDefault } = webhooksStore;
const { fetchEventData } = webhooksStore;
return { getEvent, setTitleDetails, setTitleDefault };
return { fetchEventData };
})(observer(WebhookEventDetails));

View File

@ -1,10 +1,12 @@
import React, { useMemo } from "react";
import React from "react";
import moment from "moment";
import styled from "styled-components";
import Text from "@docspace/components/text";
import StatusBadge from "../../sub-components/StatusBadge";
import { inject, observer } from "mobx-react";
import { Base } from "@docspace/components/themes";
const BarWrapper = styled.div`
@ -52,28 +54,26 @@ const FlexWrapper = styled.div`
align-items: center;
`;
export const DetailsBar = ({ webhookDetails }) => {
const formattedDelivery = useMemo(
() => moment(webhookDetails.delivery).format("MMM D, YYYY, h:mm:ss A") + " UTC",
[webhookDetails],
);
const formattedCreationTime = useMemo(
() => moment(webhookDetails.creationTime).format("MMM D, YYYY, h:mm:ss A") + " UTC",
[webhookDetails],
);
const DetailsBar = ({ eventDetails }) => {
const formatDate = (date) => {
return moment(date).format("MMM D, YYYY, h:mm:ss A") + " UTC";
};
const formattedDelivery = formatDate(eventDetails.delivery);
const formattedCreationTime = formatDate(eventDetails.creationTime);
return (
<BarWrapper>
<BarItem>
<BarItemHeader>Status</BarItemHeader>
<FlexWrapper>
<StatusBadge status={webhookDetails.status} />
<StatusBadge status={eventDetails.status} />
</FlexWrapper>
</BarItem>
<BarItem>
<BarItemHeader>Event ID</BarItemHeader>
<Text isInline fontWeight={600}>
{webhookDetails.id}
{eventDetails.id}
</Text>
</BarItem>
<BarItem>
@ -91,3 +91,9 @@ export const DetailsBar = ({ webhookDetails }) => {
</BarWrapper>
);
};
export default inject(({ webhooksStore }) => {
const { eventDetails } = webhooksStore;
return { eventDetails };
})(observer(DetailsBar));

View File

@ -2,34 +2,37 @@ import React from "react";
import styled from "styled-components";
import Submenu from "@docspace/components/submenu";
import { RequestDetails } from "./RequestDetails";
import { ResponseDetails } from "./ResponseDetails";
import RequestDetails from "./RequestDetails";
import ResponseDetails from "./ResponseDetails";
import { useTranslation } from "react-i18next";
import { isMobileOnly } from "react-device-detect";
import { inject, observer } from "mobx-react";
const SubmenuWrapper = styled.div`
.sticky {
z-index: 3;
top: 68px;
top: ${() => (isMobileOnly ? "68px" : "0px")};
}
`;
export const MessagesDetails = ({ webhookDetails }) => {
const MessagesDetails = ({ eventDetails }) => {
const { t } = useTranslation(["Webhooks"]);
const menuData = [
{
id: "webhookRequest",
name: t("Request"),
content: <RequestDetails webhookDetails={webhookDetails} />,
content: <RequestDetails />,
},
];
webhookDetails.status >= 200 &&
webhookDetails.status < 500 &&
if (eventDetails.status >= 200 && eventDetails.status < 500) {
menuData.push({
id: "webhookResponse",
name: t("Response"),
content: <ResponseDetails webhookDetails={webhookDetails} />,
content: <ResponseDetails />,
});
}
return (
<SubmenuWrapper>
@ -37,3 +40,9 @@ export const MessagesDetails = ({ webhookDetails }) => {
</SubmenuWrapper>
);
};
export default inject(({ webhooksStore }) => {
const { eventDetails } = webhooksStore;
return { eventDetails };
})(observer(MessagesDetails));

View File

@ -2,6 +2,7 @@ import React from "react";
import styled from "styled-components";
import Text from "@docspace/components/text";
import Textarea from "@docspace/components/textarea";
import { inject, observer } from "mobx-react";
import DangerIcon from "PUBLIC_DIR/images/danger.toast.react.svg?url";
import { useTranslation } from "react-i18next";
@ -9,6 +10,10 @@ import { useTranslation } from "react-i18next";
const DetailsWrapper = styled.div`
width: 100%;
.textareaBody {
height: 50vh !important;
}
.mt-7 {
margin-top: 7px;
}
@ -43,11 +48,21 @@ const ErrorMessageTooltip = styled.div`
}
`;
export const RequestDetails = ({ webhookDetails }) => {
function isJSON(jsonString) {
try {
const parsedJson = JSON.parse(jsonString);
return parsedJson && typeof parsedJson === "object";
} catch (e) {}
return false;
}
const RequestDetails = ({ eventDetails }) => {
const { t } = useTranslation(["Webhooks"]);
return (
<DetailsWrapper>
{webhookDetails.status === 0 && (
{eventDetails.status === 0 && (
<ErrorMessageTooltip>
<img src={DangerIcon} alt="danger icon" />
{t("FailedToConnect")}
@ -56,11 +71,11 @@ export const RequestDetails = ({ webhookDetails }) => {
<Text as="h3" fontWeight={600} className="mb-4 mt-7">
{t("RequestPostHeader")}
</Text>
{!webhookDetails.requestHeaders ? (
{!eventDetails.requestHeaders ? (
<Textarea isDisabled />
) : (
<Textarea
value={webhookDetails.requestHeaders}
value={eventDetails.requestHeaders}
enableCopy
hasNumeration
isFullHeight
@ -72,14 +87,24 @@ export const RequestDetails = ({ webhookDetails }) => {
<Text as="h3" fontWeight={600} className="mb-4 mt-16">
{t("RequestPostBody")}
</Text>
<Textarea
value={webhookDetails.requestPayload}
isJSONField
enableCopy
hasNumeration
isFullHeight
copyInfoText={t("RequestBodyCopied")}
/>
{isJSON(eventDetails.requestPayload) ? (
<Textarea
value={eventDetails.requestPayload}
isJSONField
enableCopy
hasNumeration
isFullHeight
copyInfoText={t("RequestBodyCopied")}
/>
) : (
<Textarea value={eventDetails.requestPayload} heightScale className="textareaBody" />
)}
</DetailsWrapper>
);
};
export default inject(({ webhooksStore }) => {
const { eventDetails } = webhooksStore;
return { eventDetails };
})(observer(RequestDetails));

View File

@ -3,6 +3,7 @@ import styled, { css } from "styled-components";
import Textarea from "@docspace/components/textarea";
import Button from "@docspace/components/button";
import Text from "@docspace/components/text";
import { inject, observer } from "mobx-react";
import json_beautifier from "csvjson-json_beautifier";
import { isMobileOnly } from "react-device-detect";
@ -61,8 +62,8 @@ function isJSON(jsonString) {
return false;
}
export const ResponseDetails = ({ webhookDetails }) => {
const responsePayload = webhookDetails.responsePayload?.trim();
const ResponseDetails = ({ eventDetails }) => {
const responsePayload = eventDetails.responsePayload?.trim();
const { t } = useTranslation(["Webhooks"]);
const beautifiedJSON = isJSON(responsePayload)
@ -88,14 +89,18 @@ export const ResponseDetails = ({ webhookDetails }) => {
<Text as="h3" fontWeight={600} className="mb-4 mt-7">
{t("ResponsePostHeader")}
</Text>
<Textarea
value={webhookDetails.responseHeaders}
enableCopy
hasNumeration
isFullHeight
isJSONField
copyInfoText={t("ResponseHeaderCopied")}
/>
{isJSON(eventDetails.responseHeaders) ? (
<Textarea
value={eventDetails.responseHeaders}
enableCopy
hasNumeration
isFullHeight
isJSONField
copyInfoText={t("ResponseHeaderCopied")}
/>
) : (
<Textarea value={eventDetails.responseHeaders} heightScale className="textareaBody" />
)}
<Text as="h3" fontWeight={600} className="mb-4 mt-16">
{t("ResponsePostBody")}
</Text>
@ -134,3 +139,9 @@ export const ResponseDetails = ({ webhookDetails }) => {
</DetailsWrapper>
);
};
export default inject(({ webhooksStore }) => {
const { eventDetails } = webhooksStore;
return { eventDetails };
})(observer(ResponseDetails));

View File

@ -14,8 +14,7 @@ const WebhookWrapper = styled.div`
`;
const WebhookHistory = (props) => {
const { historyItems, fetchHistoryItems, setTitleHistory, setTitleDefault, emptyCheckedIds } =
props;
const { historyItems, fetchHistoryItems, emptyCheckedIds, clearHistoryFilters } = props;
const [isFetchFinished, setIsFetchFinished] = useState(false);
const [isPending, startTransition] = useTransition();
@ -25,21 +24,19 @@ const WebhookHistory = (props) => {
const fetchItems = async () => {
await fetchHistoryItems({
configId: id,
count: 30,
});
setIsFetchFinished(true);
};
useEffect(() => {
setTitleHistory();
startTransition(fetchItems);
return setTitleDefault;
return clearHistoryFilters;
}, []);
const applyFilters = async ({ deliveryFrom, deliveryTo, groupStatus }) => {
emptyCheckedIds();
const params = { configId: id, deliveryFrom, deliveryTo, groupStatus, count: 30 };
const params = { configId: id, deliveryFrom, deliveryTo, groupStatus };
await fetchHistoryItems(params);
};
@ -61,8 +58,12 @@ const WebhookHistory = (props) => {
};
export default inject(({ webhooksStore }) => {
const { historyItems, fetchHistoryItems, setTitleHistory, setTitleDefault, emptyCheckedIds } =
webhooksStore;
const { historyItems, fetchHistoryItems, emptyCheckedIds, clearHistoryFilters } = webhooksStore;
return { historyItems, fetchHistoryItems, setTitleHistory, setTitleDefault, emptyCheckedIds };
return {
historyItems,
fetchHistoryItems,
emptyCheckedIds,
clearHistoryFilters,
};
})(observer(WebhookHistory));

View File

@ -56,18 +56,18 @@ const EmptyFilter = (props) => {
return (
<EmptyFilterWrapper>
<EmptyFilterContent>
<img src={theme.isBased ? EmptyFilterImg : EmptyFilterDarkImg} alt="Empty filter" />
<img src={theme.isBase ? EmptyFilterImg : EmptyFilterDarkImg} alt="Empty filter" />
<div className="emptyFilterText">
<Text fontSize="16px" fontWeight={700} as="p" className="emptyFilterHeading">
{t("Common:NotFoundTitle")}
</Text>
<Text fontSize="12px" color={theme.isBased ? "#555F65" : "rgba(255, 255, 255, 0.6)"}>
<Text fontSize="12px" color={theme.isBase ? "#555F65" : "rgba(255, 255, 255, 0.6)"}>
{t("NoResultsMatched")}
</Text>
<span className="clearFilter" onClick={clearFilters}>
<img src={ClearEmptyFilterIcon} alt={t("ClearFilter")} className="clearFilterIcon" />
<Link
color={theme.isBased ? "#657077" : "inherit"}
color={theme.isBase ? "#657077" : "inherit"}
isHovered
fontWeight={600}
type="action">
@ -82,8 +82,7 @@ const EmptyFilter = (props) => {
export default inject(({ webhooksStore, auth }) => {
const { formatFilters, clearHistoryFilters } = webhooksStore;
const { settingsStore } = auth;
const { theme } = settingsStore;
const { theme } = auth.settingsStore;
return { formatFilters, clearHistoryFilters, theme };
})(observer(EmptyFilter));

View File

@ -18,16 +18,17 @@ const RoundedButton = styled(Button)`
line-height: 20px;
`;
const StatusBadgeSelector = ({ label, statusCode, isStatusSelected, handleStatusClick }) => {
const handleOnClick = () => handleStatusClick(statusCode);
return (
<RoundedButton label={label} onClick={handleOnClick} primary={isStatusSelected(statusCode)} />
);
};
const StatusPicker = ({ Selectors, filters, setFilters }) => {
const { t } = useTranslation(["Webhooks", "People"]);
const StatusCodes = {
0: "Not sent",
200: "2XX",
300: "3XX",
400: "4XX",
500: "5XX",
};
const StatusCodes = ["Not sent", "2XX", "3XX", "4XX", "5XX"];
const isStatusSelected = (statusCode) => {
return filters.status.includes(statusCode);
@ -40,38 +41,33 @@ const StatusPicker = ({ Selectors, filters, setFilters }) => {
: [...prevFilters.status, statusCode],
}));
};
const StatusBadgeElements = StatusCodes.map((code) =>
code === "Not sent" ? (
<StatusBadgeSelector
label={t("NotSent")}
statusCode={code}
isStatusSelected={isStatusSelected}
handleStatusClick={handleStatusClick}
key={code}
/>
) : (
<StatusBadgeSelector
label={code}
statusCode={code}
isStatusSelected={isStatusSelected}
handleStatusClick={handleStatusClick}
key={code}
/>
),
);
return (
<>
<Text fontWeight={600} fontSize="15px">
{t("People:UserStatus")}
</Text>
<Selectors>
<RoundedButton
label={t("NotSent")}
onClick={() => handleStatusClick(StatusCodes[0])}
primary={isStatusSelected(StatusCodes[0])}
/>
<RoundedButton
label={StatusCodes[200]}
onClick={() => handleStatusClick(StatusCodes[200])}
primary={isStatusSelected(StatusCodes[200])}
/>
<RoundedButton
label={StatusCodes[300]}
onClick={() => handleStatusClick(StatusCodes[300])}
primary={isStatusSelected(StatusCodes[300])}
/>
<RoundedButton
label={StatusCodes[400]}
onClick={() => handleStatusClick(StatusCodes[400])}
primary={isStatusSelected(StatusCodes[400])}
/>
<RoundedButton
label={StatusCodes[500]}
onClick={() => handleStatusClick(StatusCodes[500])}
primary={isStatusSelected(StatusCodes[500])}
/>
</Selectors>
<Selectors>{StatusBadgeElements}</Selectors>
</>
);
};

View File

@ -12,13 +12,18 @@ import FilterDialog from "./FilterDialog";
import StatusBar from "./StatusBar";
import { useTranslation } from "react-i18next";
import { isMobileOnly } from "react-device-detect";
import { isMobile, isMobileOnly } from "react-device-detect";
const ListHeader = styled.header`
display: flex;
justify-content: space-between;
align-items: center;
${() =>
isMobile &&
css`
margin-top: 9px;
`}
${() =>
isMobileOnly &&
css`
@ -46,7 +51,7 @@ const FilterButton = styled.div`
width: 32px;
height: 32px;
z-index: ${(props) => (props.isHeaderVisible ? 199 : 202)};
z-index: ${(props) => (props.isHeaderVisible ? 199 : 201)};
border: 1px solid;
border-color: ${(props) => (props.theme.isBase ? "#d0d5da" : "rgb(71, 71, 71)")};

View File

@ -20,6 +20,8 @@ import toastr from "@docspace/components/toast/toastr";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom";
import { showLoader, hideLoader } from "@docspace/common/utils";
const HeaderContainer = styled.div`
position: sticky;
top: 0;
@ -48,7 +50,7 @@ const HeaderContainer = styled.div`
`}
.arrow-button {
margin-right: 15px;
margin-right: 18.5px;
@media ${tablet} {
padding: 8px 0 8px 8px;
@ -96,7 +98,7 @@ const HeaderContainer = styled.div`
const HistoryHeader = (props) => {
const {
isHeaderVisible,
isGroupMenuVisible,
checkedEventIds,
checkAllIds,
emptyCheckedIds,
@ -105,12 +107,10 @@ const HistoryHeader = (props) => {
areAllIdsChecked,
fetchHistoryItems,
theme,
setTitleDefault,
} = props;
const navigate = useNavigate();
const onBack = () => {
navigate(-1);
setTitleDefault();
};
const { t } = useTranslation(["Webhooks", "Common", "InfoPanel"]);
const { id } = useParams();
@ -118,21 +118,25 @@ const HistoryHeader = (props) => {
const handleGroupSelection = (isChecked) => {
isChecked ? checkAllIds() : emptyCheckedIds();
};
const SelectAll = () => {
() => checkAllIds();
};
const handleRetryAll = async () => {
await retryWebhookEvents(checkedEventIds);
fetchHistoryItems({
configId: id,
count: 30,
});
toastr.success(
`${t("WebhookRedilivered")}: ${checkedEventIds.length}`,
<b>{t("Common:Done")}</b>,
);
emptyCheckedIds();
try {
await emptyCheckedIds();
const tempIds = checkedEventIds;
showLoader();
await retryWebhookEvents(tempIds);
hideLoader();
fetchHistoryItems({
configId: id,
});
toastr.success(
`${t("WebhookRedilivered")}: ${checkedEventIds.length}`,
<b>{t("Common:Done")}</b>,
);
} catch (error) {
console.log(error);
toastr.error(error);
}
};
const headerMenu = [
@ -157,7 +161,7 @@ const HistoryHeader = (props) => {
key="select-all-event-ids"
label={t("Common:SelectAll")}
data-index={0}
onClick={SelectAll}
onClick={checkAllIds}
/>
<DropDownItem
key="unselect-all-event-ids"
@ -204,13 +208,13 @@ const HistoryHeader = (props) => {
}, []);
return (
<HeaderContainer isHeaderVisible={isHeaderVisible}>
<HeaderContainer>
{isMobileOnly ? (
<>
{isHeaderVisible && <GroupMenu />}
{isGroupMenuVisible && <GroupMenu />}
<NavigationHeader />
</>
) : isHeaderVisible ? (
) : isGroupMenuVisible ? (
<GroupMenu />
) : (
<NavigationHeader />
@ -221,7 +225,7 @@ const HistoryHeader = (props) => {
export default inject(({ webhooksStore, auth }) => {
const {
isHeaderVisible,
isGroupMenuVisible,
checkAllIds,
emptyCheckedIds,
checkedEventIds,
@ -229,7 +233,6 @@ export default inject(({ webhooksStore, auth }) => {
isIndeterminate,
areAllIdsChecked,
fetchHistoryItems,
setTitleDefault,
} = webhooksStore;
const { settingsStore } = auth;
@ -237,7 +240,7 @@ export default inject(({ webhooksStore, auth }) => {
const { theme } = settingsStore;
return {
isHeaderVisible,
isGroupMenuVisible,
checkAllIds,
emptyCheckedIds,
checkedEventIds,
@ -246,6 +249,5 @@ export default inject(({ webhooksStore, auth }) => {
areAllIdsChecked,
fetchHistoryItems,
theme,
setTitleDefault,
};
})(observer(HistoryHeader));

View File

@ -1,7 +1,7 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import Row from "@docspace/components/row";
import { HistoryRowContent } from "./HistoryRowContent";
@ -14,13 +14,24 @@ import toastr from "@docspace/components/toast/toastr";
import { useTranslation } from "react-i18next";
const HistoryRow = (props) => {
const { historyItem, sectionWidth, toggleEventId, isIdChecked, retryWebhookEvent } = props;
const {
historyItem,
sectionWidth,
toggleEventId,
isIdChecked,
retryWebhookEvent,
fetchHistoryItems,
} = props;
const { t } = useTranslation(["Webhooks", "Common"]);
const navigate = useNavigate();
const { id } = useParams();
const redirectToDetails = () => navigate(window.location.pathname + `/${historyItem.id}`);
const handleRetryEvent = async () => {
await retryWebhookEvent(historyItem.id);
await fetchHistoryItems({
configId: id,
});
toastr.success(t("WebhookRedilivered"), <b>{t("Common:Done")}</b>);
};
const handleOnSelect = () => toggleEventId(historyItem.id);
@ -69,7 +80,7 @@ const HistoryRow = (props) => {
};
export default inject(({ webhooksStore }) => {
const { toggleEventId, isIdChecked, retryWebhookEvent } = webhooksStore;
const { toggleEventId, isIdChecked, retryWebhookEvent, fetchHistoryItems } = webhooksStore;
return { toggleEventId, isIdChecked, retryWebhookEvent };
return { toggleEventId, isIdChecked, retryWebhookEvent, fetchHistoryItems };
})(observer(HistoryRow));

View File

@ -1,4 +1,4 @@
import React, { useMemo } from "react";
import React from "react";
import moment from "moment";
import styled from "styled-components";
@ -28,10 +28,7 @@ const StatusHeader = styled.div`
`;
export const HistoryRowContent = ({ sectionWidth, historyItem }) => {
const formattedDelivery = useMemo(
() => moment(historyItem.delivery).format("MMM D, YYYY, h:mm:ss A") + " UTC",
[historyItem],
);
const formattedDelivery = moment(historyItem.delivery).format("MMM D, YYYY, h:mm:ss A") + " UTC";
return (
<StyledRowContent sectionWidth={sectionWidth}>
<ContentWrapper>

View File

@ -54,7 +54,7 @@ const HistoryRowView = (props) => {
const fetchMoreFiles = () => {
const params = historyFilters === null ? {} : formatFilters(historyFilters);
fetchMoreItems({ ...params, configId: id, count: 10 });
fetchMoreItems({ ...params, configId: id });
};
return (

View File

@ -1,9 +1,9 @@
import React, { useMemo } from "react";
import React from "react";
import moment from "moment";
import styled, { css } from "styled-components";
import { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import TableRow from "@docspace/components/table-container/TableRow";
import TableCell from "@docspace/components/table-container/TableCell";
@ -39,13 +39,18 @@ const StyledWrapper = styled.div`
`;
const HistoryTableRow = (props) => {
const { item, toggleEventId, isIdChecked, retryWebhookEvent, hideColumns } = props;
const { item, toggleEventId, isIdChecked, retryWebhookEvent, hideColumns, fetchHistoryItems } =
props;
const { t } = useTranslation(["Webhooks", "Common"]);
const navigate = useNavigate();
const { id } = useParams();
const redirectToDetails = () => navigate(window.location.pathname + `/${item.id}`);
const handleRetryEvent = async () => {
await retryWebhookEvent(item.id);
await fetchHistoryItems({
configId: id,
});
toastr.success(t("WebhookRedilivered"), <b>{t("Common:Done")}</b>);
};
@ -64,10 +69,7 @@ const HistoryTableRow = (props) => {
},
];
const formattedDelivery = useMemo(
() => moment(item.delivery).format("MMM D, YYYY, h:mm:ss A") + " UTC",
[item],
);
const formattedDelivery = moment(item.delivery).format("MMM D, YYYY, h:mm:ss A") + " UTC";
const onChange = (e) => {
if (
@ -108,7 +110,7 @@ const HistoryTableRow = (props) => {
};
export default inject(({ webhooksStore }) => {
const { toggleEventId, isIdChecked, retryWebhookEvent } = webhooksStore;
const { toggleEventId, isIdChecked, retryWebhookEvent, fetchHistoryItems } = webhooksStore;
return { toggleEventId, isIdChecked, retryWebhookEvent };
return { toggleEventId, isIdChecked, retryWebhookEvent, fetchHistoryItems };
})(observer(HistoryTableRow));

View File

@ -78,7 +78,7 @@ const HistoryTableView = (props) => {
const fetchMoreFiles = () => {
const params = historyFilters === null ? {} : formatFilters(historyFilters);
fetchMoreItems({ ...params, configId: id, count: 10 });
fetchMoreItems({ ...params, configId: id });
};
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;

View File

@ -25,9 +25,11 @@ export const DeleteWebhookDialog = ({ visible, onClose, header, handleSubmit })
const { t } = useTranslation(["Webhooks", "Common", "EmptyTrashDialog"]);
const cleanUpEvent = () => window.removeEventListener("keyup", onKeyPress);
useEffect(() => {
window.addEventListener("keyup", onKeyPress);
return () => window.removeEventListener("keyup", onKeyPress);
return cleanUpEvent;
});
const handleDeleteClick = () => {

View File

@ -154,8 +154,9 @@ const SecretKeyInput = (props) => {
);
};
export default inject(({ settingsStore }) => {
const { webhooksGuideUrl, passwordSettings } = settingsStore;
export default inject(({ settingsStore, auth }) => {
const { passwordSettings } = settingsStore;
const { webhooksGuideUrl } = auth.settingsStore;
return {
passwordSettings,

View File

@ -107,9 +107,11 @@ const WebhookDialog = (props) => {
onModalClose();
};
const cleanUpEvent = () => window.removeEventListener("keyup", onKeyPress);
useEffect(() => {
window.addEventListener("keyup", onKeyPress);
return () => window.removeEventListener("keyup", onKeyPress);
return cleanUpEvent;
}, []);
useEffect(() => {

View File

@ -42,15 +42,15 @@ const WebhookInfo = (props) => {
return (
<InfoWrapper>
<InfoText as="p">{t("WebhooksInfo")}</InfoText>
<StyledGuideLink fontWeight={600} isHovered type="page" href={webhooksGuideUrl}>
<StyledGuideLink fontWeight={600} isHovered type="page" href={webhooksGuideUrl} target="_blank">
{t("WebhooksGuide")}
</StyledGuideLink>
</InfoWrapper>
);
};
export default inject(({ settingsStore }) => {
const { webhooksGuideUrl } = settingsStore;
export default inject(({ auth }) => {
const { webhooksGuideUrl } = auth.settingsStore;
return {
webhooksGuideUrl,

View File

@ -17,7 +17,6 @@ export const WebhookRow = (props) => {
webhook,
sectionWidth,
toggleEnabled,
setTitleHistory,
openSettingsModal,
openDeleteModal,
setCurrentWebhook,
@ -33,7 +32,6 @@ export const WebhookRow = (props) => {
};
const redirectToHistory = () => {
setTitleHistory();
navigate(window.location.pathname + `/${webhook.id}`);
};
const handleRowClick = (e) => {
@ -103,8 +101,8 @@ export const WebhookRow = (props) => {
};
export default inject(({ webhooksStore }) => {
const { toggleEnabled, deleteWebhook, editWebhook, setTitleHistory, setCurrentWebhook } =
const { toggleEnabled, deleteWebhook, editWebhook, setCurrentWebhook } =
webhooksStore;
return { toggleEnabled, deleteWebhook, editWebhook, setTitleHistory, setCurrentWebhook };
return { toggleEnabled, deleteWebhook, editWebhook, setCurrentWebhook };
})(observer(WebhookRow));

View File

@ -39,7 +39,6 @@ const WebhooksTableRow = (props) => {
const {
webhook,
toggleEnabled,
setTitleHistory,
openSettingsModal,
openDeleteModal,
setCurrentWebhook,
@ -52,7 +51,6 @@ const WebhooksTableRow = (props) => {
const [isChecked, setIsChecked] = useState(webhook.enabled);
const redirectToHistory = () => {
setTitleHistory();
navigate(window.location.pathname + `/${webhook.id}`);
};
@ -144,11 +142,10 @@ const WebhooksTableRow = (props) => {
};
export default inject(({ webhooksStore }) => {
const { toggleEnabled, setTitleHistory, setCurrentWebhook } = webhooksStore;
const { toggleEnabled, setCurrentWebhook } = webhooksStore;
return {
toggleEnabled,
setTitleHistory,
setCurrentWebhook,
};
})(observer(WebhooksTableRow));

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState } from "react";
import styled, { css } from "styled-components";
import Submenu from "@docspace/components/submenu";
import { inject, observer } from "mobx-react";
import { combineUrl } from "@docspace/common/utils";
@ -14,6 +15,18 @@ import SSOLoader from "./sub-components/ssoLoader";
import { WebhookConfigsLoader } from "./Webhooks/sub-components/Loaders";
import { useTranslation } from "react-i18next";
import { isMobileOnly } from "react-device-detect";
const StyledSubmenu = styled(Submenu)`
.sticky {
z-index: 201;
${() =>
isMobileOnly &&
css`
top: 58px;
`}
}
`;
const DeveloperToolsWrapper = (props) => {
const { loadBaseInfo, developerToolsTab, setTab } = props;
@ -71,7 +84,7 @@ const DeveloperToolsWrapper = (props) => {
<AppLoader />
);
return <Submenu data={data} startSelect={currentTab} onSelect={onSelect} />;
return <StyledSubmenu data={data} startSelect={currentTab} onSelect={onSelect} />;
};
export default inject(({ setup, webhooksStore }) => {

View File

@ -5,7 +5,6 @@ import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import Loaders from "@docspace/common/components/Loaders";
import withPeopleLoader from "../../../../HOCs/withPeopleLoader";
import MainProfile from "./sub-components/main-profile";
import LoginSettings from "./sub-components/login-settings";
@ -32,7 +31,14 @@ const Wrapper = styled.div`
`;
const SectionBodyContent = (props) => {
const { setBackupCodes, getTfaType, getBackupCodes, t } = props;
const {
setBackupCodes,
getTfaType,
getBackupCodes,
isProfileLoaded,
t,
} = props;
const [tfa, setTfa] = useState(false);
const [backupCodesCount, setBackupCodesCount] = useState(0);
@ -59,6 +65,8 @@ const SectionBodyContent = (props) => {
fetchData();
}, []);
if (!isProfileLoaded) return <Loaders.ProfileView />;
return (
<Wrapper>
<MainProfile />
@ -72,14 +80,15 @@ const SectionBodyContent = (props) => {
);
};
export default inject(({ auth }) => {
export default inject(({ auth, clientLoadingStore }) => {
const { tfaStore } = auth;
const { getBackupCodes, getTfaType, setBackupCodes } = tfaStore;
const { isProfileLoaded } = clientLoadingStore;
return {
getBackupCodes,
getTfaType,
setBackupCodes,
isProfileLoaded,
};
})(
observer(
@ -92,10 +101,6 @@ export default inject(({ auth }) => {
"BackupCodesDialog",
"DeleteSelfProfileDialog",
"Notifications",
])(
withPeopleLoader(SectionBodyContent)(
<Loaders.ProfileView isProfileView />
)
)
])(SectionBodyContent)
)
);

View File

@ -47,7 +47,7 @@ const MainProfile = (props) => {
culture,
helpLink,
cultureNames,
setIsLoading,
changeEmailVisible,
setChangeEmailVisible,
changePasswordVisible,
@ -130,13 +130,10 @@ const MainProfile = (props) => {
const onLanguageSelect = (language) => {
if (profile.cultureName === language.key) return;
setIsLoading(true);
updateProfileCulture(profile.id, language.key)
.then(() => setIsLoading(false))
.then(() => location.reload())
.catch((error) => {
toastr.error(error && error.message ? error.message : error);
setIsLoading(false);
});
};
@ -470,14 +467,8 @@ const MainProfile = (props) => {
export default inject(({ auth, peopleStore }) => {
const { withActivationBar, sendActivationLink } = auth.userStore;
const {
theme,
helpLink,
culture,
currentColorScheme,
documentationEmail,
} = auth.settingsStore;
const { setIsLoading } = peopleStore.loadingStore;
const { theme, helpLink, culture, currentColorScheme, documentationEmail } =
auth.settingsStore;
const {
targetUser: profile,
@ -497,7 +488,7 @@ export default inject(({ auth, peopleStore }) => {
profile,
culture,
helpLink,
setIsLoading,
changeEmailVisible,
setChangeEmailVisible,
changePasswordVisible,

View File

@ -12,7 +12,6 @@ import Box from "@docspace/components/box";
import HelpButton from "@docspace/components/help-button";
import toastr from "@docspace/components/toast/toastr";
import Loaders from "@docspace/common/components/Loaders";
import withPeopleLoader from "../../../../HOCs/withPeopleLoader";
import {
LogoutConnectionDialog,
@ -265,12 +264,4 @@ export default inject(({ auth, setup }) => {
setLogoutAllVisible,
removeAllExecptThis,
};
})(
observer(
withTranslation(["Profile", "Common"])(
withPeopleLoader(ActiveSessions)(
<Loaders.ProfileFooter isProfileFooter />
)
)
)
);
})(observer(withTranslation(["Profile", "Common"])(ActiveSessions)));

View File

@ -18,8 +18,6 @@ import { DeleteOwnerProfileDialog } from "SRC_DIR/components/dialogs";
import { combineUrl } from "@docspace/common/utils";
import config from "PACKAGE_FILE";
import withPeopleLoader from "SRC_DIR/HOCs/withPeopleLoader";
import { StyledHeader } from "./StyledHeader";
const Header = (props) => {
@ -39,6 +37,8 @@ const Header = (props) => {
setChangeEmailVisible,
setChangePasswordVisible,
setChangeAvatarVisible,
isProfileLoaded,
} = props;
const [deleteSelfProfileDialog, setDeleteSelfProfileDialog] = useState(false);
@ -97,6 +97,8 @@ const Header = (props) => {
setFilter(filter);
};
if (!isProfileLoaded) return <Loaders.SectionHeader />;
return (
<StyledHeader
showContextButton={(isAdmin && !profile?.isOwner) || isMe}
@ -113,9 +115,9 @@ const Header = (props) => {
)}
<Headline className="header-headline" type="content" truncate={true}>
{t("Profile:MyProfile")}
{profile.isLDAP && ` (${t("PeopleTranslations:LDAPLbl")})`}
{profile?.isLDAP && ` (${t("PeopleTranslations:LDAPLbl")})`}
</Headline>
{((isAdmin && !profile.isOwner) || isMe) && (
{((isAdmin && !profile?.isOwner) || isMe) && (
<ContextMenuButton
className="action-button"
directionX="right"
@ -132,7 +134,7 @@ const Header = (props) => {
<DeleteSelfProfileDialog
visible={deleteSelfProfileDialog}
onClose={() => setDeleteSelfProfileDialog(false)}
email={profile.email}
email={profile?.email}
/>
)}
@ -146,7 +148,7 @@ const Header = (props) => {
);
};
export default inject(({ auth, peopleStore }) => {
export default inject(({ auth, peopleStore, clientLoadingStore }) => {
const { isAdmin } = auth;
const { isVisitor, isCollaborator } = auth.userStore.user;
@ -157,6 +159,8 @@ export default inject(({ auth, peopleStore }) => {
const { targetUser, isMe } = targetUserStore;
const { isProfileLoaded } = clientLoadingStore;
const {
setChangeEmailVisible,
setChangePasswordVisible,
@ -176,11 +180,9 @@ export default inject(({ auth, peopleStore }) => {
setChangeEmailVisible,
setChangePasswordVisible,
setChangeAvatarVisible,
isProfileLoaded,
};
})(
observer(
withTranslation(["Profile", "Common", "PeopleTranslations"])(
withPeopleLoader(Header)(<Loaders.SectionHeader />)
)
)
observer(withTranslation(["Profile", "Common", "PeopleTranslations"])(Header))
);

View File

@ -22,19 +22,16 @@ class Profile extends React.Component {
profile,
t,
setDocumentTitle,
setFirstLoad,
setIsLoading,
setIsEditTargetUser,
setLoadedProfile,
isVisitor,
selectedTreeNode,
setSelectedNode,
setFirstLoadGlobal,
setIsProfileLoaded,
} = this.props;
const userId = "@self";
setFirstLoad(false);
setFirstLoadGlobal(false);
setIsEditTargetUser(false);
isVisitor
@ -54,11 +51,8 @@ class Profile extends React.Component {
// toastr.success(t("ChangeEmailSuccess"));
// }
if (!profile || profile.userName !== userId) {
setIsLoading(true);
setLoadedProfile(false);
fetchProfile(userId).finally(() => {
setIsLoading(false);
setLoadedProfile(true);
setIsProfileLoaded(true);
});
}
@ -70,13 +64,13 @@ class Profile extends React.Component {
}
componentDidUpdate(prevProps) {
const { fetchProfile, profile, setIsLoading } = this.props;
const { fetchProfile, profile } = this.props;
// const { userId } = match.params;
// const prevUserId = prevProps.match.params.userId;
// if (userId !== undefined && userId !== prevUserId) {
// setIsLoading(true);
// fetchProfile(userId).finally(() => setIsLoading(false));
// fetchProfile(userId);
// }
if (profile && this.documentElement) {
@ -118,32 +112,35 @@ Profile.propTypes = {
language: PropTypes.string,
};
export default inject(({ auth, peopleStore, filesStore, treeFoldersStore }) => {
const { setDocumentTitle, language } = auth;
const { setFirstLoad: setFirstLoadGlobal } = filesStore;
const { targetUserStore, loadingStore } = peopleStore;
const {
getTargetUser: fetchProfile,
targetUser: profile,
isEditTargetUser,
setIsEditTargetUser,
} = targetUserStore;
const { setFirstLoad, setIsLoading, setLoadedProfile } = loadingStore;
const { selectedTreeNode, setSelectedNode } = treeFoldersStore;
return {
setFirstLoadGlobal,
setDocumentTitle,
language,
fetchProfile,
profile,
setFirstLoad,
setIsLoading,
isEditTargetUser,
setIsEditTargetUser,
setLoadedProfile,
showCatalog: auth.settingsStore.showCatalog,
selectedTreeNode,
setSelectedNode,
isVisitor: auth.userStore.user.isVisitor,
};
})(observer(withTranslation(["Profile", "Common"])(withCultureNames(Profile))));
export default inject(
({ auth, peopleStore, clientLoadingStore, treeFoldersStore }) => {
const { setDocumentTitle, language } = auth;
const { setIsProfileLoaded } = clientLoadingStore;
const { targetUserStore } = peopleStore;
const {
getTargetUser: fetchProfile,
targetUser: profile,
isEditTargetUser,
setIsEditTargetUser,
} = targetUserStore;
const { selectedTreeNode, setSelectedNode } = treeFoldersStore;
return {
setDocumentTitle,
language,
fetchProfile,
profile,
isEditTargetUser,
setIsEditTargetUser,
showCatalog: auth.settingsStore.showCatalog,
selectedTreeNode,
setSelectedNode,
isVisitor: auth.userStore.user.isVisitor,
setIsProfileLoaded,
};
}
)(observer(withTranslation(["Profile", "Common"])(withCultureNames(Profile))));

View File

@ -137,8 +137,8 @@ class SectionBodyContent extends React.Component {
}
}
export default inject(({ auth, filesStore, versionHistoryStore }) => {
const { setFirstLoad, setIsLoading, isLoading } = filesStore;
export default inject(({ auth, versionHistoryStore, clientLoadingStore }) => {
const { setFirstLoad, isLoading } = clientLoadingStore;
const { versions, fetchFileVersions, fileId, fileSecurity } =
versionHistoryStore;

View File

@ -44,18 +44,21 @@ const VersionHistory = withTranslation("VersionHistory")(PureVersionHistory);
VersionHistory.propTypes = {};
export default inject(({ auth, filesStore, versionHistoryStore }) => {
const { filter, isLoading } = filesStore;
const { setIsVerHistoryPanel, versions, showProgressBar } =
versionHistoryStore;
export default inject(
({ auth, filesStore, clientLoadingStore, versionHistoryStore }) => {
const { filter } = filesStore;
const { isLoading } = clientLoadingStore;
const { setIsVerHistoryPanel, versions, showProgressBar } =
versionHistoryStore;
return {
isTabletView: auth.settingsStore.isTabletView,
isLoading,
filter,
versions,
showProgressBar,
return {
isTabletView: auth.settingsStore.isTabletView,
isLoading,
filter,
versions,
showProgressBar,
setIsVerHistoryPanel,
};
})(observer(VersionHistory));
setIsVerHistoryPanel,
};
}
)(observer(VersionHistory));

View File

@ -0,0 +1,240 @@
import { makeAutoObservable } from "mobx";
const SHOW_LOADER_TIMER = 500;
const MIN_LOADER_TIMER = 500;
class ClientLoadingStore {
isLoaded = false;
firstLoad = true;
isArticleLoading = true;
isSectionHeaderLoading = false;
isSectionFilterLoading = false;
isSectionBodyLoading = false;
isProfileLoaded = false;
sectionHeaderTimer = null;
sectionFilterTimer = null;
sectionBodyTimer = null;
pendingSectionLoaders = {
header: false,
filter: false,
body: false,
};
startLoadingTime = {
header: null,
filter: null,
body: null,
};
constructor() {
makeAutoObservable(this);
}
setIsLoaded = (isLoaded) => {
this.isLoaded = isLoaded;
};
setFirstLoad = (firstLoad) => {
this.firstLoad = firstLoad;
};
setIsArticleLoading = (isArticleLoading) => {
this.isArticleLoading = isArticleLoading;
};
updateIsSectionHeaderLoading = (param) => {
this.isSectionHeaderLoading = param;
};
updateIsSectionFilterLoading = (param) => {
this.isSectionFilterLoading = param;
};
updateIsSectionBodyLoading = (param) => {
this.isSectionBodyLoading = param;
};
setIsSectionHeaderLoading = (isSectionHeaderLoading, withTimer = true) => {
this.pendingSectionLoaders.header = isSectionHeaderLoading;
if (isSectionHeaderLoading) {
if (this.sectionHeaderTimer) {
return;
}
this.startLoadingTime.header = new Date();
if (withTimer) {
return (this.sectionHeaderTimer = setTimeout(() => {
this.updateIsSectionHeaderLoading(isSectionHeaderLoading);
}, SHOW_LOADER_TIMER));
}
this.updateIsSectionHeaderLoading(isSectionHeaderLoading);
} else {
if (this.startLoadingTime.header) {
const currentDate = new Date();
const ms = Math.abs(
this.startLoadingTime.header.getTime() - currentDate.getTime()
);
if (this.sectionHeaderTimer) {
let ms = Math.abs(ms - SHOW_LOADER_TIMER);
clearTimeout(this.sectionHeaderTimer);
this.sectionHeaderTimer = null;
}
if (ms < MIN_LOADER_TIMER)
return setTimeout(() => {
this.updateIsSectionHeaderLoading(false);
this.startLoadingTime.header = null;
}, MIN_LOADER_TIMER - ms);
}
if (this.sectionHeaderTimer) {
clearTimeout(this.sectionHeaderTimer);
this.sectionHeaderTimer = null;
}
this.startLoadingTime.header = null;
this.updateIsSectionHeaderLoading(false);
}
};
setIsSectionFilterLoading = (isSectionFilterLoading, withTimer = true) => {
this.pendingSectionLoaders.filter = isSectionFilterLoading;
if (isSectionFilterLoading) {
if (this.sectionFilterTimer) {
return;
}
this.startLoadingTime.filter = new Date();
if (withTimer) {
return (this.sectionFilterTimer = setTimeout(() => {
this.updateIsSectionFilterLoading(isSectionFilterLoading);
}, SHOW_LOADER_TIMER));
}
this.updateIsSectionFilterLoading(isSectionFilterLoading);
} else {
if (this.startLoadingTime.filter) {
const currentDate = new Date();
let ms = Math.abs(
this.startLoadingTime.filter.getTime() - currentDate.getTime()
);
if (this.sectionFilterTimer) {
let ms = Math.abs(ms - SHOW_LOADER_TIMER);
clearTimeout(this.sectionFilterTimer);
this.sectionFilterTimer = null;
}
if (ms < MIN_LOADER_TIMER) {
return setTimeout(() => {
this.updateIsSectionFilterLoading(false);
this.startLoadingTime.filter = null;
}, MIN_LOADER_TIMER - ms);
}
}
if (this.sectionFilterTimer) {
clearTimeout(this.sectionFilterTimer);
this.sectionFilterTimer = null;
}
this.startLoadingTime.filter = null;
this.updateIsSectionFilterLoading(false);
}
};
setIsSectionBodyLoading = (isSectionBodyLoading, withTimer = true) => {
this.pendingSectionLoaders.body = isSectionBodyLoading;
if (isSectionBodyLoading) {
if (this.sectionBodyTimer) {
return;
}
this.startLoadingTime.body = new Date();
if (withTimer) {
return (this.sectionBodyTimer = setTimeout(() => {
this.updateIsSectionBodyLoading(isSectionBodyLoading);
}, SHOW_LOADER_TIMER));
}
this.updateIsSectionBodyLoading(isSectionBodyLoading);
} else {
if (this.startLoadingTime.body) {
const currentDate = new Date();
let ms = Math.abs(
this.startLoadingTime.body.getTime() - currentDate.getTime()
);
if (this.sectionBodyTimer) {
let ms = Math.abs(ms - SHOW_LOADER_TIMER);
clearTimeout(this.sectionBodyTimer);
this.sectionBodyTimer = null;
}
if (ms < MIN_LOADER_TIMER)
return setTimeout(() => {
this.updateIsSectionBodyLoading(false);
this.startLoadingTime.body = null;
}, MIN_LOADER_TIMER - ms);
}
if (this.sectionBodyTimer) {
clearTimeout(this.sectionBodyTimer);
this.sectionBodyTimer = null;
}
this.startLoadingTime.body = null;
this.updateIsSectionBodyLoading(false);
}
};
setIsProfileLoaded = (isProfileLoaded) => {
this.isProfileLoaded = isProfileLoaded;
};
hideLoaders = () => {
this.clearTimers();
this.showHeaderLoader = false;
this.showFilterLoader = false;
this.showBodyLoader = false;
this.isSectionHeaderLoading = false;
this.isSectionFilterLoading = false;
this.isSectionBodyLoading = false;
};
clearTimers = () => {
clearTimeout(this.sectionHeaderTimer);
clearTimeout(this.sectionFilterTimer);
clearTimeout(this.sectionBodyTimer);
};
get isLoading() {
return (
this.isArticleLoading ||
this.pendingSectionLoaders.header ||
this.pendingSectionLoaders.filter ||
this.pendingSectionLoaders.body
);
}
get showArticleLoader() {
return this.isArticleLoading;
}
get showHeaderLoader() {
return this.isSectionHeaderLoading || this.isArticleLoading;
}
get showFilterLoader() {
return this.isSectionFilterLoading || this.showHeaderLoader;
}
get showBodyLoader() {
return this.isSectionBodyLoading || this.showFilterLoader;
}
}
export default ClientLoadingStore;

View File

@ -86,9 +86,7 @@ class ContextOptionsStore {
}
onOpenFolder = (item) => {
const { id, folderId, fileExst } = item;
const locationId = !fileExst ? id : folderId;
this.filesActionsStore.openLocationAction(locationId);
this.filesActionsStore.openLocationAction(item);
};
onClickLinkFillForm = (item) => {
@ -188,9 +186,7 @@ class ContextOptionsStore {
};
onOpenLocation = (item) => {
const { parentId, folderId, fileExst } = item;
const locationId = !fileExst ? parentId : folderId;
this.filesActionsStore.openLocationAction(locationId);
this.filesActionsStore.openLocationAction(item);
};
onOwnerChange = () => {

View File

@ -1,6 +1,9 @@
import { makeAutoObservable } from "mobx";
import toastr from "@docspace/components/toast/toastr";
import { isMobile } from "react-device-detect";
import FilesFilter from "@docspace/common/api/files/filter";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
class CreateEditRoomStore {
roomParams = null;
@ -25,7 +28,8 @@ class CreateEditRoomStore {
thirdPartyStore,
settingsStore,
infoPanelStore,
currentQuotaStore
currentQuotaStore,
clientLoadingStore
) {
makeAutoObservable(this);
@ -37,6 +41,7 @@ class CreateEditRoomStore {
this.settingsStore = settingsStore;
this.infoPanelStore = infoPanelStore;
this.currentQuotaStore = currentQuotaStore;
this.clientLoadingStore = clientLoadingStore;
}
setRoomParams = (roomParams) => {
@ -136,12 +141,12 @@ class CreateEditRoomStore {
this.onClose();
}
!withPaging && this.onOpenNewRoom(room.id);
!withPaging && this.onOpenNewRoom(room);
URL.revokeObjectURL(img.src);
};
img.src = url;
});
} else !withPaging && this.onOpenNewRoom(room.id);
} else !withPaging && this.onOpenNewRoom(room);
this.roomIsCreated = true;
} catch (err) {
@ -156,20 +161,36 @@ class CreateEditRoomStore {
}
};
onOpenNewRoom = async (id) => {
const { fetchFiles } = this.filesStore;
onOpenNewRoom = async (room) => {
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const { setView, setIsVisible } = this.infoPanelStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
setView("info_members");
fetchFiles(id)
.then(() => {
!isMobile && setIsVisible(true);
})
.finally(() => {
this.setIsLoading(false);
this.setConfirmDialogIsLoading(false);
this.onClose();
});
const state = {
isRoot: false,
title: room.title,
rootFolderType: room.rootFolderType,
};
const newFilter = FilesFilter.getDefault();
newFilter.folder = room.id;
setIsLoading(true);
const path = getCategoryUrl(CategoryType.SharedRoom, room.id);
window.DocSpace.navigate(`${path}?${newFilter.toUrlParams()}`, { state });
!isMobile && setIsVisible(true);
this.setIsLoading(false);
this.setConfirmDialogIsLoading(false);
this.onClose();
};
}

View File

@ -40,10 +40,16 @@ import { getCategoryType } from "SRC_DIR/helpers/utils";
import { muteRoomNotification } from "@docspace/common/api/settings";
import { CategoryType } from "SRC_DIR/helpers/constants";
import RoomsFilter from "@docspace/common/api/rooms/filter";
import AccountsFilter from "@docspace/common/api/people/filter";
import { RoomSearchArea } from "@docspace/common/constants";
import { getObjectByLocation } from "@docspace/common/utils";
import uniqueid from "lodash/uniqueId";
import FilesFilter from "@docspace/common/api/files/filter";
import {
getCategoryTypeByFolderType,
getCategoryUrl,
} from "SRC_DIR/helpers/utils";
class FilesActionStore {
authStore;
@ -55,6 +61,7 @@ class FilesActionStore {
dialogsStore;
mediaViewerDataStore;
accessRightsStore;
clientLoadingStore;
isBulkDownload = false;
isLoadedSearchFiles = false;
@ -70,7 +77,8 @@ class FilesActionStore {
settingsStore,
dialogsStore,
mediaViewerDataStore,
accessRightsStore
accessRightsStore,
clientLoadingStore
) {
makeAutoObservable(this);
this.authStore = authStore;
@ -82,6 +90,7 @@ class FilesActionStore {
this.dialogsStore = dialogsStore;
this.mediaViewerDataStore = mediaViewerDataStore;
this.accessRightsStore = accessRightsStore;
this.clientLoadingStore = clientLoadingStore;
}
setIsBulkDownload = (isBulkDownload) => {
@ -100,10 +109,11 @@ class FilesActionStore {
this.uploadDataStore.secondaryProgressDataStore;
const {
filter,
fetchFiles,
roomsFilter,
fetchRooms,
filter,
roomsFilter,
isEmptyLastPageAfterOperation,
resetFilterPage,
} = this.filesStore;
@ -1185,9 +1195,13 @@ class FilesActionStore {
};
selectTag = (tag) => {
const { roomsFilter, fetchRooms, setIsLoading } = this.filesStore;
const { roomsFilter } = this.filesStore;
const { id } = this.selectedFolderStore;
const { setIsSectionBodyLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionBodyLoading(param);
};
const newFilter = roomsFilter.clone();
@ -1211,13 +1225,19 @@ class FilesActionStore {
}
setIsLoading(true);
fetchRooms(id, newFilter).finally(() => setIsLoading(false));
window.DocSpace.navigate(
`${window.DocSpace.location.pathname}?${newFilter.toUrlParams()}`
);
};
selectOption = ({ option, value }) => {
const { roomsFilter, fetchRooms, setIsLoading } = this.filesStore;
const { id } = this.selectedFolderStore;
const { roomsFilter } = this.filesStore;
const { setIsSectionBodyLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionBodyLoading(param);
};
const newFilter = roomsFilter.clone();
const tags = newFilter.tags ? [...newFilter.tags] : [];
@ -1232,7 +1252,9 @@ class FilesActionStore {
}
setIsLoading(true);
fetchRooms(id, newFilter).finally(() => setIsLoading(false));
window.DocSpace.navigate(
`${window.DocSpace.location.pathname}?${newFilter.toUrlParams()}`
);
};
selectRowAction = (checked, file) => {
@ -1257,28 +1279,67 @@ class FilesActionStore {
}
};
openLocationAction = async (locationId) => {
openLocationAction = async (item) => {
this.filesStore.setBufferSelection(null);
const files = await this.filesStore.fetchFiles(locationId, null);
return files;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const { id, isRoom, title, rootFolderType } = item;
const categoryType = getCategoryTypeByFolderType(rootFolderType, id);
const state = { title, rootFolderType, isRoot: false, isRoom };
const filter = FilesFilter.getDefault();
filter.folder = id;
const url = getCategoryUrl(categoryType, id);
window.DocSpace.navigate(`${url}?${filter.toUrlParams()}`, { state });
};
checkAndOpenLocationAction = async (item) => {
const { filter, setHighlightFile, fetchFiles } = this.filesStore;
const newFilter = filter.clone();
const { categoryType } = this.filesStore;
const { myRoomsId, myFolderId, archiveRoomsId, recycleBinFolderId } =
this.treeFoldersStore;
const { rootFolderType } = this.selectedFolderStore;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const { ExtraLocationTitle, ExtraLocation, fileExst } = item;
const isRoot =
ExtraLocation === myRoomsId ||
ExtraLocation === myFolderId ||
ExtraLocation === archiveRoomsId ||
ExtraLocation === recycleBinFolderId;
const state = {
title: ExtraLocationTitle,
isRoot,
fileExst,
highlightFileId: item.id,
isFileHasExst: !item.fileExst,
rootFolderType,
};
const url = getCategoryUrl(categoryType, ExtraLocation);
const newFilter = FilesFilter.getDefault();
newFilter.page = 0;
newFilter.search = item.title;
newFilter.folder = ExtraLocation;
fetchFiles(item.ExtraLocation, newFilter)
.then(() => {
setHighlightFile({
highlightFileId: item.id,
isFileHasExst: !item.fileExst,
});
})
.catch((err) => toastr.error(err));
setIsLoading(true);
window.DocSpace.navigate(`${url}?${newFilter.toUrlParams()}`, { state });
};
setThirdpartyInfo = (providerKey) => {
@ -1943,17 +2004,19 @@ class FilesActionStore {
onMarkAsRead = (item) => this.markAsRead([], [`${item.id}`], item);
openFileAction = (item) => {
const {
isLoading,
setIsLoading,
fetchFiles,
openDocEditor,
isPrivacyFolder,
} = this.filesStore;
const { openDocEditor, isPrivacyFolder } = this.filesStore;
const { isLoading } = this.clientLoadingStore;
const { isRecycleBinFolder } = this.treeFoldersStore;
const { setMediaViewerData } = this.mediaViewerDataStore;
const { setConvertDialogVisible, setConvertItem } = this.dialogsStore;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const isMediaOrImage =
item.viewAccessability?.ImageView || item.viewAccessability?.MediaView;
const canConvert = item.viewAccessability?.Convert;
@ -1966,14 +2029,21 @@ class FilesActionStore {
if (isRecycleBinFolder || isLoading) return;
if (isFolder) {
const { isRoom, rootFolderType, title } = item;
setIsLoading(true);
fetchFiles(id, null, true, false)
.catch((err) => {
toastr.error(err);
setIsLoading(false);
})
.finally(() => setIsLoading(false));
const path = getCategoryUrl(
getCategoryTypeByFolderType(rootFolderType, id),
id
);
const filter = FilesFilter.getDefault();
filter.folder = id;
const state = { title, isRoot: false, rootFolderType, isRoom };
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });
} else {
if (canConvert) {
setConvertItem({ ...item, isOpen: true });
@ -2018,8 +2088,15 @@ class FilesActionStore {
};
onClickBack = () => {
const { roomType, parentId, setSelectedFolder } = this.selectedFolderStore;
const { roomType } = this.selectedFolderStore;
const { setSelectedNode } = this.treeFoldersStore;
const { clearFiles } = this.filesStore;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const categoryType = getCategoryType(location);
const isRoom = !!roomType;
@ -2051,49 +2128,94 @@ class FilesActionStore {
}
if (categoryType === CategoryType.Settings) {
setSelectedFolder(null);
clearFiles();
const path = getCategoryUrl(CategoryType.Settings);
setSelectedNode(["common"]);
return navigate(path);
}
if (categoryType === CategoryType.Accounts) {
setSelectedFolder(null);
const accountsFilter = AccountsFilter.getDefault();
params = accountsFilter.toUrlParams();
const path = getCategoryUrl(CategoryType.Accounts);
clearFiles();
setIsLoading(true);
setSelectedNode(["accounts", "filter"]);
return navigate(`${path}?${params}`);
}
};
moveToRoomsPage = () => {
const { setIsLoading, fetchRooms, setAlreadyFetchingRooms } =
this.filesStore;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const categoryType = getCategoryType(location);
setIsLoading(true);
setAlreadyFetchingRooms(true);
const filter = RoomsFilter.getDefault();
const path = getCategoryUrl(categoryType);
const state = {
title:
this.selectedFolderStore?.navigationPath[
this.selectedFolderStore?.navigationPath.length - 1
]?.title || "",
isRoot: true,
rootFolderType: this.selectedFolderStore.rootFolderType,
};
setIsLoading(true);
if (categoryType == CategoryType.Archive) {
filter.searchArea = RoomSearchArea.Archive;
}
fetchRooms(null, filter).finally(() => {
setIsLoading(false);
});
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });
};
backToParentFolder = () => {
const { setIsLoading, fetchFiles } = this.filesStore;
const { setIsSectionFilterLoading } = this.clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
let id = this.selectedFolderStore.parentId;
const { navigationPath, rootFolderType } = this.selectedFolderStore;
if (!id) {
const urlFilter = getObjectByLocation(location);
id = urlFilter.folder;
}
const path = getCategoryUrl(
getCategoryTypeByFolderType(rootFolderType, id),
id
);
const filter = FilesFilter.getDefault();
filter.folder = id;
const state = {
title: navigationPath[0]?.title || "",
isRoot: navigationPath.length === 1,
rootFolderType: rootFolderType,
};
setIsLoading(true);
fetchFiles(id, null, true, false).finally(() => setIsLoading(false));
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });
};
setGroupMenuBlocked = (blocked) => {

View File

@ -19,14 +19,16 @@ import config from "PACKAGE_FILE";
import { thumbnailStatuses } from "@docspace/client/src/helpers/filesConstants";
import { openDocEditor as openEditor } from "@docspace/client/src/helpers/filesUtils";
import { getDaysRemaining } from "@docspace/common/utils";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import {
getCategoryType,
getCategoryUrl,
getCategoryTypeByFolderType,
} from "SRC_DIR/helpers/utils";
import { isDesktop } from "@docspace/components/utils/device";
import { getContextMenuKeysByType } from "SRC_DIR/helpers/plugins";
import { PluginContextMenuItemType } from "SRC_DIR/helpers/plugins/constants";
import { CategoryType } from "SRC_DIR/helpers/constants";
import debounce from "lodash.debounce";
const { FilesFilter, RoomsFilter } = api;
@ -49,12 +51,10 @@ class FilesStore {
treeFoldersStore;
filesSettingsStore;
thirdPartyStore;
clientLoadingStore;
accessRightsStore;
isLoaded = false;
isLoading = false;
viewAs =
isMobile && storageViewAs !== "tile" ? "row" : storageViewAs || "table";
@ -69,7 +69,6 @@ class FilesStore {
tooltipPageY = 0;
startDrag = false;
firstLoad = true;
alreadyFetchingRooms = false;
files = [];
@ -136,7 +135,8 @@ class FilesStore {
treeFoldersStore,
filesSettingsStore,
thirdPartyStore,
accessRightsStore
accessRightsStore,
clientLoadingStore
) {
const pathname = window.location.pathname.toLowerCase();
this.isEditor = pathname.indexOf("doceditor") !== -1;
@ -149,6 +149,7 @@ class FilesStore {
this.filesSettingsStore = filesSettingsStore;
this.thirdPartyStore = thirdPartyStore;
this.accessRightsStore = accessRightsStore;
this.clientLoadingStore = clientLoadingStore;
this.roomsController = new AbortController();
this.filesController = new AbortController();
@ -157,7 +158,7 @@ class FilesStore {
socketHelper.on("s:modify-folder", async (opt) => {
console.log("[WS] s:modify-folder", opt);
if (!(this.isLoading || this.operationAction))
if (!(this.clientLoadingStore.isLoading || this.operationAction))
switch (opt?.cmd) {
case "create":
this.wsModifyFolderCreate(opt);
@ -183,10 +184,12 @@ class FilesStore {
this.selectedFolderStore.foldersCount--;
this.authStore.infoPanelStore.reloadSelection();
}
this.treeFoldersStore.updateTreeFoldersItem(opt);
});
socketHelper.on("refresh-folder", (id) => {
if (!id || this.isLoading) return;
if (!id || this.clientLoadingStore.isLoading) return;
//console.log(
// `selected folder id ${this.selectedFolderStore.id} an changed folder id ${id}`
@ -587,6 +590,13 @@ class FilesStore {
}
};
clearFiles = () => {
this.setFolders([]);
this.setFiles([]);
this.selectedFolderStore.setSelectedFolder(null);
};
setActiveFiles = (activeFiles) => {
this.activeFiles = activeFiles;
};
@ -595,10 +605,6 @@ class FilesStore {
this.activeFolders = activeFolders;
};
setIsLoaded = (isLoaded) => {
this.isLoaded = isLoaded;
};
setViewAs = (viewAs) => {
this.viewAs = viewAs;
localStorage.setItem("viewAs", viewAs);
@ -613,10 +619,6 @@ class FilesStore {
this.dragging = dragging;
};
setIsLoading = (isLoading) => {
this.isLoading = isLoading;
};
setTooltipPosition = (tooltipPageX, tooltipPageY) => {
this.tooltipPageX = tooltipPageX;
this.tooltipPageY = tooltipPageY;
@ -682,7 +684,7 @@ class FilesStore {
updateTempContent();
if (!isAuthenticated) {
return this.setIsLoaded(true);
return this.clientLoadingStore.setIsLoaded(true);
} else {
updateTempContent(isAuthenticated);
}
@ -711,7 +713,12 @@ class FilesStore {
}
requests.push(getFilesSettings());
return Promise.all(requests).then(() => this.setIsInit(true));
return Promise.all(requests).then(() => {
this.clientLoadingStore.setIsArticleLoading(false);
this.clientLoadingStore.setFirstLoad(false);
this.setIsInit(true);
});
};
setIsInit = (isInit) => {
@ -720,9 +727,12 @@ class FilesStore {
reset = () => {
this.isInit = false;
this.isLoaded = false;
this.isLoading = false;
this.firstLoad = true;
this.clientLoadingStore.setIsLoaded(false);
this.clientLoadingStore.setIsSectionHeaderLoading(true);
this.clientLoadingStore.setIsSectionFilterLoading(true);
this.clientLoadingStore.setIsSectionBodyLoading(true);
this.clientLoadingStore.setIsArticleLoading(true);
this.clientLoadingStore.setFirstLoad(true);
this.alreadyFetchingRooms = false;
@ -733,9 +743,6 @@ class FilesStore {
this.bufferSelection = null;
this.selected = "close";
};
setFirstLoad = (firstLoad) => {
this.firstLoad = firstLoad;
};
setFiles = (files) => {
const { socketHelper } = this.authStore.settingsStore;
@ -1027,7 +1034,7 @@ class FilesStore {
const value = `${filter.sortBy},${filter.pageCount},${filter.sortOrder}`;
localStorage.setItem(key, value);
this.setFilterUrl(filter);
// this.setFilterUrl(filter);
this.filter = filter;
runInAction(() => {
@ -1054,7 +1061,7 @@ class FilesStore {
if (!this.authStore.settingsStore.withPaging) filter.pageCount = 100;
this.setFilterUrl(filter, true);
// this.setFilterUrl(filter, true);
this.roomsFilter = filter;
runInAction(() => {
@ -1095,14 +1102,14 @@ class FilesStore {
if (newUrl === currentUrl) return;
window.DocSpace.navigate(newUrl, {
state: {
fromAccounts:
window.DocSpace.location.pathname.includes("accounts/filter"),
fromSettings: window.DocSpace.location.pathname.includes("settings"),
},
replace: !location.search,
});
// window.DocSpace.navigate(newUrl, {
// state: {
// fromAccounts:
// window.DocSpace.location.pathname.includes("accounts/filter"),
// fromSettings: window.DocSpace.location.pathname.includes("settings"),
// },
// replace: !location.search,
// });
};
isEmptyLastPageAfterOperation = (newSelection) => {
@ -1150,7 +1157,7 @@ class FilesStore {
clearSelection = true
) => {
const { setSelectedNode } = this.treeFoldersStore;
if (this.isLoading) {
if (this.clientLoadingStore.isLoading) {
this.roomsController.abort();
this.roomsController = new AbortController();
}
@ -1158,8 +1165,12 @@ class FilesStore {
const filterData = filter ? filter.clone() : FilesFilter.getDefault();
filterData.folder = folderId;
if (folderId === "@my" && this.authStore.userStore.user.isVisitor)
return this.fetchRooms();
if (folderId === "@my" && this.authStore.userStore.user.isVisitor) {
const url = getCategoryUrl(CategoryType.Shared);
return window.DocSpace.navigate(
`${url}?${RoomsFilter.getDefault().toUrlParams()}`
);
}
this.setIsErrorRoomNotAvailable(false);
this.setIsLoadedFetchFiles(false);
@ -1318,6 +1329,8 @@ class FilesStore {
...{ new: data.new },
});
this.clientLoadingStore.setIsSectionHeaderLoading(false);
const selectedFolder = {
selectedFolder: { ...this.selectedFolderStore },
};
@ -1370,6 +1383,13 @@ class FilesStore {
})
.finally(() => {
this.setIsLoadedFetchFiles(true);
if (window?.DocSpace?.location?.state?.highlightFileId) {
this.setHighlightFile({
highlightFileId: window.DocSpace.location.state.highlightFileId,
isFileHasExst: window.DocSpace.location.state.isFileHasExst,
});
}
});
};
@ -1382,7 +1402,7 @@ class FilesStore {
) => {
const { setSelectedNode, roomsFolderId } = this.treeFoldersStore;
if (this.isLoading) {
if (this.clientLoadingStore.isLoading) {
this.filesController.abort();
this.filesController = new AbortController();
}
@ -1484,6 +1504,8 @@ class FilesStore {
...{ new: data.new },
});
this.clientLoadingStore.setIsSectionHeaderLoading(false);
const selectedFolder = {
selectedFolder: { ...this.selectedFolderStore },
};
@ -2765,12 +2787,8 @@ class FilesStore {
}
get cbMenuItems() {
const {
isDocument,
isPresentation,
isSpreadsheet,
isArchive,
} = this.filesSettingsStore;
const { isDocument, isPresentation, isSpreadsheet, isArchive } =
this.filesSettingsStore;
let cbMenu = ["all"];
const filesItems = [...this.files, ...this.folders];
@ -3307,7 +3325,7 @@ class FilesStore {
const isRooms = isRoomsFolder || isArchiveFolder;
const filterTotal = isRooms ? this.roomsFilter.total : this.filter.total;
if (this.isLoading) return false;
if (this.clientLoadingStore.isLoading) return false;
return this.filesList.length < filterTotal;
}
@ -3316,7 +3334,12 @@ class FilesStore {
};
fetchMoreFiles = async () => {
if (!this.hasMoreFiles || this.filesIsLoading || this.isLoading) return;
if (
!this.hasMoreFiles ||
this.filesIsLoading ||
this.clientLoadingStore.isLoading
)
return;
const { isRoomsFolder, isArchiveFolder } = this.treeFoldersStore;

View File

@ -1,35 +0,0 @@
import { makeAutoObservable } from "mobx";
class LoadingStore {
isLoading = false;
isLoaded = false;
isRefresh = false;
firstLoad = true;
profileLoaded = true;
constructor() {
makeAutoObservable(this);
}
setIsLoading = (isLoading) => {
this.isLoading = isLoading;
};
setIsLoaded = (isLoaded) => {
this.isLoaded = isLoaded;
};
setIsRefresh = (isRefresh) => {
this.isRefresh = isRefresh;
};
setFirstLoad = (firstLoad) => {
this.firstLoad = firstLoad;
};
setLoadedProfile = (profileLoaded) => {
this.profileLoaded = profileLoaded;
};
}
export default LoadingStore;

View File

@ -16,7 +16,7 @@ import HeaderMenuStore from "./HeaderMenuStore";
import AvatarEditorStore from "./AvatarEditorStore";
import InviteLinksStore from "./InviteLinksStore";
import DialogStore from "./DialogStore";
import LoadingStore from "./LoadingStore";
import AccountsContextOptionsStore from "./AccountsContextOptionsStore";
import {
isMobile,
@ -44,7 +44,6 @@ class PeopleStore {
avatarEditorStore = null;
inviteLinksStore = null;
dialogStore = null;
loadingStore = null;
setupStore = null;
accessRightsStore = null;
isInit = false;
@ -64,7 +63,7 @@ class PeopleStore {
this.avatarEditorStore = new AvatarEditorStore(this);
this.inviteLinksStore = new InviteLinksStore(this);
this.dialogStore = new DialogStore();
this.loadingStore = new LoadingStore();
this.setupStore = setupStore;
this.accessRightsStore = accessRightsStore;
this.dialogsStore = dialogsStore;
@ -86,21 +85,16 @@ class PeopleStore {
await this.authStore.settingsStore.getPortalPasswordSettings();
await this.authStore.tfaStore.getTfaType();
this.loadingStore.setIsLoaded(true);
};
reset = () => {
this.isInit = false;
this.loadingStore.setIsLoaded(false);
};
resetFilter = () => {
const { getUsersList } = this.usersStore;
const filter = Filter.getDefault();
return getUsersList(filter, true);
window.DocSpace.navigate(`accounts/filter?${filter.toUrlParams()}`);
};
onChangeType = (e) => {
@ -167,10 +161,8 @@ class PeopleStore {
};
changeStatus = (status, users) => {
const {
setChangeUserStatusDialogVisible,
setDialogData,
} = this.dialogStore;
const { setChangeUserStatusDialogVisible, setDialogData } =
this.dialogStore;
const userIDs = users.map((user) => {
return user?.id ? user.id : user;
@ -195,10 +187,8 @@ class PeopleStore {
hasUsersToRemove,
hasFreeUsers,
} = this.selectionStore;
const {
setSendInviteDialogVisible,
setDeleteDialogVisible,
} = this.dialogStore;
const { setSendInviteDialogVisible, setDeleteDialogVisible } =
this.dialogStore;
const { isOwner } = this.authStore.userStore.user;

View File

@ -1,4 +1,5 @@
import { makeAutoObservable } from "mobx";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
class SelectedFolderStore {
folders = null;
@ -135,6 +136,8 @@ class SelectedFolderStore {
if (!selectedFolderItems.includes("roomType")) this.roomType = null;
setDocumentTitle(selectedFolder.title);
for (let key of selectedFolderItems) {
if (key in this) {
this[key] = selectedFolder[key];

View File

@ -23,15 +23,12 @@ class SelectedGroupStore {
const { filter } = this.peopleStore.filterStore;
const { clearSelection } = this.peopleStore.selectionStore;
const { getUsersList } = this.peopleStore.usersStore;
const { setIsLoading } = this.peopleStore.loadingStore;
setIsLoading(true);
let newFilter = filter.clone();
newFilter.group = groupId;
clearSelection();
getUsersList(newFilter).finally(() => setIsLoading(false));
getUsersList(newFilter);
};
setSelectedGroup = (groupId) => {

View File

@ -4,6 +4,7 @@ import { FolderType } from "@docspace/common/constants";
class TreeFoldersStore {
selectedFolderStore;
authStore;
treeFolders = [];
selectedTreeNode = [];
@ -11,18 +12,71 @@ class TreeFoldersStore {
rootFoldersTitles = {};
isLoadingNodes = false;
constructor(selectedFolderStore) {
constructor(selectedFolderStore, authStore) {
makeAutoObservable(this);
this.selectedFolderStore = selectedFolderStore;
this.authStore = authStore;
}
fetchTreeFolders = async () => {
const treeFolders = await getFoldersTree();
this.setRootFoldersTitles(treeFolders);
this.setTreeFolders(treeFolders);
this.listenTreeFolders(treeFolders);
return treeFolders;
};
listenTreeFolders = (treeFolders) => {
const { socketHelper } = this.authStore.settingsStore;
if (treeFolders.length > 0) {
socketHelper.emit({
command: "unsubscribe",
data: {
roomParts: treeFolders.map((f) => `DIR-${f.id}`),
individual: true,
},
});
socketHelper.emit({
command: "subscribe",
data: {
roomParts: treeFolders.map((f) => `DIR-${f.id}`),
individual: true,
},
});
}
};
updateTreeFoldersItem = (opt) => {
if (opt?.data && opt?.cmd === "create") {
const data = JSON.parse(opt.data);
const parentId = opt?.type === "file" ? data.folderId : data.parentId;
const idx = this.treeFolders.findIndex((f) => f.id === parentId);
if (idx >= 0) {
if (opt.type === "file") {
this.treeFolders[idx].filesCount++;
if (this.treeFolders[idx].files) {
this.treeFolders[idx].files.push(data);
} else {
this.treeFolders[idx].files = [data];
}
} else {
this.treeFolders[idx].foldersCount++;
if (this.treeFolders[idx].folders) {
this.treeFolders[idx].folders.push(data);
} else {
this.treeFolders[idx].folders = [data];
}
}
}
}
};
resetTreeItemCount = () => {
this.treeFolders.map((item) => {
return (item.newItems = 0);
@ -145,6 +199,10 @@ class TreeFoldersStore {
return this.archiveFolder ? this.archiveFolder.id : null;
}
get recycleBinFolderId() {
return this.recycleBinFolder ? this.recycleBinFolder.id : null;
}
get isPersonalRoom() {
return (
this.myFolder &&

View File

@ -18,8 +18,9 @@ class WebhooksStore {
startIndex = 0;
totalItems = 0;
developerToolsTab = 0;
titleType = "default"; // "default", "history" or "details"
currentWebhook = {};
eventDetails = {};
FETCH_COUNT = 100;
constructor() {
makeAutoObservable(this);
@ -110,27 +111,38 @@ class WebhooksStore {
};
fetchHistoryItems = async (params) => {
this.totalItems = 0;
this.startIndex = 0;
const historyData = await getWebhooksJournal({ ...params, startIndex: this.startIndex });
const count = params.count ? params.count : this.FETCH_COUNT;
const historyData = await getWebhooksJournal({
...params,
startIndex: this.startIndex,
count: count,
});
runInAction(() => {
this.startIndex = params.count;
this.startIndex = count;
this.historyItems = historyData.items;
this.totalItems = historyData.total;
});
};
fetchMoreItems = async (params) => {
const historyData = await getWebhooksJournal({ ...params, startIndex: this.startIndex });
const count = params.count ? params.count : this.FETCH_COUNT;
const historyData = await getWebhooksJournal({
...params,
startIndex: this.startIndex,
count: count,
});
runInAction(() => {
this.startIndex = this.startIndex + params.count;
this.startIndex = this.startIndex + count;
this.historyItems = [...this.historyItems, ...historyData.items];
});
};
getEvent = async (eventId) => {
fetchEventData = async (eventId) => {
const data = await getWebhooksJournal({ eventId });
return data.items[0];
this.eventDetails = data.items[0];
};
get hasMoreItems() {
return this.totalItems > this.historyItems.length;
return this.totalItems > this.startIndex;
}
get isWebhooksEmpty() {
@ -203,19 +215,9 @@ class WebhooksStore {
return this.checkedEventIds.length > 0 && !this.areAllIdsChecked;
}
get isHeaderVisible() {
get isGroupMenuVisible() {
return this.checkedEventIds.length !== 0;
}
setTitleDefault = () => {
this.titleType = "default";
};
setTitleHistory = () => {
this.titleType = "history";
};
setTitleDetails = () => {
this.titleType = "details";
};
}
export default WebhooksStore;

View File

@ -36,9 +36,12 @@ import TableStore from "./TableStore";
import CreateEditRoomStore from "./CreateEditRoomStore";
import WebhooksStore from "./WebhooksStore";
import ClientLoadingStore from "./ClientLoadingStore";
const oformsStore = new OformsStore(authStore);
const clientLoadingStore = new ClientLoadingStore();
const selectedFolderStore = new SelectedFolderStore(authStore.settingsStore);
const paymentStore = new PaymentStore();
@ -52,7 +55,7 @@ const ssoStore = new SsoFormStore();
const tagsStore = new TagsStore();
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore);
const treeFoldersStore = new TreeFoldersStore(selectedFolderStore, authStore);
const settingsStore = new SettingsStore(thirdPartyStore, treeFoldersStore);
const accessRightsStore = new AccessRightsStore(authStore, selectedFolderStore);
@ -64,6 +67,7 @@ const filesStore = new FilesStore(
settingsStore,
thirdPartyStore,
accessRightsStore,
clientLoadingStore,
);
const mediaViewerDataStore = new MediaViewerDataStore(filesStore, settingsStore);
@ -79,12 +83,7 @@ const dialogsStore = new DialogsStore(
versionHistoryStore,
);
const peopleStore = new PeopleStore(
authStore,
setupStore,
accessRightsStore,
dialogsStore,
);
const peopleStore = new PeopleStore(authStore, setupStore, accessRightsStore, dialogsStore);
const uploadDataStore = new UploadDataStore(
authStore,
@ -107,6 +106,7 @@ const filesActionsStore = new FilesActionsStore(
dialogsStore,
mediaViewerDataStore,
accessRightsStore,
clientLoadingStore,
);
const contextOptionsStore = new ContextOptionsStore(
@ -156,7 +156,8 @@ const createEditRoomStore = new CreateEditRoomStore(
thirdPartyStore,
authStore.settingsStore,
authStore.infoPanelStore,
authStore.currentQuotaStore
authStore.currentQuotaStore,
clientLoadingStore,
);
const webhooksStore = new WebhooksStore();
@ -198,6 +199,7 @@ const store = {
createEditRoomStore,
webhooksStore,
clientLoadingStore,
};
export default store;

View File

@ -40,13 +40,13 @@ const Article = ({
isBannerVisible,
isLiveChatAvailable,
onLogoClickAction,
...rest
}) => {
const [articleHeaderContent, setArticleHeaderContent] = React.useState(null);
const [
articleMainButtonContent,
setArticleMainButtonContent,
] = React.useState(null);
const [articleMainButtonContent, setArticleMainButtonContent] =
React.useState(null);
const [articleBodyContent, setArticleBodyContent] = React.useState(null);
const [correctTabletHeight, setCorrectTabletHeight] = React.useState(null);
@ -156,7 +156,10 @@ const Article = ({
correctTabletHeight={correctTabletHeight}
{...rest}
>
<SubArticleHeader showText={showText}>
<SubArticleHeader
showText={showText}
onLogoClickAction={onLogoClickAction}
>
{articleHeaderContent ? articleHeaderContent.props.children : null}
</SubArticleHeader>

View File

@ -145,7 +145,7 @@ StyledArticle.defaultProps = { theme: Base };
const StyledArticleHeader = styled.div`
height: 24px;
padding: 24px 21px 21px 20px;
padding: 22px 21px 23px 20px;
margin: 0;
display: flex;
justify-content: flex-start;

View File

@ -17,6 +17,7 @@ const ArticleHeader = ({
showText,
children,
onClick,
onLogoClickAction,
isBurgerLoading,
whiteLabelLogoUrls,
theme,
@ -25,7 +26,11 @@ const ArticleHeader = ({
const navigate = useNavigate();
const isTabletView = (isTabletUtils() || isTablet) && !isMobileOnly;
const onLogoClick = () => navigate("/");
const onLogoClick = () => {
onLogoClickAction && onLogoClickAction();
navigate("/");
};
const burgerLogo = !theme.isBase
? getLogoFromPath(whiteLabelLogoUrls[5].path.dark)
@ -46,16 +51,10 @@ const ArticleHeader = ({
)}
{!isTabletView && isBurgerLoading ? (
<Loaders.ArticleHeader height="28px" width="211px" />
<Loaders.ArticleHeader height="24px" width="211px" />
) : (
<StyledHeading showText={showText} size="large">
{isTabletView ? (
<img className="logo-icon_svg" src={logo} onClick={onLogoClick} />
) : (
<Link to="/">
<img className="logo-icon_svg" src={logo} />
</Link>
)}
<img className="logo-icon_svg" src={logo} onClick={onLogoClick} />
</StyledHeading>
)}
</StyledArticleHeader>

View File

@ -50,6 +50,7 @@ const Navigation = ({
isDesktop: isDesktopClient,
isRoom,
hideInfoPanel,
showRootFolderTitle,
...rest
}) => {
const [isOpen, setIsOpen] = React.useState(false);
@ -128,6 +129,36 @@ const Navigation = ({
onBackToParentFolder && onBackToParentFolder();
}, [onBackToParentFolder]);
const showRootFolderNavigation =
showRootFolderTitle &&
navigationItems &&
navigationItems.length > 1 &&
!isSmallTabletUtils() &&
!isMobileOnly;
const navigationTitleNode = (
<Text
title={title}
isOpen={false}
isRootFolder={isRootFolder}
onClick={toggleDropBox}
/>
);
const navigationTitleContainerNode = showRootFolderNavigation ? (
<div className="title-container">
<Text
title={navigationItems[navigationItems.length - 2].title}
isOpen={false}
isRootFolder={isRootFolder}
isRootFolderTitle
/>
{navigationTitleNode}
</div>
) : (
navigationTitleNode
);
return (
<Consumer>
{(context) => (
@ -162,6 +193,7 @@ const Navigation = ({
isInfoPanelVisible={isInfoPanelVisible}
onClickAvailable={onClickAvailable}
isDesktopClient={isDesktopClient}
showRootFolderNavigation={showRootFolderNavigation}
/>
</>
)}
@ -181,12 +213,9 @@ const Navigation = ({
isRootFolder={isRootFolder}
onBackToParentFolder={onBackToParentFolder}
/>
<Text
title={title}
isOpen={false}
isRootFolder={isRootFolder}
onClick={toggleDropBox}
/>
{navigationTitleContainerNode}
<ControlButtons
personal={personal}
isRootFolder={isRootFolder}

View File

@ -36,16 +36,25 @@ const StyledContainer = styled.div`
}
.arrow-button {
padding-top: 2px;
width: 17px;
min-width: 17px;
}
.title-container {
display: grid;
grid-template-columns: minmax(1px, max-content) auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.navigation-header-separator {
display: ${isMobileOnly ? "none" : "block"};
padding-left: 16px;
border-right: ${(props) =>
`1px solid ${props.theme.navigation.icon.stroke}`};
height: 21px;
@media ${mobile} {
display: none;
}

View File

@ -44,6 +44,11 @@ const StyledBox = styled.div`
filter: drop-shadow(0px 12px 40px rgba(4, 15, 27, 0.12));
border-radius: 0px 0px 6px 6px;
.title-container {
display: grid;
grid-template-columns: minmax(1px, max-content) auto;
}
@media ${tablet} {
width: ${({ dropBoxWidth }) => dropBoxWidth + "px"};
left: -16px;
@ -109,6 +114,7 @@ const DropBox = React.forwardRef(
isOpen,
isDesktop,
isDesktopClient,
showRootFolderNavigation,
},
ref
) => {
@ -144,6 +150,23 @@ const DropBox = React.forwardRef(
);
}, [sectionHeight]);
const navigationTitleNode = (
<Text title={title} isOpen={true} onClick={toggleDropBox} />
);
const navigationTitleContainerNode = showRootFolderNavigation ? (
<div className="title-container">
<Text
title={navigationItems[navigationItems.length - 2].title}
isOpen={true}
isRootFolderTitle
/>
{navigationTitleNode}
</div>
) : (
navigationTitleNode
);
return (
<>
<StyledBox
@ -164,7 +187,9 @@ const DropBox = React.forwardRef(
isRootFolder={isRootFolder}
onBackToParentFolder={onBackToParentFolder}
/>
<Text title={title} isOpen={true} onClick={toggleDropBox} />
{navigationTitleContainerNode}
<ControlButtons
isDesktop={isDesktop}
personal={personal}

View File

@ -3,6 +3,7 @@ import styled, { css } from "styled-components";
import PropTypes from "prop-types";
import ExpanderDownIcon from "PUBLIC_DIR/images/expander-down.react.svg";
import ArrowIcon from "PUBLIC_DIR/images/arrow.react.svg";
import commonIconsStyles from "@docspace/components/utils/common-icons-style";
import Heading from "@docspace/components/heading";
@ -19,13 +20,17 @@ const StyledTextContainer = styled.div`
position: relative;
overflow: hidden;
${(props) =>
!props.isRootFolder && !props.isRootFolderTitle && "cursor: pointer"};
${(props) => props.isRootFolderTitle && "padding-right: 3px"};
${(props) => !props.isRootFolder && "cursor: pointer"};
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
${(props) =>
!props.isRootFolderTitle &&
css`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`};
`;
const StyledHeading = styled(Heading)`
@ -35,6 +40,10 @@ const StyledHeading = styled(Heading)`
margin: 0;
${(props) =>
props.isRootFolderTitle &&
`color: ${props.theme.navigation.rootFolderTitleColor}`};
@media ${tablet} {
font-size: 21px;
line-height: 28px;
@ -65,6 +74,16 @@ const StyledExpanderDownIcon = styled(ExpanderDownIcon)`
${commonIconsStyles};
`;
const StyledArrowIcon = styled(ArrowIcon)`
height: 12px;
min-width: 12px;
padding-left: 6px;
path {
fill: ${(props) => props.theme.navigation.rootFolderTitleColor};
}
`;
StyledExpanderDownIcon.defaultProps = { theme: Base };
const StyledExpanderDownIconRotate = styled(ExpanderDownIcon)`
@ -83,18 +102,34 @@ const StyledExpanderDownIconRotate = styled(ExpanderDownIcon)`
StyledExpanderDownIconRotate.defaultProps = { theme: Base };
const Text = ({ title, isRootFolder, isOpen, onClick, ...rest }) => {
const Text = ({
title,
isRootFolder,
isOpen,
isRootFolderTitle,
onClick,
...rest
}) => {
return (
<StyledTextContainer
isRootFolder={isRootFolder}
onClick={onClick}
isOpen={isOpen}
isRootFolderTitle={isRootFolderTitle}
{...rest}
>
<StyledHeading type="content" title={title} truncate={true}>
<StyledHeading
type="content"
title={title}
truncate={true}
isRootFolderTitle={isRootFolderTitle}
>
{title}
</StyledHeading>
{!isRootFolder ? (
{isRootFolderTitle && <StyledArrowIcon />}
{!isRootFolderTitle && !isRootFolder ? (
isOpen ? (
<StyledExpanderDownIconRotate />
) : (

View File

@ -19,7 +19,7 @@ const isDesktopEditors = window["AscDesktopEditor"] !== undefined;
class SettingsStore {
isLoading = false;
isLoaded = false;
isBurgerLoading = false;
isBurgerLoading = true;
checkedMaintenance = false;
maintenanceExist = false;

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