Merge branch 'develop' into bugfix/rows-jump-styles
This commit is contained in:
commit
f3a8316a7d
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docspace",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/client",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"private": true,
|
||||
"homepage": "",
|
||||
"scripts": {
|
||||
|
@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { useLocation, Outlet } from "react-router-dom";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import Article from "@docspace/common/components/Article";
|
||||
import Article from "@docspace/shared/components/article";
|
||||
import {
|
||||
updateTempContent,
|
||||
showLoader,
|
||||
@ -20,6 +20,7 @@ import {
|
||||
ArticleHeaderContent,
|
||||
ArticleMainButtonContent,
|
||||
} from "./components/Article";
|
||||
import ArticleWrapper from "./components/ArticleWrapper";
|
||||
|
||||
const ClientArticle = React.memo(
|
||||
({
|
||||
@ -29,7 +30,7 @@ const ClientArticle = React.memo(
|
||||
showArticleLoader,
|
||||
}) => {
|
||||
return (
|
||||
<Article
|
||||
<ArticleWrapper
|
||||
withMainButton={withMainButton}
|
||||
onLogoClickAction={() => {
|
||||
setIsFilterLoading(true, false);
|
||||
@ -48,7 +49,7 @@ const ClientArticle = React.memo(
|
||||
<Article.Body>
|
||||
<ArticleBodyContent />
|
||||
</Article.Body>
|
||||
</Article>
|
||||
</ArticleWrapper>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -15,10 +15,10 @@ import AccountsFilter from "@docspace/shared/api/people/filter";
|
||||
|
||||
import Banner from "./Banner";
|
||||
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
|
||||
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
|
||||
import { CategoryType } from "SRC_DIR/helpers/constants";
|
||||
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
|
||||
const StyledBlock = styled.div`
|
||||
padding: 0 20px;
|
||||
@ -221,7 +221,7 @@ const ArticleBodyContent = (props) => {
|
||||
return setActiveItemId(rootFolderId || roomsFolderId);
|
||||
}
|
||||
|
||||
if (location.pathname.includes("/products/files/#preview")) {
|
||||
if (location.pathname.includes(MEDIA_VIEW_URL)) {
|
||||
setActiveItemId(rootFolderId);
|
||||
}
|
||||
}, [
|
||||
@ -239,7 +239,7 @@ const ArticleBodyContent = (props) => {
|
||||
setIsBurgerLoading(showArticleLoader);
|
||||
}, [showArticleLoader]);
|
||||
|
||||
if (showArticleLoader) return <Loaders.ArticleFolder />;
|
||||
if (showArticleLoader) return <ArticleFolderLoader />;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React from "react";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import withLoader from "../../../HOCs/withLoader";
|
||||
import { ArticleHeaderLoader } from "@docspace/shared/skeletons/article";
|
||||
|
||||
const ArticleHeaderContent = ({ currentModuleName }) => {
|
||||
return <>{currentModuleName}</>;
|
||||
@ -14,6 +15,6 @@ export default inject(({ auth }) => {
|
||||
};
|
||||
})(
|
||||
withTranslation([])(
|
||||
withLoader(observer(ArticleHeaderContent))(<Loaders.ArticleHeader />)
|
||||
withLoader(observer(ArticleHeaderContent))(<ArticleHeaderLoader />)
|
||||
)
|
||||
);
|
||||
|
@ -22,7 +22,6 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import { encryptionUploadDialog } from "../../../helpers/desktop";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
|
||||
@ -34,6 +33,7 @@ import styled, { css } from "styled-components";
|
||||
|
||||
import { resendInvitesAgain } from "@docspace/shared/api/people";
|
||||
import { getCorrectFourValuesStyle } from "@docspace/shared/utils";
|
||||
import { ArticleButtonLoader } from "@docspace/shared/skeletons/article";
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
font-weight: 700;
|
||||
@ -512,7 +512,7 @@ const ArticleMainButtonContent = (props) => {
|
||||
}
|
||||
|
||||
if (showArticleLoader)
|
||||
return isMobileArticle ? null : <Loaders.ArticleButton height="32px" />;
|
||||
return isMobileArticle ? null : <ArticleButtonLoader height="32px" />;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
141
packages/client/src/components/ArticleWrapper/index.tsx
Normal file
141
packages/client/src/components/ArticleWrapper/index.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import Article from "@docspace/shared/components/article";
|
||||
import { ArticleProps } from "@docspace/shared/components/article/Article.types";
|
||||
|
||||
const ArticleWrapper = (props: ArticleProps) => {
|
||||
return <Article {...props} />;
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ auth, uploadDataStore, profileActionsStore, dialogsStore }: any) => {
|
||||
const {
|
||||
settingsStore,
|
||||
userStore,
|
||||
isLiveChatAvailable,
|
||||
bannerStore,
|
||||
currentQuotaStore,
|
||||
|
||||
isPaymentPageAvailable,
|
||||
isTeamTrainingAlertAvailable,
|
||||
isSubmitToGalleryAlertAvailable,
|
||||
currentTariffStatusStore,
|
||||
isEnterprise,
|
||||
} = auth;
|
||||
|
||||
const { getActions, getUserRole, onProfileClick } = profileActionsStore;
|
||||
|
||||
const { withSendAgain, user } = userStore;
|
||||
|
||||
const { isBannerVisible } = bannerStore;
|
||||
|
||||
const { primaryProgressDataStore, secondaryProgressDataStore } =
|
||||
uploadDataStore;
|
||||
|
||||
const { email, displayName } = user;
|
||||
|
||||
const isAdmin = user?.isAdmin;
|
||||
|
||||
const { visible: primaryProgressDataVisible } = primaryProgressDataStore;
|
||||
const { visible: secondaryProgressDataStoreVisible } =
|
||||
secondaryProgressDataStore;
|
||||
|
||||
const showProgress =
|
||||
primaryProgressDataVisible || secondaryProgressDataStoreVisible;
|
||||
|
||||
const {
|
||||
showText,
|
||||
setShowText,
|
||||
articleOpen,
|
||||
setIsMobileArticle,
|
||||
toggleShowText,
|
||||
toggleArticleOpen,
|
||||
currentColorScheme,
|
||||
setArticleOpen,
|
||||
mainBarVisible,
|
||||
zendeskKey,
|
||||
isMobileArticle,
|
||||
|
||||
currentDeviceType,
|
||||
standalone,
|
||||
articleAlertsData,
|
||||
incrementIndexOfArticleAlertsData,
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
removeAlertFromArticleAlertsData,
|
||||
bookTrainingEmail,
|
||||
} = settingsStore;
|
||||
|
||||
const { setSubmitToGalleryDialogVisible } = dialogsStore;
|
||||
|
||||
const { isFreeTariff, isNonProfit, isTrial, currentTariffPlanTitle } =
|
||||
currentQuotaStore;
|
||||
const {
|
||||
isGracePeriod,
|
||||
isLicenseExpiring,
|
||||
isLicenseDateExpired,
|
||||
trialDaysLeft,
|
||||
paymentDate,
|
||||
} = currentTariffStatusStore;
|
||||
|
||||
return {
|
||||
bookTrainingEmail,
|
||||
onProfileClick,
|
||||
user,
|
||||
getUserRole,
|
||||
getActions,
|
||||
|
||||
currentTariffPlanTitle,
|
||||
email,
|
||||
displayName,
|
||||
|
||||
zendeskKey,
|
||||
isMobileArticle,
|
||||
showProgress,
|
||||
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
isEnterprise,
|
||||
isTrial,
|
||||
isLicenseDateExpired,
|
||||
trialDaysLeft,
|
||||
paymentDate,
|
||||
|
||||
toggleArticleOpen,
|
||||
|
||||
articleAlertsData,
|
||||
incrementIndexOfArticleAlertsData,
|
||||
|
||||
showText,
|
||||
isNonProfit,
|
||||
isGracePeriod,
|
||||
isFreeTariff,
|
||||
isPaymentPageAvailable,
|
||||
isTeamTrainingAlertAvailable,
|
||||
isSubmitToGalleryAlertAvailable,
|
||||
isLicenseExpiring,
|
||||
|
||||
standalone,
|
||||
|
||||
setShowText,
|
||||
articleOpen,
|
||||
setIsMobileArticle,
|
||||
toggleShowText,
|
||||
|
||||
removeAlertFromArticleAlertsData,
|
||||
setSubmitToGalleryDialogVisible,
|
||||
|
||||
currentColorScheme,
|
||||
setArticleOpen,
|
||||
withSendAgain,
|
||||
mainBarVisible,
|
||||
isBannerVisible,
|
||||
|
||||
isLiveChatAvailable,
|
||||
|
||||
currentDeviceType,
|
||||
|
||||
isAdmin,
|
||||
};
|
||||
}
|
||||
)(observer(Article));
|
@ -29,6 +29,7 @@ export type Item = {
|
||||
security: Security;
|
||||
roomType: number;
|
||||
fileExst?: string;
|
||||
shared: boolean;
|
||||
};
|
||||
|
||||
export type BreadCrumb = {
|
||||
|
@ -226,6 +226,7 @@ const FilesSelector = ({
|
||||
isRoom:
|
||||
item.parentId === 0 && item.rootFolderType === FolderType.Rooms,
|
||||
roomType: item.roomType,
|
||||
shared: item.shared,
|
||||
},
|
||||
]);
|
||||
setSelectedItemId(item.id);
|
||||
@ -365,7 +366,7 @@ const FilesSelector = ({
|
||||
onCloseAction();
|
||||
};
|
||||
|
||||
const onSearchAction = (value: string) => {
|
||||
const onSearchAction = (value: string, callback?: Function) => {
|
||||
setIsFirstLoad(true);
|
||||
setItems(null);
|
||||
if (selectedItemType === "rooms") {
|
||||
@ -375,9 +376,10 @@ const FilesSelector = ({
|
||||
}
|
||||
|
||||
setSearchValue(value);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
const onClearSearchAction = () => {
|
||||
const onClearSearchAction = (callback?: Function) => {
|
||||
setIsFirstLoad(true);
|
||||
setItems(null);
|
||||
if (selectedItemType === "rooms") {
|
||||
@ -387,6 +389,7 @@ const FilesSelector = ({
|
||||
}
|
||||
|
||||
setSearchValue("");
|
||||
callback?.();
|
||||
};
|
||||
|
||||
const onAcceptAction = (
|
||||
|
@ -19,7 +19,7 @@ const ChangeUserTypeEvent = ({
|
||||
onClose,
|
||||
setSelected,
|
||||
getPeopleListItem,
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
needResetUserSelection,
|
||||
isRoomAdmin,
|
||||
}) => {
|
||||
@ -70,7 +70,7 @@ const ChangeUserTypeEvent = ({
|
||||
if (!needResetUserSelection) {
|
||||
const user = getPeopleListItem(users[0]);
|
||||
|
||||
setSelection(user);
|
||||
setInfoPanelSelection(user);
|
||||
}
|
||||
|
||||
successCallback && successCallback(users);
|
||||
@ -144,7 +144,7 @@ export default inject(({ auth, dialogsStore, peopleStore }) => {
|
||||
setChangeUserTypeDialogVisible: setVisible,
|
||||
} = dialogsStore;
|
||||
const { isRoomAdmin, infoPanelStore } = auth;
|
||||
const { setSelection } = infoPanelStore;
|
||||
const { setInfoPanelSelection } = infoPanelStore;
|
||||
const { dialogStore, filterStore, usersStore } = peopleStore;
|
||||
|
||||
const { data: peopleDialogData } = dialogStore;
|
||||
@ -160,7 +160,7 @@ export default inject(({ auth, dialogsStore, peopleStore }) => {
|
||||
isRoomAdmin,
|
||||
needResetUserSelection,
|
||||
getPeopleListItem,
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
setSelected,
|
||||
|
||||
visible,
|
||||
|
@ -44,9 +44,8 @@ const EditRoomEvent = ({
|
||||
updateLogoPathsCacheBreaker,
|
||||
removeLogoPaths,
|
||||
|
||||
reloadInfoPanelSelection,
|
||||
updateInfoPanelSelection,
|
||||
changeRoomOwner,
|
||||
reloadSelectionParentRoom,
|
||||
}) => {
|
||||
const { t } = useTranslation(["CreateEditRoomDialog", "Common", "Files"]);
|
||||
|
||||
@ -108,6 +107,8 @@ const EditRoomEvent = ({
|
||||
const uploadLogoData = new FormData();
|
||||
uploadLogoData.append(0, roomParams.icon.uploadedFile);
|
||||
|
||||
let room = null;
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
@ -115,7 +116,7 @@ const EditRoomEvent = ({
|
||||
await changeRoomOwner(t, roomParams?.roomOwner?.id);
|
||||
}
|
||||
|
||||
let room = await editRoom(item.id, editRoomParams);
|
||||
room = await editRoom(item.id, editRoomParams);
|
||||
|
||||
room.isLogoLoading = true;
|
||||
|
||||
@ -154,15 +155,14 @@ const EditRoomEvent = ({
|
||||
}
|
||||
|
||||
!withPaging && updateRoom(item, room);
|
||||
reloadSelectionParentRoom();
|
||||
reloadInfoPanelSelection();
|
||||
// updateInfoPanelSelection();
|
||||
URL.revokeObjectURL(img.src);
|
||||
setActiveFolders([]);
|
||||
};
|
||||
img.src = url;
|
||||
} else {
|
||||
!withPaging && updateRoom(item, room);
|
||||
reloadInfoPanelSelection();
|
||||
// updateInfoPanelSelection();
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
@ -173,14 +173,14 @@ const EditRoomEvent = ({
|
||||
updateEditedSelectedRoom(editRoomParams.title, tags);
|
||||
if (item.logo.original && !roomParams.icon.uploadedFile) {
|
||||
removeLogoPaths();
|
||||
reloadInfoPanelSelection();
|
||||
// updateInfoPanelSelection();
|
||||
} else if (!item.logo.original && roomParams.icon.uploadedFile)
|
||||
addDefaultLogoPaths();
|
||||
else if (item.logo.original && roomParams.icon.uploadedFile)
|
||||
updateLogoPathsCacheBreaker();
|
||||
}
|
||||
|
||||
reloadSelectionParentRoom();
|
||||
updateInfoPanelSelection(room);
|
||||
setIsLoading(false);
|
||||
onClose();
|
||||
}
|
||||
@ -272,10 +272,7 @@ export default inject(
|
||||
const { getThirdPartyIcon } = settingsStore.thirdPartyStore;
|
||||
const { setCreateRoomDialogVisible } = dialogsStore;
|
||||
const { withPaging } = auth.settingsStore;
|
||||
const {
|
||||
reloadSelection: reloadInfoPanelSelection,
|
||||
reloadSelectionParentRoom,
|
||||
} = auth.infoPanelStore;
|
||||
const { updateInfoPanelSelection } = auth.infoPanelStore;
|
||||
return {
|
||||
addActiveItems,
|
||||
setActiveFolders,
|
||||
@ -308,9 +305,8 @@ export default inject(
|
||||
updateLogoPathsCacheBreaker,
|
||||
removeLogoPaths,
|
||||
|
||||
reloadInfoPanelSelection,
|
||||
updateInfoPanelSelection,
|
||||
changeRoomOwner,
|
||||
reloadSelectionParentRoom,
|
||||
};
|
||||
}
|
||||
)(observer(EditRoomEvent));
|
||||
|
@ -3,7 +3,6 @@ import CatalogFolderReactSvgUrl from "PUBLIC_DIR/images/catalog.folder.react.svg
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import Filter from "@docspace/shared/api/people/filter";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { getSelectedGroup } from "../../../helpers/people-helpers";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@ -13,6 +12,7 @@ import config from "PACKAGE_FILE";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { ArticleItem } from "@docspace/shared/components/article-item";
|
||||
import withLoader from "../../../HOCs/withLoader";
|
||||
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
|
||||
|
||||
const departmentsIcon = DepartmentsGroupReactSvgUrl;
|
||||
const groupIcon = CatalogFolderReactSvgUrl;
|
||||
@ -128,7 +128,7 @@ const ArticleBodyContent = ({
|
||||
};
|
||||
|
||||
const BodyContent = withTranslation(["Article"])(
|
||||
withLoader(ArticleBodyContent)(<Loaders.ArticleFolder />)
|
||||
withLoader(ArticleBodyContent)(<ArticleFolderLoader />)
|
||||
);
|
||||
|
||||
export default inject(({ auth, peopleStore }) => {
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
import MobileView from "./MobileView";
|
||||
|
||||
import withLoader from "../../../HOCs/withLoader";
|
||||
import { ArticleButtonLoader } from "@docspace/shared/skeletons/article";
|
||||
|
||||
const ArticleMainButtonContent = (props) => {
|
||||
const [dialogVisible, setDialogVisible] = React.useState(false);
|
||||
@ -128,6 +129,6 @@ export default inject(({ auth }) => {
|
||||
};
|
||||
})(
|
||||
withTranslation(["Article", "Common", "PeopleTranslations"])(
|
||||
withLoader(observer(ArticleMainButtonContent))(<Loaders.ArticleButton />)
|
||||
withLoader(observer(ArticleMainButtonContent))(<ArticleButtonLoader />)
|
||||
)
|
||||
);
|
||||
|
@ -40,7 +40,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
|
||||
onClose,
|
||||
userIDs,
|
||||
getPeopleListItem,
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
infoPanelVisible,
|
||||
needResetUserSelection,
|
||||
} = this.props;
|
||||
@ -51,7 +51,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
|
||||
if (users.length === 1 && infoPanelVisible) {
|
||||
const user = getPeopleListItem(users[0]);
|
||||
|
||||
setSelection(user);
|
||||
setInfoPanelSelection(user);
|
||||
}
|
||||
|
||||
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"));
|
||||
@ -176,7 +176,8 @@ export default inject(({ peopleStore, auth }) => {
|
||||
const { getPeopleListItem, updateUserStatus, needResetUserSelection } =
|
||||
peopleStore.usersStore;
|
||||
|
||||
const { setSelection, isVisible: infoPanelVisible } = auth.infoPanelStore;
|
||||
const { setInfoPanelSelection, isVisible: infoPanelVisible } =
|
||||
auth.infoPanelStore;
|
||||
|
||||
return {
|
||||
needResetUserSelection,
|
||||
@ -186,7 +187,7 @@ export default inject(({ peopleStore, auth }) => {
|
||||
|
||||
getPeopleListItem,
|
||||
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
infoPanelVisible,
|
||||
};
|
||||
})(observer(ChangeUserStatusDialog));
|
||||
|
@ -42,7 +42,7 @@ const DropdownDesktop = ({ t, open, chooseRoomType }) => {
|
||||
return (
|
||||
<StyledDropdownDesktop className="dropdown-content-wrapper" isOpen={open}>
|
||||
<div className="dropdown-content">
|
||||
{Object.values(RoomsTypeValues).map((roomType) => (
|
||||
{RoomsTypeValues.map((roomType) => (
|
||||
<RoomType
|
||||
id={roomType}
|
||||
t={t}
|
||||
|
@ -31,7 +31,7 @@ const DropdownMobile = ({ t, open, onClose, chooseRoomType }) => {
|
||||
<>
|
||||
<Backdrop visible={open} onClick={onClose} zIndex={450} />
|
||||
<StyledDropdownMobile className="dropdown-mobile" isOpen={open}>
|
||||
{Object.values(RoomsTypeValues).map((roomType) => (
|
||||
{RoomsTypeValues.map((roomType) => (
|
||||
<RoomType
|
||||
id={roomType}
|
||||
t={t}
|
||||
|
@ -19,7 +19,7 @@ const StyledRoomTypeList = styled.div`
|
||||
const RoomTypeList = ({ t, setRoomType }) => {
|
||||
return (
|
||||
<StyledRoomTypeList>
|
||||
{Object.values(RoomsTypeValues).map((roomType) => (
|
||||
{RoomsTypeValues.map((roomType) => (
|
||||
<RoomType
|
||||
id={roomType}
|
||||
t={t}
|
||||
|
@ -121,7 +121,7 @@ const DeleteLinkDialog = withTranslation(["Common", "Files"])(
|
||||
);
|
||||
|
||||
export default inject(({ auth, dialogsStore, publicRoomStore, filesStore }) => {
|
||||
const { selectionParentRoom } = auth.infoPanelStore;
|
||||
const { infoPanelSelection } = auth.infoPanelStore;
|
||||
const {
|
||||
deleteLinkDialogVisible: visible,
|
||||
setDeleteLinkDialogVisible: setIsVisible,
|
||||
@ -132,11 +132,11 @@ export default inject(({ auth, dialogsStore, publicRoomStore, filesStore }) => {
|
||||
return {
|
||||
visible,
|
||||
setIsVisible,
|
||||
roomId: selectionParentRoom.id,
|
||||
roomId: infoPanelSelection.id,
|
||||
link: linkParams.link,
|
||||
editExternalLink,
|
||||
deleteExternalLink,
|
||||
isPublicRoomType: selectionParentRoom.roomType === RoomsType.PublicRoom,
|
||||
isPublicRoomType: infoPanelSelection.roomType === RoomsType.PublicRoom,
|
||||
setRoomShared: filesStore.setRoomShared,
|
||||
};
|
||||
})(observer(DeleteLinkDialog));
|
||||
|
@ -46,6 +46,7 @@ const ChangeRoomOwner = (props) => {
|
||||
roomOwnerId,
|
||||
changeRoomOwner,
|
||||
userId,
|
||||
updateInfoPanelSelection,
|
||||
} = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -71,6 +72,7 @@ const ChangeRoomOwner = (props) => {
|
||||
setIsLoading(true);
|
||||
|
||||
await changeRoomOwner(t, user[0]?.id, isChecked);
|
||||
updateInfoPanelSelection();
|
||||
setIsLoading(false);
|
||||
}
|
||||
onClose();
|
||||
@ -147,9 +149,10 @@ export default inject(
|
||||
setChangeRoomOwnerIsVisible,
|
||||
changeRoomOwnerData,
|
||||
} = dialogsStore;
|
||||
const { settingsStore, userStore } = auth;
|
||||
|
||||
const { settingsStore, userStore, infoPanelStore } = auth;
|
||||
const { selection, bufferSelection } = filesStore;
|
||||
const { currentDeviceType } = settingsStore;
|
||||
const { updateInfoPanelSelection } = infoPanelStore;
|
||||
|
||||
const room = selection.length
|
||||
? selection[0]
|
||||
@ -157,8 +160,6 @@ export default inject(
|
||||
? bufferSelection
|
||||
: selectedFolderStore;
|
||||
|
||||
const { currentDeviceType } = settingsStore;
|
||||
|
||||
const { id } = userStore.user;
|
||||
|
||||
return {
|
||||
@ -170,6 +171,7 @@ export default inject(
|
||||
currentDeviceType,
|
||||
changeRoomOwner: filesActionsStore.changeRoomOwner,
|
||||
userId: id,
|
||||
updateInfoPanelSelection,
|
||||
};
|
||||
}
|
||||
)(observer(withTranslation(["Files"])(ChangeRoomOwner)));
|
||||
|
@ -271,7 +271,7 @@ const EditLinkPanel = (props) => {
|
||||
};
|
||||
|
||||
export default inject(({ auth, dialogsStore, publicRoomStore }) => {
|
||||
const { selectionParentRoom } = auth.infoPanelStore;
|
||||
const { infoPanelSelection } = auth.infoPanelStore;
|
||||
const {
|
||||
editLinkPanelIsVisible,
|
||||
setEditLinkPanelIsVisible,
|
||||
@ -286,7 +286,7 @@ export default inject(({ auth, dialogsStore, publicRoomStore }) => {
|
||||
const link = externalLinks.find((l) => l?.sharedTo?.id === linkId);
|
||||
|
||||
const shareLink = link?.sharedTo?.shareLink;
|
||||
const isPublic = selectionParentRoom?.roomType === RoomsType.PublicRoom;
|
||||
const isPublic = infoPanelSelection?.roomType === RoomsType.PublicRoom;
|
||||
|
||||
return {
|
||||
visible: editLinkPanelIsVisible,
|
||||
@ -294,7 +294,7 @@ export default inject(({ auth, dialogsStore, publicRoomStore }) => {
|
||||
isEdit,
|
||||
linkId: link?.sharedTo?.id,
|
||||
editExternalLink,
|
||||
roomId: selectionParentRoom.id,
|
||||
roomId: infoPanelSelection.id,
|
||||
setExternalLink,
|
||||
isLocked: !!link?.sharedTo?.password,
|
||||
password: link?.sharedTo?.password ?? "",
|
||||
|
@ -54,9 +54,8 @@ const InvitePanel = ({
|
||||
defaultAccess,
|
||||
inviteUsers,
|
||||
setInfoPanelIsMobileHidden,
|
||||
reloadSelectionParentRoom,
|
||||
setUpdateRoomMembers,
|
||||
roomsView,
|
||||
updateInfoPanelSelection,
|
||||
addInfoPanelMembers,
|
||||
setInviteLanguage,
|
||||
getUsersList,
|
||||
filter,
|
||||
@ -277,15 +276,15 @@ const InvitePanel = ({
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const result =
|
||||
roomId === -1
|
||||
? await inviteUsers(data)
|
||||
: await setRoomSecurity(roomId, data);
|
||||
const isRooms = roomId !== -1;
|
||||
const result = !isRooms
|
||||
? await inviteUsers(data)
|
||||
: await setRoomSecurity(roomId, data);
|
||||
|
||||
setIsLoading(false);
|
||||
|
||||
if (roomsView === "info_members") {
|
||||
setUpdateRoomMembers(true);
|
||||
if (isRooms) {
|
||||
addInfoPanelMembers(t, result.members, true);
|
||||
}
|
||||
|
||||
onClose();
|
||||
@ -295,7 +294,7 @@ const InvitePanel = ({
|
||||
toastr.warning(result?.warning);
|
||||
}
|
||||
|
||||
reloadSelectionParentRoom();
|
||||
updateInfoPanelSelection();
|
||||
} catch (err) {
|
||||
toastr.error(err);
|
||||
setIsLoading(false);
|
||||
@ -471,10 +470,8 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
|
||||
const { filter } = peopleStore.filterStore;
|
||||
const {
|
||||
setIsMobileHidden: setInfoPanelIsMobileHidden,
|
||||
reloadSelectionParentRoom,
|
||||
setUpdateRoomMembers,
|
||||
roomsView,
|
||||
filesView,
|
||||
updateInfoPanelSelection,
|
||||
addInfoPanelMembers,
|
||||
} = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
@ -517,9 +514,8 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
|
||||
collaboratorLink,
|
||||
inviteUsers,
|
||||
setInfoPanelIsMobileHidden,
|
||||
reloadSelectionParentRoom,
|
||||
setUpdateRoomMembers,
|
||||
roomsView,
|
||||
updateInfoPanelSelection,
|
||||
addInfoPanelMembers,
|
||||
getUsersList,
|
||||
filter,
|
||||
currentDeviceType,
|
||||
|
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
||||
import { Backdrop } from "@docspace/shared/components/backdrop";
|
||||
import { Heading } from "@docspace/shared/components/heading";
|
||||
import { Aside } from "@docspace/shared/components/aside";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
|
||||
import { FloatingButton } from "@docspace/shared/components/floating-button";
|
||||
import { Portal } from "@docspace/shared/components/portal";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
@ -17,6 +17,7 @@ import {
|
||||
import { SectionBodyContent } from "../../../pages/VersionHistory/Section/";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { ArticleHeaderLoader } from "@docspace/shared/skeletons/article";
|
||||
|
||||
class PureVersionHistoryPanel extends React.Component {
|
||||
onClose = () => {
|
||||
@ -70,7 +71,7 @@ class PureVersionHistoryPanel extends React.Component {
|
||||
{versions[0].title}
|
||||
</Heading>
|
||||
) : (
|
||||
<Loaders.ArticleHeader
|
||||
<ArticleHeaderLoader
|
||||
className="loader-version-history"
|
||||
height="28"
|
||||
width="688"
|
||||
|
@ -150,11 +150,6 @@ export const LinkType = Object.freeze({
|
||||
|
||||
export const SSO_LABEL = "SSO";
|
||||
|
||||
export const ARTICLE_ALERTS = Object.freeze({
|
||||
TeamTraining: "TeamTraining",
|
||||
SubmitToFormGallery: "SubmitToFormGallery",
|
||||
});
|
||||
|
||||
export const AuthenticatedAction = Object.freeze({
|
||||
None: 0,
|
||||
Logout: 1,
|
||||
|
@ -5,7 +5,7 @@ import { I18nextProvider, useTranslation } from "react-i18next";
|
||||
import ErrorContainer from "@docspace/common/components/ErrorContainer";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { ZendeskAPI } from "@docspace/common/components/Zendesk";
|
||||
import { ZendeskAPI } from "@docspace/shared/components/zendesk";
|
||||
|
||||
import { ReportDialog } from "SRC_DIR/components/dialogs";
|
||||
import DocspaceLogo from "SRC_DIR/DocspaceLogo";
|
||||
|
@ -5,7 +5,7 @@ import { useState, useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { Scrollbar } from "@docspace/shared/components/scrollbar";
|
||||
import { ComboButton } from "@docspace/shared/components/combobox";
|
||||
import { ComboButton } from "@docspace/shared/components/combobox/sub-components/ComboButton";
|
||||
import { Backdrop } from "@docspace/shared/components/backdrop";
|
||||
import { isMobile } from "@docspace/shared/utils";
|
||||
|
||||
|
@ -6,9 +6,11 @@ import FilesFilter from "@docspace/shared/api/files/filter";
|
||||
import RoomsFilter from "@docspace/shared/api/rooms/filter";
|
||||
import { getGroup } from "@docspace/shared/api/groups";
|
||||
import { getUserById } from "@docspace/shared/api/people";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
|
||||
import { Events, RoomSearchArea } from "@docspace/shared/enums";
|
||||
import { getObjectByLocation } from "@docspace/shared/utils/common";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { getCategoryType, getCategoryUrl } from "SRC_DIR/helpers/utils";
|
||||
import { CategoryType } from "SRC_DIR/helpers/constants";
|
||||
@ -44,6 +46,7 @@ const useFiles = ({
|
||||
folderSecurity,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
|
||||
const fetchDefaultFiles = () => {
|
||||
const filter = FilesFilter.getDefault();
|
||||
@ -98,7 +101,7 @@ const useFiles = ({
|
||||
if (location.pathname === "/") setIsLoading(true, true, true);
|
||||
else setIsLoading(true, false, false);
|
||||
|
||||
if (!window.location.href.includes("#preview")) {
|
||||
if (!window.location.href.includes(MEDIA_VIEW_URL)) {
|
||||
// localStorage.removeItem("isFirstUrl");
|
||||
// Media viewer
|
||||
removeFirstUrl();
|
||||
@ -109,12 +112,12 @@ const useFiles = ({
|
||||
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);
|
||||
|
||||
if (
|
||||
window.location.href.indexOf(MEDIA_VIEW_URL) > 1 &&
|
||||
playlist.length < 1
|
||||
) {
|
||||
setTimeout(() => {
|
||||
getFileInfo(fileId)
|
||||
getFileInfo(id)
|
||||
.then((data) => {
|
||||
const canOpenPlayer =
|
||||
data.viewAccessibility.ImageView ||
|
||||
@ -132,7 +135,7 @@ const useFiles = ({
|
||||
return setIsLoading(false);
|
||||
}
|
||||
|
||||
if (window.location.href.indexOf("/#preview") > 1)
|
||||
if (window.location.href.indexOf(MEDIA_VIEW_URL) > 1)
|
||||
return setIsLoading(false);
|
||||
|
||||
const isRoomFolder = getObjectByLocation(window.location)?.folder;
|
||||
|
@ -1,7 +1,5 @@
|
||||
const excludeGeneralOptions = ["select", "show-info"];
|
||||
const excludeRoomOptions = ["separator0", "room-info"];
|
||||
const excludeOptionsIntoRoom = ["pin-room", "unpin-room"];
|
||||
const excludeOptionsIntoFolder = ["open", "separator0", "separator1"];
|
||||
|
||||
class ContextHelper {
|
||||
constructor(props) {
|
||||
@ -38,20 +36,7 @@ class ContextHelper {
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
|
||||
if (this.selection.isSelectedFolder) {
|
||||
excludeOptionsIntoRoom.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.selection?.isSelectedFolder && !this.selection?.isRoom) {
|
||||
excludeOptionsIntoFolder.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
|
||||
const length = options.length;
|
||||
|
||||
|
@ -1,20 +1,15 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import ViewHelper from "./helpers/ViewHelper";
|
||||
import ItemTitle from "./sub-components/ItemTitle";
|
||||
|
||||
import { StyledInfoPanelBody } from "./styles/common";
|
||||
import { getRoomInfo } from "@docspace/shared/api/rooms";
|
||||
|
||||
const InfoPanelBodyContent = ({
|
||||
selection,
|
||||
setSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
infoPanelSelection,
|
||||
setNewInfoPanelSelection,
|
||||
isItemChanged,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
fileView,
|
||||
getIsFiles,
|
||||
@ -36,13 +31,15 @@ const InfoPanelBodyContent = ({
|
||||
const isSeveralItems = props.selectedItems?.length > 1;
|
||||
|
||||
const isNoItemGallery = isGallery && !gallerySelected;
|
||||
const itemIsRoot =
|
||||
selection?.isSelectedFolder && selection?.id === selection?.rootFolderId;
|
||||
const isRoot =
|
||||
infoPanelSelection?.isFolder &&
|
||||
infoPanelSelection?.id === infoPanelSelection?.rootFolderId;
|
||||
const isNoItem =
|
||||
!isSeveralItems && (isNoItemGallery || (itemIsRoot && !isGallery));
|
||||
!infoPanelSelection ||
|
||||
(!isSeveralItems && (isNoItemGallery || (isRoot && !isGallery)));
|
||||
|
||||
const defaultProps = {
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
isFiles,
|
||||
isRooms,
|
||||
isAccounts,
|
||||
@ -111,45 +108,14 @@ const InfoPanelBodyContent = ({
|
||||
if (selectedFolderChanged) setSelectedFolder(props.selectedFolder);
|
||||
}, [props.selectedFolder]);
|
||||
|
||||
// Updating selectionParentRoom after selectFolder change
|
||||
// Updating infoPanelSelection after selectFolder change
|
||||
// if it is located in another room
|
||||
|
||||
const updateSelectionParentRoomAction = useCallback(async () => {
|
||||
if (!isRooms) return;
|
||||
if (selection?.isRoom && roomsView === "members") return;
|
||||
|
||||
const currentFolderRoomId =
|
||||
selectedFolder?.pathParts &&
|
||||
selectedFolder?.pathParts?.length > 1 &&
|
||||
selectedFolder.pathParts[1].id;
|
||||
|
||||
const storeRoomId = selectionParentRoom?.id;
|
||||
if (!currentFolderRoomId || currentFolderRoomId === storeRoomId) return;
|
||||
|
||||
const newSelectionParentRoom = await getRoomInfo(currentFolderRoomId);
|
||||
|
||||
if (storeRoomId === newSelectionParentRoom.id) return;
|
||||
|
||||
setSelectionParentRoom(normalizeSelection(newSelectionParentRoom));
|
||||
}, [selectedFolder]);
|
||||
|
||||
// Setting infoPanelSelection after selectedItems or selectedFolder update
|
||||
useEffect(() => {
|
||||
updateSelectionParentRoomAction();
|
||||
}, [selectedFolder, updateSelectionParentRoomAction]);
|
||||
|
||||
// Setting selection after selectedItems or selectedFolder update
|
||||
useEffect(() => {
|
||||
setSelection(calculateSelection());
|
||||
setNewInfoPanelSelection();
|
||||
}, [selectedItems, selectedFolder]);
|
||||
|
||||
// * DEV-ONLY - Logs selection change
|
||||
// useEffect(() => {
|
||||
// console.log("\nfor-dev Selected items: ", selectedItems);
|
||||
// console.log("\nfor-dev Selected folder: ", selectedFolder);
|
||||
// }, [selectedItems, selectedFolder]);
|
||||
|
||||
if (!selection && !isGallery) return null;
|
||||
|
||||
return (
|
||||
<StyledInfoPanelBody>
|
||||
{!isNoItem && (
|
||||
@ -166,38 +132,27 @@ const InfoPanelBodyContent = ({
|
||||
|
||||
export default inject(({ auth, selectedFolderStore, oformsStore }) => {
|
||||
const {
|
||||
selection,
|
||||
setSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
infoPanelSelection,
|
||||
setNewInfoPanelSelection,
|
||||
isItemChanged,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
fileView,
|
||||
getIsFiles,
|
||||
getIsRooms,
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
infoPanelSelectedItems,
|
||||
getInfoPanelSelectedFolder,
|
||||
} = auth.infoPanelStore;
|
||||
|
||||
const { gallerySelected } = oformsStore;
|
||||
|
||||
const { isRootFolder } = selectedFolderStore;
|
||||
|
||||
const selectedItems = auth.infoPanelStore.getSelectedItems();
|
||||
|
||||
const selectedFolder = auth.infoPanelStore.getSelectedFolder();
|
||||
|
||||
return {
|
||||
selection,
|
||||
setSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
infoPanelSelection,
|
||||
setNewInfoPanelSelection,
|
||||
isItemChanged,
|
||||
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
fileView,
|
||||
getIsFiles,
|
||||
@ -205,8 +160,8 @@ export default inject(({ auth, selectedFolderStore, oformsStore }) => {
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
|
||||
selectedItems,
|
||||
selectedFolder,
|
||||
selectedItems: infoPanelSelectedItems,
|
||||
selectedFolder: getInfoPanelSelectedFolder(),
|
||||
|
||||
isRootFolder,
|
||||
gallerySelected,
|
||||
|
@ -15,7 +15,7 @@ const CommentEditor = ({
|
||||
t,
|
||||
item,
|
||||
editing,
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
fetchFileVersions,
|
||||
updateCommentVersion,
|
||||
|
||||
@ -61,7 +61,7 @@ const CommentEditor = ({
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
setSelection({ ...item, comment: inputValue });
|
||||
setInfoPanelSelection({ ...item, comment: inputValue });
|
||||
setIsEdit(false);
|
||||
setIsLoading(false);
|
||||
};
|
||||
@ -121,7 +121,7 @@ const CommentEditor = ({
|
||||
};
|
||||
|
||||
export default inject(({ auth, versionHistoryStore }) => {
|
||||
const { setSelection } = auth.infoPanelStore;
|
||||
const { setInfoPanelSelection } = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
fetchFileVersions,
|
||||
@ -136,7 +136,7 @@ export default inject(({ auth, versionHistoryStore }) => {
|
||||
const editing = isEditingVersion || isEditing;
|
||||
|
||||
return {
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
fetchFileVersions,
|
||||
updateCommentVersion,
|
||||
|
||||
|
@ -16,7 +16,7 @@ import { decode } from "he";
|
||||
const AccountsItemTitle = ({
|
||||
t,
|
||||
isSeveralItems,
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
getUserContextOptions,
|
||||
}) => {
|
||||
if (isSeveralItems) {
|
||||
@ -26,20 +26,23 @@ const AccountsItemTitle = ({
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
const isPending =
|
||||
selection.statusType === "pending" || selection.statusType === "disabled";
|
||||
infoPanelSelection.statusType === "pending" ||
|
||||
infoPanelSelection.statusType === "disabled";
|
||||
|
||||
const getData = () => {
|
||||
const newOptions = selection.options?.filter(
|
||||
const newOptions = infoPanelSelection.options?.filter(
|
||||
(option) => option !== "details"
|
||||
);
|
||||
return getUserContextOptions(t, newOptions || [], selection);
|
||||
return getUserContextOptions(t, newOptions || [], infoPanelSelection);
|
||||
};
|
||||
const contextOptions = getData();
|
||||
|
||||
const userAvatar = selection.hasAvatar ? selection.avatar : DefaultUserPhoto;
|
||||
const isSSO = selection.isSSO || false;
|
||||
const displayName = selection.displayName
|
||||
? decode(selection.displayName).trim()
|
||||
const userAvatar = infoPanelSelection.hasAvatar
|
||||
? infoPanelSelection.avatar
|
||||
: DefaultUserPhoto;
|
||||
const isSSO = infoPanelSelection.isSSO || false;
|
||||
const displayName = infoPanelSelection.displayName
|
||||
? decode(infoPanelSelection.displayName).trim()
|
||||
: "";
|
||||
|
||||
return (
|
||||
@ -50,7 +53,7 @@ const AccountsItemTitle = ({
|
||||
>
|
||||
<Avatar
|
||||
className="avatar"
|
||||
role={selection.role ? selection.role : "user"}
|
||||
role={infoPanelSelection.role ? infoPanelSelection.role : "user"}
|
||||
size={"big"}
|
||||
source={userAvatar}
|
||||
/>
|
||||
@ -62,15 +65,18 @@ const AccountsItemTitle = ({
|
||||
title={displayName}
|
||||
truncate
|
||||
>
|
||||
{isPending || !displayName ? selection.email : displayName}
|
||||
{isPending || !displayName ? infoPanelSelection.email : displayName}
|
||||
</Text>
|
||||
{isPending && (
|
||||
<Badges withoutPaid={true} statusType={selection.statusType} />
|
||||
<Badges
|
||||
withoutPaid={true}
|
||||
statusType={infoPanelSelection.statusType}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{!isPending && !!displayName && (
|
||||
<Text className={"info-text__email"} title={selection.email}>
|
||||
{selection.email}
|
||||
<Text className={"info-text__email"} title={infoPanelSelection.email}>
|
||||
{infoPanelSelection.email}
|
||||
</Text>
|
||||
)}
|
||||
{isSSO && (
|
||||
|
@ -7,8 +7,6 @@ import { ContextMenuButton } from "@docspace/shared/components/context-menu-butt
|
||||
|
||||
const generalKeys = ["select", "show-info"];
|
||||
const roomKeys = ["separator0", "room-info"];
|
||||
const currentRoomKeys = ["pin-room", "unpin-room"];
|
||||
const currentFolderKeys = ["open", "separator0", "separator1"];
|
||||
|
||||
const StyledItemContextOptions = styled.div`
|
||||
height: 16px;
|
||||
@ -23,7 +21,6 @@ const RoomsContextBtn = ({
|
||||
|
||||
getItemContextOptionsKeys,
|
||||
getItemContextOptionsActions,
|
||||
|
||||
onSelectItem,
|
||||
}) => {
|
||||
const contextMenuRef = useRef();
|
||||
@ -54,10 +51,6 @@ const RoomsContextBtn = ({
|
||||
|
||||
generalKeys.forEach((key) => removeOptionByKey(key));
|
||||
if (selection.isRoom) roomKeys.forEach((key) => removeOptionByKey(key));
|
||||
if (selection.isSelectedFolder && selection.isRoom)
|
||||
currentRoomKeys.forEach((key) => removeOptionByKey(key));
|
||||
if (selection.isSelectedFolder && !selection.isRoom)
|
||||
currentFolderKeys.forEach((key) => removeOptionByKey(key));
|
||||
|
||||
options.forEach((item, index) => {
|
||||
const isSeparator = item.key.includes("separator");
|
||||
@ -76,10 +69,6 @@ const RoomsContextBtn = ({
|
||||
return options;
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// contextMenuRef?.current.hide();
|
||||
// }, [selection]);
|
||||
|
||||
return (
|
||||
<StyledItemContextOptions>
|
||||
<ContextMenuButton
|
||||
|
@ -8,12 +8,16 @@ import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { StyledTitle } from "../../../styles/common";
|
||||
import { RoomIcon } from "@docspace/shared/components/room-icon";
|
||||
import RoomsContextBtn from "./context-btn";
|
||||
import { RoomsType, ShareAccessRights } from "@docspace/shared/enums";
|
||||
import {
|
||||
FolderType,
|
||||
RoomsType,
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
|
||||
const RoomsItemHeader = ({
|
||||
t,
|
||||
selection,
|
||||
selectionParentRoom,
|
||||
infoPanelSelection,
|
||||
setIsMobileHidden,
|
||||
isGracePeriod,
|
||||
setInvitePanelOptions,
|
||||
@ -22,6 +26,7 @@ const RoomsItemHeader = ({
|
||||
roomsView,
|
||||
setSelected,
|
||||
setBufferSelection,
|
||||
isArchive,
|
||||
}) => {
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
@ -30,7 +35,7 @@ const RoomsItemHeader = ({
|
||||
const icon = selection.icon;
|
||||
const isLoadedRoomIcon = !!selection.logo?.medium;
|
||||
const showDefaultRoomIcon = !isLoadedRoomIcon && selection.isRoom;
|
||||
const security = selectionParentRoom ? selectionParentRoom.security : {};
|
||||
const security = infoPanelSelection ? infoPanelSelection.security : {};
|
||||
const canInviteUserInRoomAbility = security?.EditAccess;
|
||||
const showInviteUserIcon = selection?.isRoom && roomsView === "info_members";
|
||||
|
||||
@ -41,7 +46,7 @@ const RoomsItemHeader = ({
|
||||
|
||||
const onClickInviteUsers = () => {
|
||||
setIsMobileHidden(true);
|
||||
const parentRoomId = selectionParentRoom.id;
|
||||
const parentRoomId = infoPanelSelection.id;
|
||||
|
||||
if (isGracePeriod) {
|
||||
setInviteUsersWarningDialogVisible(true);
|
||||
@ -65,7 +70,7 @@ const RoomsItemHeader = ({
|
||||
<RoomIcon
|
||||
color={selection.logo.color}
|
||||
title={selection.title}
|
||||
isArchive={selection.isArchive}
|
||||
isArchive={isArchive}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
@ -103,30 +108,15 @@ const RoomsItemHeader = ({
|
||||
|
||||
export default inject(
|
||||
({ auth, dialogsStore, selectedFolderStore, filesStore }) => {
|
||||
const {
|
||||
selection: selectionItem,
|
||||
selectionParentRoom,
|
||||
getIsRooms,
|
||||
roomsView,
|
||||
} = auth.infoPanelStore;
|
||||
const { infoPanelSelection, roomsView } = auth.infoPanelStore;
|
||||
|
||||
const isShowParentRoom =
|
||||
getIsRooms() &&
|
||||
roomsView === "info_members" &&
|
||||
!selectionItem.isRoom &&
|
||||
!!selectionParentRoom;
|
||||
|
||||
const selection =
|
||||
selectionItem.length > 1
|
||||
? null
|
||||
: isShowParentRoom
|
||||
? selectionParentRoom
|
||||
: selectionItem;
|
||||
const selection = infoPanelSelection.length > 1 ? null : infoPanelSelection;
|
||||
const isArchive = selection?.rootFolderType === FolderType.Archive;
|
||||
|
||||
return {
|
||||
selection,
|
||||
roomsView,
|
||||
selectionParentRoom: auth.infoPanelStore.selectionParentRoom,
|
||||
infoPanelSelection: auth.infoPanelStore.infoPanelSelection,
|
||||
setIsMobileHidden: auth.infoPanelStore.setIsMobileHidden,
|
||||
|
||||
isGracePeriod: auth.currentTariffStatusStore.isGracePeriod,
|
||||
@ -137,11 +127,12 @@ export default inject(
|
||||
|
||||
isPublicRoomType:
|
||||
(selectedFolderStore.roomType ??
|
||||
auth.infoPanelStore.selectionParentRoom?.roomType) ===
|
||||
auth.infoPanelStore.infoPanelSelection?.roomType) ===
|
||||
RoomsType.PublicRoom,
|
||||
|
||||
setSelected: filesStore.setSelected,
|
||||
setBufferSelection: filesStore.setBufferSelection,
|
||||
isArchive,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -5,7 +5,7 @@ import GalleryItemTitle from "./GalleryItemTitle";
|
||||
import RoomsItemHeader from "./Rooms";
|
||||
|
||||
const ItemTitle = ({
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
gallerySelected,
|
||||
isNoItem,
|
||||
isAccounts,
|
||||
@ -16,13 +16,13 @@ const ItemTitle = ({
|
||||
getIcon,
|
||||
getUserContextOptions,
|
||||
}) => {
|
||||
if (!selection) return null;
|
||||
if (!infoPanelSelection) return null;
|
||||
if (isNoItem) return null;
|
||||
|
||||
if (isAccounts)
|
||||
return (
|
||||
<AccountsItemTitle
|
||||
selection={selection}
|
||||
infoPanelSelection={infoPanelSelection}
|
||||
isSeveralItems={isSeveralItems}
|
||||
getUserContextOptions={getUserContextOptions}
|
||||
selectionLength={selectionLength}
|
||||
|
@ -11,27 +11,29 @@ import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { getUserStatus } from "SRC_DIR/helpers/people-helpers";
|
||||
import { StyledAccountContent } from "../../styles/accounts";
|
||||
|
||||
const Accounts = ({
|
||||
t,
|
||||
selection,
|
||||
isOwner,
|
||||
isAdmin,
|
||||
changeUserType,
|
||||
canChangeUserType,
|
||||
setSelection,
|
||||
getPeopleListItem,
|
||||
}) => {
|
||||
const Accounts = (props) => {
|
||||
const {
|
||||
t,
|
||||
infoPanelSelection,
|
||||
isOwner,
|
||||
isAdmin,
|
||||
changeUserType,
|
||||
canChangeUserType,
|
||||
setInfoPanelSelection,
|
||||
getPeopleListItem,
|
||||
} = props;
|
||||
|
||||
const [statusLabel, setStatusLabel] = React.useState("");
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
|
||||
const { role, id, isVisitor, isCollaborator } = selection;
|
||||
const { role, id, isVisitor, isCollaborator } = infoPanelSelection;
|
||||
|
||||
React.useEffect(() => {
|
||||
getStatusLabel();
|
||||
}, [selection, getStatusLabel]);
|
||||
}, [infoPanelSelection, getStatusLabel]);
|
||||
|
||||
const getStatusLabel = React.useCallback(() => {
|
||||
const status = getUserStatus(selection);
|
||||
const status = getUserStatus(infoPanelSelection);
|
||||
switch (status) {
|
||||
case "active":
|
||||
return setStatusLabel(t("Common:Active"));
|
||||
@ -42,7 +44,7 @@ const Accounts = ({
|
||||
default:
|
||||
return setStatusLabel(t("Common:Active"));
|
||||
}
|
||||
}, [selection]);
|
||||
}, [infoPanelSelection]);
|
||||
|
||||
const getUserTypeLabel = React.useCallback((role) => {
|
||||
switch (role) {
|
||||
@ -111,9 +113,9 @@ const Accounts = ({
|
||||
const items = [];
|
||||
users.map((u) => items.push(getPeopleListItem(u)));
|
||||
if (items.length === 1) {
|
||||
setSelection(getPeopleListItem(items[0]));
|
||||
setInfoPanelSelection(getPeopleListItem(items[0]));
|
||||
} else {
|
||||
setSelection(items);
|
||||
setInfoPanelSelection(items);
|
||||
}
|
||||
}
|
||||
setIsLoading(false);
|
||||
@ -122,11 +124,11 @@ const Accounts = ({
|
||||
const onTypeChange = React.useCallback(
|
||||
({ action }) => {
|
||||
setIsLoading(true);
|
||||
if (!changeUserType(action, [selection], onSuccess, onAbort)) {
|
||||
if (!changeUserType(action, [infoPanelSelection], onSuccess, onAbort)) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[selection, changeUserType, t]
|
||||
[infoPanelSelection, changeUserType, t]
|
||||
);
|
||||
|
||||
const typeLabel = getUserTypeLabel(role);
|
||||
@ -165,9 +167,12 @@ const Accounts = ({
|
||||
</Text>
|
||||
);
|
||||
|
||||
const status = getUserStatus(selection);
|
||||
const status = getUserStatus(infoPanelSelection);
|
||||
|
||||
const canChange = canChangeUserType({ ...selection, statusType: status });
|
||||
const canChange = canChangeUserType({
|
||||
...infoPanelSelection,
|
||||
statusType: status,
|
||||
});
|
||||
|
||||
return canChange ? combobox : text;
|
||||
};
|
||||
@ -230,7 +235,7 @@ export default inject(({ auth, peopleStore, accessRightsStore }) => {
|
||||
const { changeType: changeUserType, usersStore } = peopleStore;
|
||||
const { canChangeUserType } = accessRightsStore;
|
||||
|
||||
const { setSelection } = auth.infoPanelStore;
|
||||
const { setInfoPanelSelection } = auth.infoPanelStore;
|
||||
|
||||
return {
|
||||
isOwner,
|
||||
@ -240,7 +245,7 @@ export default inject(({ auth, peopleStore, accessRightsStore }) => {
|
||||
canChangeUserType,
|
||||
loading: usersStore.operationRunning,
|
||||
getPeopleListItem: usersStore.getPeopleListItem,
|
||||
setSelection,
|
||||
setInfoPanelSelection,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
|
@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { inject } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import { FileType } from "@docspace/shared/enums";
|
||||
import { FileType, FolderType } from "@docspace/shared/enums";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import DetailsHelper from "../../helpers/DetailsHelper.js";
|
||||
@ -21,6 +21,7 @@ const Details = ({
|
||||
isVisitor,
|
||||
isCollaborator,
|
||||
selectTag,
|
||||
isArchive,
|
||||
}) => {
|
||||
const [itemProperties, setItemProperties] = useState([]);
|
||||
|
||||
@ -61,7 +62,7 @@ const Details = ({
|
||||
}, [selection, createThumbnailAction]);
|
||||
|
||||
const currentIcon =
|
||||
!selection.isArchive && selection?.logo?.large
|
||||
!isArchive && selection?.logo?.large
|
||||
? selection?.logo?.large
|
||||
: getInfoPanelItemIcon(selection, 96);
|
||||
|
||||
@ -93,7 +94,7 @@ const Details = ({
|
||||
<RoomIcon
|
||||
color={selection.logo.color}
|
||||
title={selection.title}
|
||||
isArchive={selection.isArchive}
|
||||
isArchive={isArchive}
|
||||
size="96px"
|
||||
radius="16px"
|
||||
/>
|
||||
@ -101,7 +102,7 @@ const Details = ({
|
||||
<img
|
||||
className={`no-thumbnail-img ${selection.isRoom && "is-room"} ${
|
||||
selection.isRoom &&
|
||||
!selection.isArchive &&
|
||||
!isArchive &&
|
||||
selection.logo?.large &&
|
||||
"custom-logo"
|
||||
}`}
|
||||
@ -138,7 +139,8 @@ const Details = ({
|
||||
|
||||
export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
const { userStore } = auth;
|
||||
const { selection, getInfoPanelItemIcon, openUser } = auth.infoPanelStore;
|
||||
const { infoPanelSelection, getInfoPanelItemIcon, openUser } =
|
||||
auth.infoPanelStore;
|
||||
const { createThumbnail } = filesStore;
|
||||
const { personal, culture } = auth.settingsStore;
|
||||
const { user } = userStore;
|
||||
@ -148,15 +150,18 @@ export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
const isVisitor = user.isVisitor;
|
||||
const isCollaborator = user.isCollaborator;
|
||||
|
||||
const isArchive = infoPanelSelection?.rootFolderType === FolderType.Archive;
|
||||
|
||||
return {
|
||||
personal,
|
||||
culture,
|
||||
selection,
|
||||
selection: infoPanelSelection,
|
||||
createThumbnail,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
isVisitor,
|
||||
isCollaborator,
|
||||
selectTag,
|
||||
isArchive,
|
||||
};
|
||||
})(withTranslation(["InfoPanel", "Common", "Translations", "Files"])(Details));
|
||||
|
@ -13,11 +13,10 @@ import { decode } from "he";
|
||||
|
||||
const HistoryBlock = ({
|
||||
t,
|
||||
selection,
|
||||
selectionIsFile,
|
||||
feed,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
infoPanelSelection,
|
||||
getInfoPanelItemIcon,
|
||||
checkAndOpenLocationAction,
|
||||
openUser,
|
||||
@ -72,9 +71,8 @@ const HistoryBlock = ({
|
||||
className="message"
|
||||
action={json}
|
||||
groupedActions={groupedFeeds}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
infoPanelSelection={infoPanelSelection}
|
||||
/>
|
||||
|
||||
{isItemAction && withFileList && (
|
||||
|
@ -10,9 +10,8 @@ const HistoryBlockMessage = ({
|
||||
t,
|
||||
action,
|
||||
groupedActions,
|
||||
selection,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
infoPanelSelection,
|
||||
}) => {
|
||||
const message = getBlockMessageTranslation(
|
||||
t,
|
||||
@ -31,7 +30,7 @@ const HistoryBlockMessage = ({
|
||||
|
||||
const itemLocationId = +action.ExtraLocation;
|
||||
if (selectedFolder?.id === itemLocationId) return "";
|
||||
if (selection?.isRoom && selectionParentRoom?.id === itemLocationId)
|
||||
if (infoPanelSelection?.isRoom && infoPanelSelection?.id === itemLocationId)
|
||||
return "";
|
||||
|
||||
const folderTitle = action.ExtraLocationTitle;
|
||||
|
@ -11,12 +11,11 @@ import NoHistory from "../NoItem/NoHistory";
|
||||
|
||||
const History = ({
|
||||
t,
|
||||
selection,
|
||||
historyWithFileList,
|
||||
selectedFolder,
|
||||
selectionHistory,
|
||||
setSelectionHistory,
|
||||
selectionParentRoom,
|
||||
infoPanelSelection,
|
||||
getInfoPanelItemIcon,
|
||||
getHistory,
|
||||
checkAndOpenLocationAction,
|
||||
@ -32,14 +31,15 @@ const History = ({
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const fetchHistory = async (item) => {
|
||||
if (!item?.id) return;
|
||||
if (isLoading) {
|
||||
abortControllerRef.current?.abort();
|
||||
abortControllerRef.current = new AbortController();
|
||||
} else setIsLoading(true);
|
||||
|
||||
let module = "files";
|
||||
if (selection.isRoom) module = "rooms";
|
||||
else if (selection.isFolder) module = "folders";
|
||||
if (infoPanelSelection.isRoom) module = "rooms";
|
||||
else if (infoPanelSelection.isFolder) module = "folders";
|
||||
|
||||
getHistory(
|
||||
module,
|
||||
@ -64,8 +64,8 @@ const History = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (!isMount.current) return;
|
||||
fetchHistory(selection);
|
||||
}, [selection.id]);
|
||||
fetchHistory(infoPanelSelection);
|
||||
}, [infoPanelSelection.id]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@ -86,9 +86,8 @@ const History = ({
|
||||
key={feed.json.Id}
|
||||
t={t}
|
||||
feed={feed}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
infoPanelSelection={infoPanelSelection}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
openUser={openUser}
|
||||
@ -106,11 +105,10 @@ const History = ({
|
||||
export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
const { userStore } = auth;
|
||||
const {
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
selectionHistory,
|
||||
setSelectionHistory,
|
||||
historyWithFileList,
|
||||
selectionParentRoom,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
} = auth.infoPanelStore;
|
||||
@ -126,11 +124,10 @@ export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
return {
|
||||
personal,
|
||||
culture,
|
||||
selection,
|
||||
selectionHistory,
|
||||
setSelectionHistory,
|
||||
historyWithFileList,
|
||||
selectionParentRoom,
|
||||
infoPanelSelection,
|
||||
getInfoPanelItemIcon,
|
||||
getHistory,
|
||||
checkAndOpenLocationAction,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import AtReactSvgUrl from "PUBLIC_DIR/images/@.react.svg?url";
|
||||
import { StyledUser } from "../../styles/members";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
@ -17,62 +18,69 @@ import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
const User = ({
|
||||
t,
|
||||
user,
|
||||
setMembers,
|
||||
isExpect,
|
||||
membersHelper,
|
||||
currentMember,
|
||||
updateRoomMemberRole,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
infoPanelSelection,
|
||||
changeUserType,
|
||||
setIsScrollLocked,
|
||||
isTitle,
|
||||
onRepeatInvitation,
|
||||
showInviteIcon,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
fetchMembers,
|
||||
hasNextPage,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
}) => {
|
||||
if (!selectionParentRoom) return null;
|
||||
if (!infoPanelSelection) return null;
|
||||
if (!user.displayName && !user.email) return null;
|
||||
|
||||
//const [userIsRemoved, setUserIsRemoved] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
//if (userIsRemoved) return null;
|
||||
|
||||
const security = infoPanelSelection ? infoPanelSelection.security : {};
|
||||
const isExpect = user.isExpect;
|
||||
const canInviteUserInRoomAbility = security?.EditAccess;
|
||||
const showInviteIcon = canInviteUserInRoomAbility && isExpect;
|
||||
const canChangeUserRole = user.canEditAccess;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const fullRoomRoleOptions = membersHelper.getOptionsByRoomType(
|
||||
selectionParentRoom.roomType,
|
||||
infoPanelSelection.roomType,
|
||||
canChangeUserRole
|
||||
);
|
||||
|
||||
const userRole = membersHelper.getOptionByUserAccess(user.access, user);
|
||||
|
||||
const userRoleOptions = filterUserRoleOptions(fullRoomRoleOptions, user);
|
||||
|
||||
const onRepeatInvitation = async () => {
|
||||
resendEmailInvitations(infoPanelSelection.id, true)
|
||||
.then(() =>
|
||||
toastr.success(t("PeopleTranslations:SuccessSentMultipleInvitatios"))
|
||||
)
|
||||
.catch((err) => toastr.error(err));
|
||||
};
|
||||
|
||||
const updateRole = (option) => {
|
||||
return updateRoomMemberRole(selectionParentRoom.id, {
|
||||
return updateRoomMemberRole(infoPanelSelection.id, {
|
||||
invitations: [{ id: user.id, access: option.access }],
|
||||
notify: false,
|
||||
sharingMessage: "",
|
||||
})
|
||||
.then(async () => {
|
||||
setIsLoading(false);
|
||||
const users = selectionParentRoom.members.users;
|
||||
const administrators = selectionParentRoom.members.administrators;
|
||||
const expectedMembers = selectionParentRoom.members.expected;
|
||||
|
||||
if (option.key === "remove") {
|
||||
const newMembersFilter = JSON.parse(JSON.stringify(membersFilter));
|
||||
|
||||
const newMembers = {
|
||||
users: users?.filter((m) => m.id !== user.id),
|
||||
administrators: administrators?.filter((m) => m.id !== user.id),
|
||||
expected: expectedMembers?.filter((m) => m.id !== user.id),
|
||||
users: infoPanelMembers.users?.filter((m) => m.id !== user.id),
|
||||
administrators: infoPanelMembers.administrators?.filter(
|
||||
(m) => m.id !== user.id
|
||||
),
|
||||
expected: infoPanelMembers.expected?.filter(
|
||||
(m) => m.id !== user.id
|
||||
),
|
||||
};
|
||||
|
||||
const roomId = selectionParentRoom.id;
|
||||
const roomId = infoPanelSelection.id;
|
||||
const newUsers = newMembers.users.length > 1 ? newMembers?.users : [];
|
||||
const newAdministrators =
|
||||
newMembers.administrators.length > 1
|
||||
@ -81,7 +89,7 @@ const User = ({
|
||||
const newExpected =
|
||||
newMembers.expected.length > 1 ? newMembers?.expected : [];
|
||||
|
||||
setMembers({
|
||||
setInfoPanelMembers({
|
||||
roomId,
|
||||
users: newUsers,
|
||||
administrators: newAdministrators,
|
||||
@ -90,25 +98,12 @@ const User = ({
|
||||
|
||||
newMembersFilter.total -= 1;
|
||||
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: {
|
||||
users: newUsers,
|
||||
administrators: newAdministrators,
|
||||
expected: newExpected,
|
||||
},
|
||||
});
|
||||
|
||||
if (hasNextPage) {
|
||||
newMembersFilter.startIndex =
|
||||
(newMembersFilter.page + 1) * newMembersFilter.pageCount - 1;
|
||||
newMembersFilter.pageCount = 1;
|
||||
|
||||
const fetchedMembers = await fetchMembers(
|
||||
selectionParentRoom.id,
|
||||
false,
|
||||
newMembersFilter
|
||||
);
|
||||
const fetchedMembers = await fetchMembers(t, false);
|
||||
|
||||
const newMembers = {
|
||||
administrators: [
|
||||
@ -119,48 +114,26 @@ const User = ({
|
||||
expected: [...newExpected, ...fetchedMembers.expected],
|
||||
};
|
||||
|
||||
setMembers({
|
||||
roomId: selectionParentRoom.id,
|
||||
setInfoPanelMembers({
|
||||
roomId: infoPanelSelection.id,
|
||||
...newMembers,
|
||||
});
|
||||
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: newMembers,
|
||||
});
|
||||
}
|
||||
|
||||
setMembersFilter(newMembersFilter);
|
||||
|
||||
//setUserIsRemoved(true);
|
||||
} else {
|
||||
setMembers({
|
||||
roomId: selectionParentRoom.id,
|
||||
users: users?.map((m) =>
|
||||
setInfoPanelMembers({
|
||||
roomId: infoPanelSelection.id,
|
||||
users: infoPanelMembers.users?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
administrators: administrators?.map((m) =>
|
||||
administrators: infoPanelMembers.administrators?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
expected: expectedMembers?.map((m) =>
|
||||
expected: infoPanelMembers.expected?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
});
|
||||
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: {
|
||||
users: users?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
administrators: administrators?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
expected: expectedMembers?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -203,7 +176,7 @@ const User = ({
|
||||
};
|
||||
|
||||
const onToggle = (e, isOpen) => {
|
||||
setIsScrollLocked(isOpen);
|
||||
// setIsScrollLocked(isOpen);
|
||||
};
|
||||
|
||||
const userAvatar = user.hasAvatar ? user.avatar : DefaultUserPhotoUrl;
|
||||
@ -216,7 +189,7 @@ const User = ({
|
||||
user.isOwner ? t("Common:DocSpaceOwner") : t("Common:DocSpaceAdmin")
|
||||
}. ${t("Common:HasFullAccess")}`;
|
||||
|
||||
return isTitle ? (
|
||||
return user.isTitle ? (
|
||||
<StyledUserTypeHeader isExpect={isExpect}>
|
||||
<Text className="title">{user.displayName}</Text>
|
||||
|
||||
@ -282,4 +255,33 @@ const User = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default User;
|
||||
export default inject(({ auth, filesStore, peopleStore }) => {
|
||||
const {
|
||||
infoPanelSelection,
|
||||
setIsScrollLocked,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
fetchMembers,
|
||||
} = auth.infoPanelStore;
|
||||
const {
|
||||
updateRoomMemberRole,
|
||||
resendEmailInvitations,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
} = filesStore;
|
||||
|
||||
const { changeType: changeUserType } = peopleStore;
|
||||
|
||||
return {
|
||||
infoPanelSelection,
|
||||
setIsScrollLocked,
|
||||
updateRoomMemberRole,
|
||||
resendEmailInvitations,
|
||||
changeUserType,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
fetchMembers,
|
||||
};
|
||||
})(observer(User));
|
||||
|
@ -1,13 +1,9 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
import {
|
||||
EmployeeActivationStatus,
|
||||
RoomsType,
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
import { RoomsType, ShareAccessRights } from "@docspace/shared/enums";
|
||||
import { LINKS_LIMIT_COUNT } from "@docspace/shared/constants";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import MembersHelper from "../../helpers/MembersHelper";
|
||||
@ -30,214 +26,60 @@ import LinkRow from "./sub-components/LinkRow";
|
||||
const Members = ({
|
||||
t,
|
||||
selfId,
|
||||
selection,
|
||||
|
||||
updateRoomMembers,
|
||||
setUpdateRoomMembers,
|
||||
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
|
||||
infoPanelSelection,
|
||||
setIsScrollLocked,
|
||||
|
||||
getRoomMembers,
|
||||
getRoomLinks,
|
||||
updateRoomMemberRole,
|
||||
setView,
|
||||
roomsView,
|
||||
resendEmailInvitations,
|
||||
changeUserType,
|
||||
isPublicRoomType,
|
||||
|
||||
setExternalLinks,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
externalLinks,
|
||||
members,
|
||||
setMembersList,
|
||||
roomType,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
primaryLink,
|
||||
isArchiveFolder,
|
||||
isPublicRoom,
|
||||
|
||||
additionalLinks,
|
||||
setLinkParams,
|
||||
setEditLinkPanelIsVisible,
|
||||
getPrimaryLink,
|
||||
setExternalLink,
|
||||
withPublicRoomBlock,
|
||||
fetchMembers,
|
||||
membersIsLoading,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const membersHelper = new MembersHelper({ t });
|
||||
|
||||
const security = selectionParentRoom ? selectionParentRoom.security : {};
|
||||
|
||||
const fetchMembers = async (roomId, clearFilter = true) => {
|
||||
if (isLoading) return;
|
||||
const isPublic = selection?.roomType ?? selectionParentRoom?.roomType;
|
||||
const requests = [getRoomMembers(roomId, clearFilter)];
|
||||
|
||||
if (isPublic && clearFilter && withPublicRoomBlock) {
|
||||
requests.push(getRoomLinks(roomId));
|
||||
}
|
||||
|
||||
let timerId;
|
||||
if (clearFilter) timerId = setTimeout(() => setIsLoading(true), 300);
|
||||
|
||||
const [data, links] = await Promise.all(requests);
|
||||
clearFilter && setIsLoading(false);
|
||||
clearTimeout(timerId);
|
||||
|
||||
links && setExternalLinks(links);
|
||||
|
||||
const users = [];
|
||||
const administrators = [];
|
||||
const expectedMembers = [];
|
||||
data?.map((fetchedMember) => {
|
||||
const member = {
|
||||
access: fetchedMember.access,
|
||||
canEditAccess: fetchedMember.canEditAccess,
|
||||
...fetchedMember.sharedTo,
|
||||
};
|
||||
|
||||
if (member.activationStatus === EmployeeActivationStatus.Pending) {
|
||||
member.isExpect = true;
|
||||
expectedMembers.push(member);
|
||||
} else if (
|
||||
member.access === ShareAccessRights.FullAccess ||
|
||||
member.access === ShareAccessRights.RoomManager
|
||||
) {
|
||||
administrators.push(member);
|
||||
} else {
|
||||
users.push(member);
|
||||
}
|
||||
});
|
||||
|
||||
let hasPrevAdminsTitle =
|
||||
members?.roomId === roomId && !clearFilter
|
||||
? getHasPrevTitle(members?.administrators, "administration")
|
||||
: false;
|
||||
|
||||
if (administrators.length && !hasPrevAdminsTitle) {
|
||||
administrators.unshift({
|
||||
id: "administration",
|
||||
displayName: t("Administration"),
|
||||
isTitle: true,
|
||||
});
|
||||
}
|
||||
|
||||
let hasPrevUsersTitle =
|
||||
members?.roomId === roomId && !clearFilter
|
||||
? getHasPrevTitle(members?.users, "user")
|
||||
: false;
|
||||
|
||||
if (users.length && !hasPrevUsersTitle) {
|
||||
users.unshift({ id: "user", displayName: t("Users"), isTitle: true });
|
||||
}
|
||||
|
||||
let hasPrevExpectedTitle =
|
||||
members?.roomId === roomId && !clearFilter
|
||||
? getHasPrevTitle(members?.expected, "expected")
|
||||
: false;
|
||||
|
||||
if (expectedMembers.length && !hasPrevExpectedTitle) {
|
||||
expectedMembers.unshift({
|
||||
id: "expected",
|
||||
displayName: t("ExpectUsers"),
|
||||
isTitle: true,
|
||||
isExpect: true,
|
||||
});
|
||||
}
|
||||
|
||||
setUpdateRoomMembers(false);
|
||||
|
||||
return {
|
||||
users,
|
||||
administrators,
|
||||
expected: expectedMembers,
|
||||
roomId,
|
||||
};
|
||||
const updateInfoPanelMembers = async () => {
|
||||
if (!infoPanelSelection) return;
|
||||
const fetchedMembers = await fetchMembers(t);
|
||||
setInfoPanelMembers(fetchedMembers);
|
||||
};
|
||||
|
||||
const getHasPrevTitle = (array, type) => {
|
||||
return array.findIndex((x) => x.id === type) > -1;
|
||||
};
|
||||
|
||||
const updateSelectionParentRoomActionSelection = useCallback(async () => {
|
||||
if (!selection?.isRoom || selection.id === members?.roomId) return;
|
||||
|
||||
const fetchedMembers = await fetchMembers(selection.id);
|
||||
setMembersList(fetchedMembers);
|
||||
|
||||
setSelectionParentRoom({
|
||||
...selection,
|
||||
members: fetchedMembers,
|
||||
});
|
||||
if (roomsView === "info_members" && !selection?.security?.Read)
|
||||
setView("info_details");
|
||||
}, [selection]);
|
||||
|
||||
useEffect(() => {
|
||||
updateSelectionParentRoomActionSelection();
|
||||
}, [selection, updateSelectionParentRoomActionSelection]);
|
||||
|
||||
const updateMembersAction = useCallback(async () => {
|
||||
if (!updateRoomMembers) return;
|
||||
|
||||
const fetchedMembers = await fetchMembers(selection.id);
|
||||
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: fetchedMembers,
|
||||
});
|
||||
|
||||
setMembersList(fetchedMembers);
|
||||
}, [selectionParentRoom, selection?.id, updateRoomMembers]);
|
||||
|
||||
useEffect(() => {
|
||||
updateMembersAction();
|
||||
}, [
|
||||
selectionParentRoom,
|
||||
selection?.id,
|
||||
updateRoomMembers,
|
||||
updateMembersAction,
|
||||
]);
|
||||
|
||||
const onRepeatInvitation = async () => {
|
||||
resendEmailInvitations(selectionParentRoom.id, true)
|
||||
.then(() =>
|
||||
toastr.success(t("PeopleTranslations:SuccessSentMultipleInvitatios"))
|
||||
)
|
||||
.catch((err) => toastr.error(err));
|
||||
};
|
||||
updateInfoPanelMembers();
|
||||
}, [infoPanelSelection]);
|
||||
|
||||
const loadNextPage = async () => {
|
||||
const roomId = selectionParentRoom.id;
|
||||
const fetchedMembers = await fetchMembers(roomId, false);
|
||||
const roomId = infoPanelSelection.id;
|
||||
const fetchedMembers = await fetchMembers(t, false);
|
||||
const { users, administrators, expected } = fetchedMembers;
|
||||
|
||||
const newMembers = {
|
||||
roomId: roomId,
|
||||
administrators: [...members.administrators, ...administrators],
|
||||
users: [...members.users, ...users],
|
||||
expected: [...members.expected, ...expected],
|
||||
administrators: [...infoPanelMembers.administrators, ...administrators],
|
||||
users: [...infoPanelMembers.users, ...users],
|
||||
expected: [...infoPanelMembers.expected, ...expected],
|
||||
};
|
||||
|
||||
setMembersList(newMembers);
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: newMembers,
|
||||
});
|
||||
setInfoPanelMembers(newMembers);
|
||||
};
|
||||
|
||||
if (isLoading) return <Loaders.InfoPanelViewLoader view="members" />;
|
||||
else if (!members) return <></>;
|
||||
if (membersIsLoading) return <Loaders.InfoPanelViewLoader view="members" />;
|
||||
else if (!infoPanelMembers) return <></>;
|
||||
|
||||
const [currentMember] = members.administrators.filter(
|
||||
const [currentMember] = infoPanelMembers.administrators.filter(
|
||||
(member) => member.id === selfId
|
||||
);
|
||||
|
||||
const { administrators, users, expected } = members;
|
||||
const { administrators, users, expected } = infoPanelMembers;
|
||||
|
||||
const membersList = [...administrators, ...users, ...expected];
|
||||
|
||||
const adminsTitleCount = administrators.length ? 1 : 0;
|
||||
@ -245,18 +87,13 @@ const Members = ({
|
||||
const expectedTitleCount = expected.length ? 1 : 0;
|
||||
|
||||
const headersCount = adminsTitleCount + usersTitleCount + expectedTitleCount;
|
||||
const dataReadyMembersList = selection?.id === selectionParentRoom?.id;
|
||||
|
||||
if (!dataReadyMembersList) return <></>;
|
||||
|
||||
const canInviteUserInRoomAbility = security?.EditAccess;
|
||||
|
||||
const onAddNewLink = async () => {
|
||||
if (isPublicRoom || primaryLink) {
|
||||
setLinkParams({ isEdit: false });
|
||||
setEditLinkPanelIsVisible(true);
|
||||
} else {
|
||||
getPrimaryLink(selectionParentRoom.id).then((link) => {
|
||||
getPrimaryLink(infoPanelSelection.id).then((link) => {
|
||||
setExternalLink(link);
|
||||
copy(link.sharedTo.shareLink);
|
||||
toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
@ -402,24 +239,8 @@ const Members = ({
|
||||
user={user}
|
||||
key={user.id}
|
||||
index={index + publicRoomItemsLength}
|
||||
security={security}
|
||||
membersHelper={membersHelper}
|
||||
currentMember={currentMember}
|
||||
updateRoomMemberRole={updateRoomMemberRole}
|
||||
roomId={selectionParentRoom.id}
|
||||
roomType={selectionParentRoom.roomType}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
setSelectionParentRoom={setSelectionParentRoom}
|
||||
changeUserType={changeUserType}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isTitle={user.isTitle}
|
||||
isExpect={user.isExpect}
|
||||
showInviteIcon={canInviteUserInRoomAbility && user.isExpect}
|
||||
onRepeatInvitation={onRepeatInvitation}
|
||||
setMembers={setMembersList}
|
||||
membersFilter={membersFilter}
|
||||
setMembersFilter={setMembersFilter}
|
||||
fetchMembers={fetchMembers}
|
||||
hasNextPage={
|
||||
membersList.length - headersCount < membersFilter.total
|
||||
}
|
||||
@ -435,115 +256,50 @@ export default inject(
|
||||
({
|
||||
auth,
|
||||
filesStore,
|
||||
peopleStore,
|
||||
selectedFolderStore,
|
||||
publicRoomStore,
|
||||
treeFoldersStore,
|
||||
dialogsStore,
|
||||
}) => {
|
||||
const {
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
setView,
|
||||
roomsView,
|
||||
|
||||
updateRoomMembers,
|
||||
setUpdateRoomMembers,
|
||||
|
||||
infoPanelSelection,
|
||||
setIsScrollLocked,
|
||||
membersList,
|
||||
setMembersList,
|
||||
selection: selectionItem,
|
||||
getIsRooms,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
fetchMembers,
|
||||
membersIsLoading,
|
||||
withPublicRoomBlock,
|
||||
} = auth.infoPanelStore;
|
||||
const {
|
||||
getRoomMembers,
|
||||
getRoomLinks,
|
||||
updateRoomMemberRole,
|
||||
resendEmailInvitations,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
selection,
|
||||
bufferSelection,
|
||||
} = filesStore;
|
||||
const { membersFilter } = filesStore;
|
||||
const { id: selfId } = auth.userStore.user;
|
||||
|
||||
const { changeType: changeUserType } = peopleStore;
|
||||
const {
|
||||
roomLinks,
|
||||
setExternalLinks,
|
||||
primaryLink,
|
||||
additionalLinks,
|
||||
setExternalLink,
|
||||
} = publicRoomStore;
|
||||
const { primaryLink, additionalLinks, setExternalLink } = publicRoomStore;
|
||||
const { isArchiveFolderRoot } = treeFoldersStore;
|
||||
const { setLinkParams, setEditLinkPanelIsVisible } = dialogsStore;
|
||||
|
||||
const roomType =
|
||||
selectedFolderStore.roomType ?? selectionParentRoom?.roomType;
|
||||
selectedFolderStore.roomType ?? infoPanelSelection?.roomType;
|
||||
|
||||
const isPublicRoomType =
|
||||
roomType === RoomsType.PublicRoom || roomType === RoomsType.CustomRoom;
|
||||
|
||||
const isPublicRoom = roomType === RoomsType.PublicRoom;
|
||||
|
||||
const room = selectionParentRoom
|
||||
? selectionParentRoom
|
||||
: selection.length
|
||||
? selection[0]
|
||||
: bufferSelection
|
||||
? bufferSelection
|
||||
: null;
|
||||
|
||||
const withPublicRoomBlock =
|
||||
room?.access === ShareAccessRights.RoomManager ||
|
||||
room?.access === ShareAccessRights.None;
|
||||
|
||||
const isShowParentRoom =
|
||||
getIsRooms() &&
|
||||
roomsView === "info_members" &&
|
||||
!selectionItem?.isRoom &&
|
||||
!!selectionParentRoom;
|
||||
|
||||
const infoSelection =
|
||||
selectionItem?.length > 1
|
||||
? null
|
||||
: isShowParentRoom
|
||||
? selectionParentRoom
|
||||
: selectionItem;
|
||||
infoPanelSelection?.length > 1 ? null : infoPanelSelection;
|
||||
|
||||
return {
|
||||
setView,
|
||||
roomsView,
|
||||
selection: infoSelection,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
|
||||
infoPanelSelection: infoSelection,
|
||||
setIsScrollLocked,
|
||||
|
||||
getRoomMembers,
|
||||
getRoomLinks,
|
||||
updateRoomMemberRole,
|
||||
|
||||
updateRoomMembers,
|
||||
setUpdateRoomMembers,
|
||||
|
||||
selfId,
|
||||
|
||||
resendEmailInvitations,
|
||||
changeUserType,
|
||||
isPublicRoomType,
|
||||
setExternalLinks,
|
||||
membersFilter,
|
||||
setMembersFilter,
|
||||
externalLinks: roomLinks,
|
||||
members: membersList,
|
||||
setMembersList,
|
||||
infoPanelMembers,
|
||||
setInfoPanelMembers,
|
||||
roomType,
|
||||
primaryLink,
|
||||
isArchiveFolder: isArchiveFolderRoot,
|
||||
isPublicRoom,
|
||||
|
||||
additionalLinks: additionalLinks,
|
||||
isArchiveFolder: isArchiveFolderRoot,
|
||||
setLinkParams,
|
||||
@ -552,6 +308,8 @@ export default inject(
|
||||
getPrimaryLink: filesStore.getPrimaryLink,
|
||||
setExternalLink,
|
||||
withPublicRoomBlock,
|
||||
fetchMembers,
|
||||
membersIsLoading,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -259,7 +259,7 @@ const LinkRow = (props) => {
|
||||
|
||||
export default inject(
|
||||
({ auth, dialogsStore, publicRoomStore, treeFoldersStore }) => {
|
||||
const { selectionParentRoom } = auth.infoPanelStore;
|
||||
const { infoPanelSelection } = auth.infoPanelStore;
|
||||
const { theme } = auth.settingsStore;
|
||||
|
||||
const {
|
||||
@ -274,14 +274,14 @@ export default inject(
|
||||
return {
|
||||
setLinkParams,
|
||||
editExternalLink,
|
||||
roomId: selectionParentRoom.id,
|
||||
roomId: infoPanelSelection.id,
|
||||
setExternalLink,
|
||||
setEditLinkPanelIsVisible,
|
||||
setDeleteLinkDialogVisible,
|
||||
setEmbeddingPanelIsVisible,
|
||||
isArchiveFolder: isArchiveFolderRoot,
|
||||
theme,
|
||||
isPublicRoomType: selectionParentRoom.roomType === RoomsType.PublicRoom,
|
||||
isPublicRoomType: infoPanelSelection.roomType === RoomsType.PublicRoom,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -2,7 +2,8 @@ import React, { useState, useCallback, useEffect, useRef, memo } from "react";
|
||||
import styled, { useTheme } from "styled-components";
|
||||
import { FixedSizeList as List, areEqual } from "react-window";
|
||||
import InfiniteLoader from "react-window-infinite-loader";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import { RowLoader } from "@docspace/shared/skeletons/selector";
|
||||
|
||||
import { CustomScrollbarsVirtualList } from "@docspace/shared/components/scrollbar";
|
||||
import { isMobile } from "@docspace/shared/utils";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
@ -31,11 +32,7 @@ const Item = memo(({ data, index, style }) => {
|
||||
if (!item) {
|
||||
return (
|
||||
<div style={{ ...style, width: "calc(100% - 20px)", margin: "0 -16px" }}>
|
||||
<Loaders.SelectorRowLoader
|
||||
isMultiSelect={false}
|
||||
isContainer={true}
|
||||
isUser={true}
|
||||
/>
|
||||
<RowLoader isMultiSelect={false} isContainer={true} isUser={true} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,21 +1,15 @@
|
||||
import InfoPanelRoomEmptyScreenSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate.svg?url";
|
||||
import InfoPanelRoomEmptyScreenDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import { StyledNoItemContainer } from "../../styles/noItem";
|
||||
|
||||
const NoRoomItem = ({ t, theme, setMembersList }) => {
|
||||
const NoRoomItem = ({ t, theme }) => {
|
||||
const imageSrc = theme.isBase
|
||||
? InfoPanelRoomEmptyScreenSvgUrl
|
||||
: InfoPanelRoomEmptyScreenDarkSvgUrl;
|
||||
|
||||
useEffect(() => {
|
||||
setMembersList(null);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<StyledNoItemContainer className="info-panel_gallery-empty-screen">
|
||||
<div className="no-thumbnail-img-wrapper">
|
||||
@ -31,6 +25,5 @@ const NoRoomItem = ({ t, theme, setMembersList }) => {
|
||||
export default inject(({ auth }) => {
|
||||
return {
|
||||
theme: auth.settingsStore.theme,
|
||||
setMembersList: auth.infoPanelStore.setMembersList,
|
||||
};
|
||||
})(observer(NoRoomItem));
|
||||
|
@ -40,7 +40,7 @@ const SeveralItems = ({ isAccounts, theme, selectedItems }) => {
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const selectedItems = auth.infoPanelStore.getSelectedItems();
|
||||
const selectedItems = auth.infoPanelStore.infoPanelSelectedItems;
|
||||
|
||||
return {
|
||||
theme: auth.settingsStore.theme,
|
||||
|
@ -21,7 +21,7 @@ const Share = (props) => {
|
||||
const {
|
||||
isRooms,
|
||||
setView,
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
getPrimaryFileLink,
|
||||
getFileLinks,
|
||||
editFileLink,
|
||||
@ -35,14 +35,14 @@ const Share = (props) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [loadingLinks, setLoadingLinks] = useState([]);
|
||||
|
||||
const hideSharePanel = isRooms || !selection?.canShare;
|
||||
const hideSharePanel = isRooms || !infoPanelSelection?.canShare;
|
||||
|
||||
useEffect(() => {
|
||||
if (hideSharePanel) {
|
||||
setView("info_details");
|
||||
}
|
||||
fetchLinks();
|
||||
}, [selection]);
|
||||
}, [infoPanelSelection]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLinks();
|
||||
@ -50,7 +50,7 @@ const Share = (props) => {
|
||||
}, [shareChanged]);
|
||||
|
||||
const fetchLinks = async () => {
|
||||
const res = await getFileLinks(selection.id);
|
||||
const res = await getFileLinks(infoPanelSelection.id);
|
||||
const primaryLink = res.items.filter(
|
||||
(item) => item.sharedTo.primary === true
|
||||
);
|
||||
@ -65,7 +65,7 @@ const Share = (props) => {
|
||||
|
||||
const addGeneralLink = async () => {
|
||||
addLoaderLink(true);
|
||||
const link = await getPrimaryFileLink(selection.id);
|
||||
const link = await getPrimaryFileLink(infoPanelSelection.id);
|
||||
setPrimaryFileLink([link]);
|
||||
copy(link.sharedTo.shareLink);
|
||||
toastr.success(t("SharingPanel:GeneralAccessLinkCopied"));
|
||||
@ -74,7 +74,7 @@ const Share = (props) => {
|
||||
const addAdditionalLinks = async () => {
|
||||
addLoaderLink(false);
|
||||
const newLink = await addFileLink(
|
||||
selection.id,
|
||||
infoPanelSelection.id,
|
||||
ShareAccessRights.ReadOnly,
|
||||
false,
|
||||
false
|
||||
@ -96,7 +96,7 @@ const Share = (props) => {
|
||||
setLoadingLinks([...loadingLinks, link.sharedTo.id]);
|
||||
|
||||
const res = await editFileLink(
|
||||
selection.id,
|
||||
infoPanelSelection.id,
|
||||
link.sharedTo.id,
|
||||
link.access,
|
||||
link.sharedTo.primary,
|
||||
@ -117,7 +117,7 @@ const Share = (props) => {
|
||||
setLoadingLinks([...loadingLinks, link.sharedTo.id]);
|
||||
|
||||
const res = await editFileLink(
|
||||
selection.id,
|
||||
infoPanelSelection.id,
|
||||
link.sharedTo.id,
|
||||
item.access,
|
||||
link.sharedTo.primary,
|
||||
@ -150,7 +150,7 @@ const Share = (props) => {
|
||||
setLoadingLinks([...loadingLinks, link.sharedTo.id]);
|
||||
|
||||
const res = await editFileLink(
|
||||
selection.id,
|
||||
infoPanelSelection.id,
|
||||
link.sharedTo.id,
|
||||
link.access,
|
||||
link.sharedTo.primary,
|
||||
@ -218,7 +218,9 @@ const Share = (props) => {
|
||||
changeShareOption={changeShareOption}
|
||||
changeAccessOption={changeAccessOption}
|
||||
changeExpirationOption={changeExpirationOption}
|
||||
availableExternalRights={selection.availableExternalRights}
|
||||
availableExternalRights={
|
||||
infoPanelSelection.availableExternalRights
|
||||
}
|
||||
loadingLinks={loadingLinks}
|
||||
/>
|
||||
</StyledLinks>
|
||||
@ -242,7 +244,9 @@ const Share = (props) => {
|
||||
changeShareOption={changeShareOption}
|
||||
changeAccessOption={changeAccessOption}
|
||||
changeExpirationOption={changeExpirationOption}
|
||||
availableExternalRights={selection.availableExternalRights}
|
||||
availableExternalRights={
|
||||
infoPanelSelection.availableExternalRights
|
||||
}
|
||||
loadingLinks={loadingLinks}
|
||||
/>
|
||||
</StyledLinks>
|
||||
|
@ -43,12 +43,12 @@ const InfoPanelHeaderContent = (props) => {
|
||||
const isAccounts = getIsAccounts();
|
||||
const isTrash = getIsTrash();
|
||||
|
||||
const isNoItem =
|
||||
selection?.isSelectedFolder && selection?.id === selection?.rootFolderId;
|
||||
const isRoot =
|
||||
selection?.isFolder && selection?.id === selection?.rootFolderId;
|
||||
const isSeveralItems = selection && Array.isArray(selection);
|
||||
|
||||
const withSubmenu =
|
||||
!isNoItem && !isSeveralItems && !isGallery && !isAccounts && !isTrash;
|
||||
!isRoot && !isSeveralItems && !isGallery && !isAccounts && !isTrash;
|
||||
|
||||
useEffect(() => {
|
||||
checkWidth();
|
||||
@ -94,9 +94,6 @@ const InfoPanelHeaderContent = (props) => {
|
||||
content: null,
|
||||
},
|
||||
];
|
||||
// const selectionRoomRights = selectionParentRoom
|
||||
// ? selectionParentRoom.security?.Read
|
||||
// : selection?.security?.Read;
|
||||
|
||||
const roomsSubmenu = [...submenuData];
|
||||
|
||||
@ -211,7 +208,7 @@ export default inject(({ auth, treeFoldersStore, pluginStore }) => {
|
||||
const { infoPanelItemsList } = pluginStore;
|
||||
|
||||
const {
|
||||
selection,
|
||||
infoPanelSelection,
|
||||
setIsVisible,
|
||||
roomsView,
|
||||
fileView,
|
||||
@ -222,7 +219,6 @@ export default inject(({ auth, treeFoldersStore, pluginStore }) => {
|
||||
getIsAccounts,
|
||||
getIsTrash,
|
||||
resetView,
|
||||
//selectionParentRoom,
|
||||
} = auth.infoPanelStore;
|
||||
|
||||
const { myRoomsId, archiveRoomsId } = treeFoldersStore;
|
||||
@ -230,7 +226,7 @@ export default inject(({ auth, treeFoldersStore, pluginStore }) => {
|
||||
const { enablePlugins } = auth.settingsStore;
|
||||
|
||||
return {
|
||||
selection,
|
||||
selection: infoPanelSelection,
|
||||
setIsVisible,
|
||||
roomsView,
|
||||
fileView,
|
||||
@ -247,10 +243,6 @@ export default inject(({ auth, treeFoldersStore, pluginStore }) => {
|
||||
archiveRoomsId,
|
||||
|
||||
enablePlugins,
|
||||
|
||||
// rootFolderType,
|
||||
|
||||
//selectionParentRoom,
|
||||
};
|
||||
})(
|
||||
withTranslation(["Common", "InfoPanel"])(
|
||||
|
@ -5,6 +5,8 @@ import { useNavigate, useLocation } from "react-router-dom";
|
||||
import queryString from "query-string";
|
||||
import MediaViewer from "@docspace/common/components/MediaViewer";
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
const FilesMediaViewer = (props) => {
|
||||
const {
|
||||
@ -106,7 +108,8 @@ const FilesMediaViewer = (props) => {
|
||||
};
|
||||
|
||||
const onChangeUrl = (id) => {
|
||||
const url = "/products/files/#preview/" + id;
|
||||
const url = combineUrl(MEDIA_VIEW_URL, id);
|
||||
|
||||
setCurrentId(id);
|
||||
navigate(url);
|
||||
};
|
||||
|
@ -242,8 +242,6 @@ class FilesTableHeader extends React.Component {
|
||||
!splitColumns ||
|
||||
isFrame;
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
|
||||
if (isFrame && frameTableColumns) {
|
||||
const frameTableArray = frameTableColumns.split(",");
|
||||
|
||||
@ -253,6 +251,8 @@ class FilesTableHeader extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
|
||||
this.setTableColumns(tableColumns);
|
||||
if (fromUpdate) {
|
||||
this.setState({
|
||||
|
@ -1202,7 +1202,7 @@ const SectionFilterContent = ({
|
||||
isHeader: true,
|
||||
isLast: isLastTypeOptionsRooms,
|
||||
},
|
||||
...Object.values(RoomsTypeValues).map((roomType) => {
|
||||
...RoomsTypeValues.map((roomType) => {
|
||||
switch (roomType) {
|
||||
case RoomsType.FillingFormsRoom:
|
||||
return {
|
||||
|
@ -930,6 +930,7 @@ const SectionHeaderContent = (props) => {
|
||||
: "",
|
||||
};
|
||||
|
||||
setSelected("none");
|
||||
setIsLoading(true);
|
||||
|
||||
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Article from "@docspace/common/components/Article";
|
||||
import Article from "@docspace/shared/components/article";
|
||||
import { ArticleHeaderContent, ArticleBodyContent } from "./Article";
|
||||
import { SectionHeaderContent, SectionPagingContent } from "./Section";
|
||||
import { inject, observer } from "mobx-react";
|
||||
@ -11,10 +11,11 @@ import SectionWrapper from "SRC_DIR/components/Section";
|
||||
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";
|
||||
import ArticleWrapper from "SRC_DIR/components/ArticleWrapper";
|
||||
|
||||
const ArticleSettings = React.memo(({ showArticleLoader }) => {
|
||||
return (
|
||||
<Article showArticleLoader={showArticleLoader}>
|
||||
<ArticleWrapper showArticleLoader={showArticleLoader}>
|
||||
<Article.Header>
|
||||
<ArticleHeaderContent />
|
||||
</Article.Header>
|
||||
@ -22,7 +23,7 @@ const ArticleSettings = React.memo(({ showArticleLoader }) => {
|
||||
<Article.Body>
|
||||
<ArticleBodyContent />
|
||||
</Article.Body>
|
||||
</Article>
|
||||
</ArticleWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -14,8 +14,6 @@ import { setDocumentTitle } from "SRC_DIR/helpers/utils";
|
||||
import { DropDownItem } from "@docspace/shared/components/drop-down-item";
|
||||
import { DropDown } from "@docspace/shared/components/drop-down";
|
||||
|
||||
import HexColorPickerComponent from "./sub-components/hexColorPicker";
|
||||
|
||||
import Loader from "./sub-components/loaderAppearance";
|
||||
|
||||
import { StyledComponent, StyledTheme } from "./Appearance/StyledApperance.js";
|
||||
@ -25,6 +23,8 @@ import hexToRgba from "hex-to-rgba";
|
||||
import { isMobile } from "@docspace/shared/utils";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
import { ColorPicker } from "@docspace/shared/components/color-picker";
|
||||
|
||||
const Appearance = (props) => {
|
||||
const {
|
||||
appearanceTheme,
|
||||
@ -594,11 +594,13 @@ const Appearance = (props) => {
|
||||
clickOutsideAction={onCloseHexColorPickerButtons}
|
||||
>
|
||||
<DropDownItem className="drop-down-item-hex">
|
||||
<HexColorPickerComponent
|
||||
<ColorPicker
|
||||
id="buttons-hex"
|
||||
onCloseHexColorPicker={onCloseHexColorPickerButtons}
|
||||
onAppliedColor={onAppliedColorButtons}
|
||||
onClose={onCloseHexColorPickerButtons}
|
||||
onApply={onAppliedColorButtons}
|
||||
appliedColor={appliedColorButtons}
|
||||
applyButtonLabel={t("Common:ApplyButton")}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
/>
|
||||
</DropDownItem>
|
||||
</DropDown>
|
||||
@ -614,11 +616,13 @@ const Appearance = (props) => {
|
||||
clickOutsideAction={onCloseHexColorPickerAccent}
|
||||
>
|
||||
<DropDownItem className="drop-down-item-hex">
|
||||
<HexColorPickerComponent
|
||||
<ColorPicker
|
||||
id="accent-hex"
|
||||
onCloseHexColorPicker={onCloseHexColorPickerAccent}
|
||||
onAppliedColor={onAppliedColorAccent}
|
||||
onClose={onCloseHexColorPickerAccent}
|
||||
onApply={onAppliedColorAccent}
|
||||
appliedColor={appliedColorAccent}
|
||||
applyButtonLabel={t("Common:ApplyButton")}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
/>
|
||||
</DropDownItem>
|
||||
</DropDown>
|
||||
|
@ -29,7 +29,12 @@ const AuditContent = ({ sectionWidth, item, isSettingNotPaid, locale }) => {
|
||||
isSettingNotPaid={isSettingNotPaid}
|
||||
>
|
||||
<div className="user-container-wrapper">
|
||||
<Text fontWeight={600} fontSize="14px" isTextOverflow={true}>
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize="14px"
|
||||
isTextOverflow={true}
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{item.user}
|
||||
</Text>
|
||||
</div>
|
||||
|
@ -25,9 +25,7 @@ const AuditTrail = (props) => {
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("AuditTrailNav"));
|
||||
|
||||
if (isAuditAvailable) {
|
||||
getAuditTrail();
|
||||
}
|
||||
getAuditTrail();
|
||||
|
||||
getLifetimeAuditSettings();
|
||||
}, []);
|
||||
@ -73,7 +71,7 @@ const AuditTrail = (props) => {
|
||||
securityLifetime={securityLifetime}
|
||||
lifetime={securityLifetime.auditTrailLifeTime}
|
||||
setLifetimeAuditSettings={setLifetimeAuditSettings}
|
||||
content={isAuditAvailable && getContent()}
|
||||
content={getContent()}
|
||||
downloadReport={t("DownloadReportBtnText")}
|
||||
downloadReportDescription={t("DownloadReportDescription")}
|
||||
getReport={getAuditTrailReport}
|
||||
|
@ -25,7 +25,12 @@ const HistoryContent = ({ sectionWidth, item, locale }) => {
|
||||
sectionWidth={sectionWidth}
|
||||
>
|
||||
<div className="user-container-wrapper">
|
||||
<Text fontWeight={600} fontSize="14px" isTextOverflow={true}>
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize="14px"
|
||||
isTextOverflow={true}
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{item.user}
|
||||
</Text>
|
||||
</div>
|
||||
@ -36,10 +41,16 @@ const HistoryContent = ({ sectionWidth, item, locale }) => {
|
||||
fontWeight={600}
|
||||
truncate={true}
|
||||
color="#A3A9AE"
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{dateStr}
|
||||
</Text>
|
||||
<Text fontSize="12px" as="div" fontWeight={600}>
|
||||
<Text
|
||||
fontSize="12px"
|
||||
as="div"
|
||||
fontWeight={600}
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{item.action}
|
||||
</Text>
|
||||
</StyledRowContent>
|
||||
|
@ -46,6 +46,7 @@ const PeopleTableRow = (props) => {
|
||||
fontSize="12px"
|
||||
fontWeight={600}
|
||||
truncate
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{item.user}
|
||||
</Text>
|
||||
@ -57,6 +58,7 @@ const PeopleTableRow = (props) => {
|
||||
fontSize="12px"
|
||||
fontWeight={600}
|
||||
truncate
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{dateStr}
|
||||
</Text>
|
||||
@ -70,6 +72,7 @@ const PeopleTableRow = (props) => {
|
||||
fontWeight={600}
|
||||
onClick={onEmailClick}
|
||||
isTextOverflow
|
||||
className="settings_unavailable"
|
||||
>
|
||||
{item.action}
|
||||
</Text>
|
||||
|
@ -25,9 +25,7 @@ const LoginHistory = (props) => {
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("LoginHistoryTitle"));
|
||||
|
||||
if (isAuditAvailable) {
|
||||
getLoginHistory();
|
||||
}
|
||||
getLoginHistory();
|
||||
|
||||
getLifetimeAuditSettings();
|
||||
}, []);
|
||||
@ -73,7 +71,7 @@ const LoginHistory = (props) => {
|
||||
lifetime={securityLifetime.loginHistoryLifeTime}
|
||||
securityLifetime={securityLifetime}
|
||||
setLifetimeAuditSettings={setLifetimeAuditSettings}
|
||||
content={isAuditAvailable && getContent()}
|
||||
content={getContent()}
|
||||
downloadReport={t("DownloadReportBtnText")}
|
||||
downloadReportDescription={t("DownloadReportDescription")}
|
||||
getReport={getLoginHistoryReport}
|
||||
|
@ -27,7 +27,7 @@ const Sdk = ({
|
||||
user,
|
||||
updateProfileCulture,
|
||||
getRoomsIcon,
|
||||
getPrimaryLink,
|
||||
fetchExternalLinks,
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
window.addEventListener("message", handleMessage, false);
|
||||
@ -128,9 +128,23 @@ const Sdk = ({
|
||||
data[0].icon = await getRoomsIcon(data[0].roomType, false, 32);
|
||||
}
|
||||
|
||||
if (data[0].roomType === RoomsType.PublicRoom) {
|
||||
const { sharedTo } = await getPrimaryLink(data[0].id);
|
||||
data[0].requestToken = sharedTo?.requestToken;
|
||||
if (
|
||||
data[0].roomType === RoomsType.PublicRoom ||
|
||||
(data[0].roomType === RoomsType.CustomRoom && data[0].shared)
|
||||
) {
|
||||
const links = await fetchExternalLinks(data[0].id);
|
||||
|
||||
const requestTokens = links.map((link) => {
|
||||
const { id, title, requestToken } = link.sharedTo;
|
||||
|
||||
return {
|
||||
id,
|
||||
title,
|
||||
requestToken,
|
||||
};
|
||||
});
|
||||
|
||||
data[0].requestTokens = requestTokens;
|
||||
}
|
||||
|
||||
frameCallEvent({ event: "onSelectCallback", data });
|
||||
@ -193,28 +207,30 @@ const Sdk = ({
|
||||
return component;
|
||||
};
|
||||
|
||||
export default inject(({ auth, settingsStore, peopleStore, filesStore }) => {
|
||||
const { login, logout, userStore } = auth;
|
||||
const { theme, setFrameConfig, frameConfig, getSettings, isLoaded } =
|
||||
auth.settingsStore;
|
||||
const { loadCurrentUser, user } = userStore;
|
||||
const { updateProfileCulture } = peopleStore.targetUserStore;
|
||||
const { getIcon, getRoomsIcon } = settingsStore;
|
||||
const { getPrimaryLink } = filesStore;
|
||||
export default inject(
|
||||
({ auth, settingsStore, peopleStore, publicRoomStore }) => {
|
||||
const { login, logout, userStore } = auth;
|
||||
const { theme, setFrameConfig, frameConfig, getSettings, isLoaded } =
|
||||
auth.settingsStore;
|
||||
const { loadCurrentUser, user } = userStore;
|
||||
const { updateProfileCulture } = peopleStore.targetUserStore;
|
||||
const { getIcon, getRoomsIcon } = settingsStore;
|
||||
const { fetchExternalLinks } = publicRoomStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setFrameConfig,
|
||||
frameConfig,
|
||||
login,
|
||||
logout,
|
||||
getSettings,
|
||||
loadCurrentUser,
|
||||
getIcon,
|
||||
getRoomsIcon,
|
||||
isLoaded,
|
||||
updateProfileCulture,
|
||||
user,
|
||||
getPrimaryLink,
|
||||
};
|
||||
})(observer(Sdk));
|
||||
return {
|
||||
theme,
|
||||
setFrameConfig,
|
||||
frameConfig,
|
||||
login,
|
||||
logout,
|
||||
getSettings,
|
||||
loadCurrentUser,
|
||||
getIcon,
|
||||
getRoomsIcon,
|
||||
isLoaded,
|
||||
updateProfileCulture,
|
||||
user,
|
||||
fetchExternalLinks,
|
||||
};
|
||||
}
|
||||
)(observer(Sdk));
|
||||
|
@ -18,8 +18,12 @@ import { inject, observer } from "mobx-react";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { Encoder } from "@docspace/shared/utils/encoder";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { MAX_FILE_COMMENT_LENGTH } from "@docspace/shared/constants";
|
||||
import {
|
||||
MAX_FILE_COMMENT_LENGTH,
|
||||
MEDIA_VIEW_URL,
|
||||
} from "@docspace/shared/constants";
|
||||
import moment from "moment-timezone";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
const StyledExternalLinkIcon = styled(ExternalLinkIcon)`
|
||||
${commonIconsStyles}
|
||||
@ -110,7 +114,7 @@ const VersionRow = (props) => {
|
||||
|
||||
if (MediaView || ImageView) {
|
||||
return window.open(
|
||||
"/products/files/#preview/" + info.id,
|
||||
combineUrl(MEDIA_VIEW_URL, info.id),
|
||||
window.DocSpaceConfig?.editor?.openOnNewPage ? "_blank" : "_self"
|
||||
);
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ const Wizard = loadable(() => import("../pages/Wizard"));
|
||||
const PreparationPortal = loadable(() => import("../pages/PreparationPortal"));
|
||||
const PortalUnavailable = loadable(() => import("../pages/PortalUnavailable"));
|
||||
const ErrorUnavailable = loadable(() => import("../pages/Errors/Unavailable"));
|
||||
const AccessRestricted = loadable(() =>
|
||||
import("../pages/Errors/AccessRestricted")
|
||||
const AccessRestricted = loadable(
|
||||
() => import("../pages/Errors/AccessRestricted")
|
||||
);
|
||||
|
||||
const Error401 = loadable(() => import("client/Error401"));
|
||||
@ -169,7 +169,7 @@ const ClientRoutes = [
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "products/files",
|
||||
path: "media/view/:id",
|
||||
element: (
|
||||
<PrivateRoute>
|
||||
<FilesView />
|
||||
|
@ -285,7 +285,7 @@ class ContextOptionsStore {
|
||||
|
||||
lockFile = (item, t) => {
|
||||
const { id, locked } = item;
|
||||
const { setSelection: setInfoPanelSelection } =
|
||||
const { setInfoPanelSelection: setInfoPanelSelection } =
|
||||
this.authStore.infoPanelStore;
|
||||
|
||||
this.filesActionsStore
|
||||
@ -620,10 +620,8 @@ class ContextOptionsStore {
|
||||
};
|
||||
|
||||
onShowInfoPanel = (item, view) => {
|
||||
const { setSelection, setIsVisible, setView } =
|
||||
this.authStore.infoPanelStore;
|
||||
const { setIsVisible, setView } = this.authStore.infoPanelStore;
|
||||
|
||||
setSelection(item);
|
||||
setIsVisible(true);
|
||||
view && setView(view);
|
||||
};
|
||||
@ -1166,6 +1164,8 @@ class ContextOptionsStore {
|
||||
) === -1;
|
||||
}
|
||||
|
||||
const isArchive = item.rootFolderType === FolderType.Archive;
|
||||
|
||||
const optionsModel = [
|
||||
{
|
||||
id: "option_select",
|
||||
@ -1286,9 +1286,7 @@ class ContextOptionsStore {
|
||||
icon: InvitationLinkReactSvgUrl,
|
||||
onClick: () => this.onCopyLink(item, t),
|
||||
disabled:
|
||||
(isPublicRoomType &&
|
||||
item.canCopyPublicLink &&
|
||||
!this.treeFoldersStore.isArchiveFolder) ||
|
||||
(isPublicRoomType && item.canCopyPublicLink && !isArchive) ||
|
||||
this.publicRoomStore.isPublicRoom,
|
||||
},
|
||||
{
|
||||
@ -1298,7 +1296,7 @@ class ContextOptionsStore {
|
||||
icon: TabletLinkReactSvgUrl,
|
||||
disabled:
|
||||
this.publicRoomStore.isPublicRoom ||
|
||||
this.treeFoldersStore.isArchiveFolder ||
|
||||
isArchive ||
|
||||
!item.canCopyPublicLink ||
|
||||
!isPublicRoomType,
|
||||
onClick: async () => {
|
||||
@ -1482,9 +1480,7 @@ class ContextOptionsStore {
|
||||
icon: LeaveRoomSvgUrl,
|
||||
onClick: this.onLeaveRoom,
|
||||
disabled:
|
||||
this.treeFoldersStore.isArchiveFolder ||
|
||||
!item.inRoom ||
|
||||
this.publicRoomStore.isPublicRoom,
|
||||
isArchive || !item.inRoom || this.publicRoomStore.isPublicRoom,
|
||||
},
|
||||
{
|
||||
id: "option_unarchive-room",
|
||||
|
@ -131,7 +131,7 @@ class DialogsStore {
|
||||
visible &&
|
||||
!this.filesStore.hasSelection &&
|
||||
!this.filesStore.hasBufferSelection &&
|
||||
!this.authStore.infoPanelStore.selection
|
||||
!this.authStore.infoPanelStore.infoPanelSelection
|
||||
)
|
||||
return;
|
||||
|
||||
@ -160,7 +160,7 @@ class DialogsStore {
|
||||
visible &&
|
||||
!this.filesStore.hasSelection &&
|
||||
!this.filesStore.hasBufferSelection &&
|
||||
!this.authStore.infoPanelStore.selection
|
||||
!this.authStore.infoPanelStore.infoPanelSelection
|
||||
) {
|
||||
console.log("No files selected");
|
||||
return;
|
||||
|
@ -55,6 +55,7 @@ import {
|
||||
getCategoryTypeByFolderType,
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
|
||||
class FilesActionStore {
|
||||
authStore;
|
||||
@ -289,8 +290,8 @@ class FilesActionStore {
|
||||
let selection = newSelection
|
||||
? newSelection
|
||||
: this.filesStore.selection.length
|
||||
? this.filesStore.selection
|
||||
: [bufferSelection];
|
||||
? this.filesStore.selection
|
||||
: [bufferSelection];
|
||||
|
||||
selection = selection.filter((item) => item.security.Delete);
|
||||
|
||||
@ -996,7 +997,8 @@ class FilesActionStore {
|
||||
setPinAction = (action, id, t) => {
|
||||
const { pinRoom, unpinRoom, updateRoomPin, setSelected } = this.filesStore;
|
||||
|
||||
const { selection, setSelection } = this.authStore.infoPanelStore;
|
||||
const { infoPanelSelection, setInfoPanelSelection } =
|
||||
this.authStore.infoPanelStore;
|
||||
|
||||
const items = Array.isArray(id) ? id : [id];
|
||||
|
||||
@ -1013,8 +1015,8 @@ class FilesActionStore {
|
||||
return Promise.all(actions)
|
||||
.then(() => {
|
||||
this.updateCurrentFolder(null, items, null, operationId);
|
||||
if (selection) {
|
||||
setSelection({ ...selection, pinned: true });
|
||||
if (infoPanelSelection) {
|
||||
setInfoPanelSelection({ ...infoPanelSelection, pinned: true });
|
||||
}
|
||||
})
|
||||
.then(() => setSelected("close"))
|
||||
@ -1035,7 +1037,7 @@ class FilesActionStore {
|
||||
.then(() => {
|
||||
this.updateCurrentFolder(null, items, null, operationId);
|
||||
if (selection) {
|
||||
setSelection({ ...selection, pinned: false });
|
||||
setInfoPanelSelection({ ...selection, pinned: false });
|
||||
}
|
||||
})
|
||||
.then(() => setSelected("close"))
|
||||
@ -1731,9 +1733,10 @@ class FilesActionStore {
|
||||
|
||||
onShowInfoPanel = () => {
|
||||
const { selection } = this.filesStore;
|
||||
const { setSelection, setIsVisible } = this.authStore.infoPanelStore;
|
||||
const { setInfoPanelSelection, setIsVisible } =
|
||||
this.authStore.infoPanelStore;
|
||||
|
||||
setSelection([selection]);
|
||||
setInfoPanelSelection([selection]);
|
||||
setIsVisible(true);
|
||||
};
|
||||
|
||||
@ -2200,7 +2203,7 @@ class FilesActionStore {
|
||||
);
|
||||
setMediaViewerData({ visible: true, id });
|
||||
|
||||
const url = "/products/files/#preview/" + id;
|
||||
const url = combineUrl(MEDIA_VIEW_URL, id);
|
||||
|
||||
if (this.publicRoomStore.isPublicRoom) return;
|
||||
|
||||
@ -2230,7 +2233,9 @@ class FilesActionStore {
|
||||
onClickBack = () => {
|
||||
const { roomType, ...rest } = this.selectedFolderStore;
|
||||
const { setSelectedNode } = this.treeFoldersStore;
|
||||
const { clearFiles } = this.filesStore;
|
||||
const { clearFiles, setBufferSelection } = this.filesStore;
|
||||
|
||||
setBufferSelection(null);
|
||||
|
||||
const categoryType = getCategoryType(window.DocSpace.location);
|
||||
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
|
||||
import { RoomsTypeValues } from "@docspace/shared/utils";
|
||||
import { RoomsTypes } from "@docspace/shared/utils";
|
||||
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { updateTempContent } from "@docspace/shared/utils/common";
|
||||
@ -219,7 +219,7 @@ class FilesStore {
|
||||
} else if (opt.cmd === "delete") {
|
||||
this.selectedFolderStore[opt.type + "sCount"]--;
|
||||
}
|
||||
this.authStore.infoPanelStore.reloadSelection();
|
||||
// this.authStore.infoPanelStore.updateInfoPanelSelection();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1455,9 +1455,12 @@ class FilesStore {
|
||||
// Clear all selections
|
||||
this.setSelected("close");
|
||||
|
||||
// Restore not processed
|
||||
tempSelection.length && this.setSelection(tempSelection);
|
||||
tempBuffer && this.setBufferSelection(tempBuffer);
|
||||
// TODO: see bug 63479
|
||||
if (this.selectedFolderStore?.id === folderId) {
|
||||
// Restore not processed
|
||||
tempSelection.length && this.setSelection(tempSelection);
|
||||
tempBuffer && this.setBufferSelection(tempBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1498,6 +1501,9 @@ class FilesStore {
|
||||
canCopyPublicLink =
|
||||
room.access === ShareAccessRights.RoomManager ||
|
||||
room.access === ShareAccessRights.None;
|
||||
|
||||
room.canCopyPublicLink = canCopyPublicLink;
|
||||
this.authStore.infoPanelStore.setInfoPanelRoom(room);
|
||||
}
|
||||
|
||||
const { mute } = room;
|
||||
@ -1712,6 +1718,7 @@ class FilesStore {
|
||||
}
|
||||
}
|
||||
|
||||
this.authStore.infoPanelStore.setInfoPanelRoom(null);
|
||||
this.selectedFolderStore.setSelectedFolder({
|
||||
folders: data.folders,
|
||||
...data.current,
|
||||
@ -2952,7 +2959,7 @@ class FilesStore {
|
||||
const url = getCategoryUrl(this.categoryType, id);
|
||||
|
||||
if (canOpenPlayer) {
|
||||
return combineUrl(proxyURL, config.homepage, `${url}/#preview/${id}`);
|
||||
return combineUrl(proxyURL, config.homepage, url, id);
|
||||
}
|
||||
|
||||
if (isFolder) {
|
||||
@ -3227,8 +3234,8 @@ class FilesStore {
|
||||
|
||||
if (this.folders.length) {
|
||||
for (const item of this.folders) {
|
||||
if (item.roomType && RoomsTypeValues[item.roomType]) {
|
||||
cbMenu.push(`room-${RoomsTypeValues[item.roomType]}`);
|
||||
if (item.roomType && RoomsTypes[item.roomType]) {
|
||||
cbMenu.push(`room-${RoomsTypes[item.roomType]}`);
|
||||
} else {
|
||||
cbMenu.push(FilterType.FoldersOnly);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import {
|
||||
isVideo,
|
||||
} from "@docspace/common/components/MediaViewer/helpers";
|
||||
import { thumbnailStatuses } from "SRC_DIR/helpers/filesConstants";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
const FirstUrlKey = "isFirstUrl";
|
||||
|
||||
@ -76,7 +78,7 @@ class MediaViewerDataStore {
|
||||
changeUrl = (id) => {
|
||||
if (this.publicRoomStore.isPublicRoom) return;
|
||||
|
||||
const url = "/products/files/#preview/" + id;
|
||||
const url = combineUrl(MEDIA_VIEW_URL, id);
|
||||
window.DocSpace.navigate(url);
|
||||
};
|
||||
|
||||
|
@ -75,7 +75,7 @@ class OformsStore {
|
||||
|
||||
setGallerySelected = (gallerySelected) => {
|
||||
this.gallerySelected = gallerySelected;
|
||||
this.authStore.infoPanelStore.setSelection(gallerySelected);
|
||||
this.authStore.infoPanelStore.setInfoPanelSelection(gallerySelected);
|
||||
};
|
||||
|
||||
setOformLocales = (oformLocales) => (this.oformLocales = oformLocales);
|
||||
|
@ -15,7 +15,7 @@ import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
import { ZendeskAPI } from "@docspace/common/components/Zendesk";
|
||||
import { ZendeskAPI } from "@docspace/shared/components/zendesk";
|
||||
import { LIVE_CHAT_LOCAL_STORAGE_KEY } from "@docspace/shared/constants";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { isDesktop, isTablet } from "@docspace/shared/utils";
|
||||
|
@ -34,6 +34,7 @@ class SelectedFolderStore {
|
||||
security = null;
|
||||
type = null;
|
||||
inRoom = false;
|
||||
isFolder = true;
|
||||
|
||||
constructor(settingsStore) {
|
||||
makeAutoObservable(this);
|
||||
@ -70,6 +71,7 @@ class SelectedFolderStore {
|
||||
rootFolderId: this.rootFolderId,
|
||||
security: this.security,
|
||||
inRoom: this.inRoom,
|
||||
isFolder: this.isFolder,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -36,6 +36,7 @@ class SettingsStore {
|
||||
keepNewFileName = null;
|
||||
thumbnails1280x720 = window.DocSpaceConfig?.thumbnails1280x720 || false;
|
||||
chunkUploadSize = 1024 * 1023; // 1024 * 1023; //~0.999mb
|
||||
chunkUploadCount = 5;
|
||||
|
||||
settingsIsLoaded = false;
|
||||
|
||||
|
@ -31,8 +31,6 @@ import {
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
|
||||
const UPLOAD_LIMIT_AT_ONCE = 5;
|
||||
|
||||
class UploadDataStore {
|
||||
authStore;
|
||||
treeFoldersStore;
|
||||
@ -69,6 +67,7 @@ class UploadDataStore {
|
||||
uploadedFilesSize = 0;
|
||||
|
||||
isParallel = true;
|
||||
asyncUploadObj = {};
|
||||
|
||||
constructor(
|
||||
authStore,
|
||||
@ -147,6 +146,7 @@ class UploadDataStore {
|
||||
|
||||
this.isUploadingAndConversion = false;
|
||||
this.isUploading = false;
|
||||
this.asyncUploadObj = {};
|
||||
};
|
||||
|
||||
removeFileFromList = (id) => {
|
||||
@ -704,6 +704,7 @@ class UploadDataStore {
|
||||
this.files = [];
|
||||
this.filesToConversion = [];
|
||||
this.uploadedFilesSize = 0;
|
||||
this.asyncUploadObj = {};
|
||||
}
|
||||
|
||||
let newFiles = this.files;
|
||||
@ -904,100 +905,90 @@ class UploadDataStore {
|
||||
}
|
||||
};
|
||||
|
||||
uploadFileChunks = async (
|
||||
location,
|
||||
requestsDataArray,
|
||||
checkChunkUpload = (
|
||||
t,
|
||||
res,
|
||||
fileSize,
|
||||
index,
|
||||
indexOfFile,
|
||||
file,
|
||||
path,
|
||||
t
|
||||
length,
|
||||
resolve,
|
||||
reject,
|
||||
isAsyncUpload = false
|
||||
) => {
|
||||
const length = requestsDataArray.length;
|
||||
for (let index = 0; index < length; index++) {
|
||||
if (
|
||||
this.uploaded ||
|
||||
!this.files.some((f) => f.file === file) ||
|
||||
this.files[indexOfFile].cancel
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!res.data.data && res.data.message) {
|
||||
return reject(res.data.message);
|
||||
}
|
||||
|
||||
const res = await uploadFile(location, requestsDataArray[index]);
|
||||
const { uploaded, id: fileId, file: fileInfo } = res.data.data;
|
||||
|
||||
//console.log(`Uploaded chunk ${index}/${length}`, res);
|
||||
let uploadedSize, newPercent;
|
||||
|
||||
//let isLatestFile = indexOfFile === newFilesLength - 1;
|
||||
if (!this.isParallel) {
|
||||
uploadedSize = uploaded
|
||||
? fileSize
|
||||
: index * this.settingsStore.chunkUploadSize;
|
||||
|
||||
if (!res.data.data && res.data.message) {
|
||||
return Promise.reject(res.data.message);
|
||||
}
|
||||
|
||||
const { uploaded, id: fileId, file: fileInfo } = res.data.data;
|
||||
|
||||
let uploadedSize, newPercent;
|
||||
|
||||
if (!this.isParallel) {
|
||||
uploadedSize = uploaded
|
||||
? fileSize
|
||||
: index * this.settingsStore.chunkUploadSize;
|
||||
|
||||
newPercent = this.getNewPercent(uploadedSize, indexOfFile);
|
||||
newPercent = this.getNewPercent(uploadedSize, indexOfFile);
|
||||
} else {
|
||||
if (!uploaded) {
|
||||
uploadedSize =
|
||||
fileSize <= this.settingsStore.chunkUploadSize
|
||||
? fileSize
|
||||
: this.settingsStore.chunkUploadSize;
|
||||
} else {
|
||||
if (!uploaded) {
|
||||
uploadedSize =
|
||||
fileSize <= this.settingsStore.chunkUploadSize
|
||||
? fileSize
|
||||
: this.settingsStore.chunkUploadSize;
|
||||
} else {
|
||||
uploadedSize = fileSize - index * this.settingsStore.chunkUploadSize;
|
||||
}
|
||||
newPercent = this.getFilesPercent(uploadedSize);
|
||||
uploadedSize = fileSize - index * this.settingsStore.chunkUploadSize;
|
||||
}
|
||||
newPercent = this.getFilesPercent(uploadedSize);
|
||||
}
|
||||
|
||||
const percentCurrentFile = ((index + 1) / length) * 100;
|
||||
if (isAsyncUpload && !uploaded && newPercent >= 100) {
|
||||
newPercent = 99;
|
||||
}
|
||||
|
||||
const fileIndex = this.uploadedFilesHistory.findIndex(
|
||||
(f) => f.uniqueId === this.files[indexOfFile].uniqueId
|
||||
);
|
||||
if (fileIndex > -1)
|
||||
this.uploadedFilesHistory[fileIndex].percent = percentCurrentFile;
|
||||
const percentCurrentFile = ((index + 1) / length) * 100;
|
||||
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
percent: newPercent,
|
||||
visible: true,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: percentCurrentFile,
|
||||
},
|
||||
const fileIndex = this.uploadedFilesHistory.findIndex(
|
||||
(f) => f.uniqueId === this.files[indexOfFile].uniqueId
|
||||
);
|
||||
if (fileIndex > -1)
|
||||
this.uploadedFilesHistory[fileIndex].percent = percentCurrentFile;
|
||||
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
percent: newPercent,
|
||||
visible: true,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: percentCurrentFile,
|
||||
},
|
||||
});
|
||||
|
||||
if (uploaded) {
|
||||
runInAction(() => {
|
||||
this.files[indexOfFile].action = "uploaded";
|
||||
this.files[indexOfFile].fileId = fileId;
|
||||
this.files[indexOfFile].fileInfo = fileInfo;
|
||||
|
||||
if (!this.isParallel) this.percent = newPercent;
|
||||
|
||||
if (this.isParallel) {
|
||||
this.currentUploadNumber -= 1;
|
||||
|
||||
const nextFileIndex = this.files.findIndex((f) => !f.inAction);
|
||||
|
||||
if (nextFileIndex !== -1) {
|
||||
this.startSessionFunc(nextFileIndex, t);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (uploaded) {
|
||||
runInAction(() => {
|
||||
this.files[indexOfFile].action = "uploaded";
|
||||
this.files[indexOfFile].fileId = fileId;
|
||||
this.files[indexOfFile].fileInfo = fileInfo;
|
||||
|
||||
if (!this.isParallel) this.percent = newPercent;
|
||||
|
||||
if (this.isParallel) {
|
||||
this.currentUploadNumber -= 1;
|
||||
|
||||
const nextFileIndex = this.files.findIndex((f) => !f.inAction);
|
||||
|
||||
if (nextFileIndex !== -1) {
|
||||
this.startSessionFunc(nextFileIndex, t);
|
||||
}
|
||||
}
|
||||
if (fileInfo.version > 2) {
|
||||
this.filesStore.setHighlightFile({
|
||||
highlightFileId: fileInfo.id,
|
||||
isFileHasExst: !fileInfo.fileExst,
|
||||
});
|
||||
|
||||
if (fileInfo.version > 2) {
|
||||
this.filesStore.setHighlightFile({
|
||||
highlightFileId: fileInfo.id,
|
||||
isFileHasExst: !fileInfo.fileExst,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1005,7 +996,7 @@ class UploadDataStore {
|
||||
|
||||
const currentFile = this.files[indexOfFile];
|
||||
currentFile.path = path;
|
||||
if (!currentFile) return Promise.resolve();
|
||||
if (!currentFile) return resolve();
|
||||
const { needConvert } = currentFile;
|
||||
|
||||
if (needConvert) {
|
||||
@ -1019,12 +1010,195 @@ class UploadDataStore {
|
||||
} else {
|
||||
this.filesToConversion.push(currentFile);
|
||||
}
|
||||
return Promise.resolve();
|
||||
return resolve();
|
||||
} else {
|
||||
if (currentFile.action === "uploaded") {
|
||||
this.refreshFiles(currentFile);
|
||||
}
|
||||
return Promise.resolve();
|
||||
if (!isAsyncUpload || res.status === 201) {
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
asyncUpload = async (t, chunkData, resolve, reject) => {
|
||||
const { operationId, file, fileSize, indexOfFile, path, length } =
|
||||
chunkData;
|
||||
|
||||
if (
|
||||
this.uploaded ||
|
||||
!this.files.some((f) => f.file === file) ||
|
||||
this.files[indexOfFile].cancel
|
||||
) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
if (!this.asyncUploadObj[operationId]) {
|
||||
return reject();
|
||||
}
|
||||
const chunkObjIndex = this.asyncUploadObj[
|
||||
operationId
|
||||
].chunksArray.findIndex((x) => !x.isActive && !x.isFinalize);
|
||||
|
||||
if (chunkObjIndex !== -1) {
|
||||
this.asyncUploadObj[operationId].chunksArray[
|
||||
chunkObjIndex
|
||||
].isActive = true;
|
||||
|
||||
try {
|
||||
const res = await this.asyncUploadObj[operationId].chunksArray[
|
||||
chunkObjIndex
|
||||
].onUpload();
|
||||
|
||||
this.asyncUploadObj[operationId].chunksArray[
|
||||
chunkObjIndex
|
||||
].isFinished = true;
|
||||
|
||||
if (!res.data.data && res.data.message) {
|
||||
delete this.asyncUploadObj[operationId];
|
||||
return reject(res.data.message);
|
||||
} else this.asyncUpload(t, chunkData, resolve, reject);
|
||||
|
||||
const activeLength = this.asyncUploadObj[operationId]
|
||||
? this.asyncUploadObj[operationId].chunksArray.filter(
|
||||
(x) => x.isActive
|
||||
).length - 1
|
||||
: 0;
|
||||
|
||||
this.checkChunkUpload(
|
||||
t,
|
||||
res,
|
||||
fileSize,
|
||||
activeLength,
|
||||
indexOfFile,
|
||||
path,
|
||||
length,
|
||||
resolve,
|
||||
reject,
|
||||
true
|
||||
);
|
||||
|
||||
const finalizeChunk = this.asyncUploadObj[
|
||||
operationId
|
||||
].chunksArray.findIndex((x) => !x.isFinished && !x.isFinalize);
|
||||
|
||||
if (finalizeChunk === -1) {
|
||||
const finalizeChunkIndex = this.asyncUploadObj[
|
||||
operationId
|
||||
].chunksArray.findIndex((x) => x.isFinalize);
|
||||
|
||||
if (finalizeChunkIndex > -1) {
|
||||
const finalizeRes = await this.asyncUploadObj[
|
||||
operationId
|
||||
].chunksArray[finalizeChunkIndex].onUpload();
|
||||
|
||||
const finalizeIndex =
|
||||
this.asyncUploadObj[operationId].chunksArray.length - 1;
|
||||
|
||||
this.checkChunkUpload(
|
||||
t,
|
||||
finalizeRes,
|
||||
fileSize,
|
||||
finalizeIndex,
|
||||
indexOfFile,
|
||||
path,
|
||||
length,
|
||||
resolve,
|
||||
reject,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return reject(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uploadFileChunks = async (
|
||||
location,
|
||||
requestsDataArray,
|
||||
fileSize,
|
||||
indexOfFile,
|
||||
file,
|
||||
path,
|
||||
t,
|
||||
operationId,
|
||||
toFolderId
|
||||
) => {
|
||||
const { chunkUploadCount: asyncChunkUploadCount } = this.settingsStore;
|
||||
const length = requestsDataArray.length;
|
||||
|
||||
const isThirdPartyFolder = typeof toFolderId === "string";
|
||||
if (!isThirdPartyFolder) {
|
||||
const chunksArray = [];
|
||||
for (let index = 0; index < length; index++) {
|
||||
chunksArray.push({
|
||||
isActive: false,
|
||||
isFinished: false,
|
||||
isFinalize: false,
|
||||
onUpload: () =>
|
||||
uploadFile(
|
||||
location + `&chunkNumber=${index + 1}&upload=true`,
|
||||
requestsDataArray[index]
|
||||
),
|
||||
});
|
||||
}
|
||||
chunksArray.push({
|
||||
isActive: false,
|
||||
isFinished: false,
|
||||
isFinalize: true,
|
||||
onUpload: () => uploadFile(location + "&finalize=true"),
|
||||
});
|
||||
|
||||
if (!this.asyncUploadObj[operationId]) {
|
||||
this.asyncUploadObj[operationId] = { chunksArray: [] };
|
||||
this.asyncUploadObj[operationId].chunksArray = chunksArray;
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
let i =
|
||||
length <= asyncChunkUploadCount ? length : asyncChunkUploadCount;
|
||||
while (i !== 0) {
|
||||
this.asyncUpload(
|
||||
t,
|
||||
{ operationId, file, fileSize, indexOfFile, path, length },
|
||||
resolve,
|
||||
reject
|
||||
);
|
||||
i--;
|
||||
}
|
||||
});
|
||||
|
||||
await promise;
|
||||
} else {
|
||||
for (let index = 0; index < length; index++) {
|
||||
if (
|
||||
this.uploaded ||
|
||||
!this.files.some((f) => f.file === file) ||
|
||||
this.files[indexOfFile].cancel
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const res = await uploadFile(location, requestsDataArray[index]);
|
||||
const resolve = (res) => Promise.resolve(res);
|
||||
const reject = (err) => Promise.reject(err);
|
||||
|
||||
this.checkChunkUpload(
|
||||
t,
|
||||
res,
|
||||
fileSize,
|
||||
index,
|
||||
indexOfFile,
|
||||
path,
|
||||
length,
|
||||
resolve,
|
||||
reject
|
||||
);
|
||||
|
||||
//console.log(`Uploaded chunk ${index}/${length}`, res);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1048,13 +1222,15 @@ class UploadDataStore {
|
||||
// console.log("IS PARALLEL");
|
||||
const notUploadedFiles = this.files.filter((f) => !f.inAction);
|
||||
|
||||
const { chunkUploadCount } = this.settingsStore;
|
||||
|
||||
const countFiles =
|
||||
notUploadedFiles.length >= UPLOAD_LIMIT_AT_ONCE
|
||||
? UPLOAD_LIMIT_AT_ONCE
|
||||
notUploadedFiles.length >= chunkUploadCount
|
||||
? chunkUploadCount
|
||||
: notUploadedFiles.length;
|
||||
|
||||
for (let i = 0; i < countFiles; i++) {
|
||||
if (this.currentUploadNumber <= UPLOAD_LIMIT_AT_ONCE) {
|
||||
if (this.currentUploadNumber <= chunkUploadCount) {
|
||||
const fileIndex = this.files.findIndex(
|
||||
(f) => f.uniqueId === notUploadedFiles[i].uniqueId
|
||||
);
|
||||
@ -1082,6 +1258,7 @@ class UploadDataStore {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
this.asyncUploadObj = {};
|
||||
});
|
||||
const uploadedFiles = this.files.filter((x) => x.action === "uploaded");
|
||||
const totalErrorsCount = sumBy(uploadedFiles, (f) => (f.error ? 1 : 0));
|
||||
@ -1103,6 +1280,7 @@ class UploadDataStore {
|
||||
if (!this.uploaded && this.files.length === 0) {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
this.asyncUploadObj = {};
|
||||
//setUploadData(uploadData);
|
||||
return;
|
||||
}
|
||||
@ -1145,6 +1323,7 @@ class UploadDataStore {
|
||||
.then((res) => {
|
||||
const location = res.data.location;
|
||||
const path = res.data.path;
|
||||
const operationId = res.data.id;
|
||||
|
||||
const requestsDataArray = [];
|
||||
|
||||
@ -1158,37 +1337,56 @@ class UploadDataStore {
|
||||
chunk++;
|
||||
}
|
||||
|
||||
return { location, requestsDataArray, fileSize, path };
|
||||
})
|
||||
.then(({ location, requestsDataArray, fileSize, path }) => {
|
||||
const fileIndex = this.uploadedFilesHistory.findIndex(
|
||||
(f) => f.uniqueId === this.files[indexOfFile].uniqueId
|
||||
);
|
||||
if (fileIndex > -1)
|
||||
this.uploadedFilesHistory[fileIndex].percent = chunks < 2 ? 50 : 0;
|
||||
|
||||
if (!this.isParallel) {
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
visible: true,
|
||||
percent: this.percent,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: chunks < 2 ? 50 : 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return this.uploadFileChunks(
|
||||
return {
|
||||
location,
|
||||
requestsDataArray,
|
||||
fileSize,
|
||||
indexOfFile,
|
||||
file,
|
||||
path,
|
||||
t
|
||||
);
|
||||
operationId,
|
||||
toFolderId,
|
||||
};
|
||||
})
|
||||
.then(
|
||||
({
|
||||
location,
|
||||
requestsDataArray,
|
||||
fileSize,
|
||||
path,
|
||||
t,
|
||||
operationId,
|
||||
toFolderId,
|
||||
}) => {
|
||||
const fileIndex = this.uploadedFilesHistory.findIndex(
|
||||
(f) => f.uniqueId === this.files[indexOfFile].uniqueId
|
||||
);
|
||||
if (fileIndex > -1)
|
||||
this.uploadedFilesHistory[fileIndex].percent = chunks < 2 ? 50 : 0;
|
||||
|
||||
if (!this.isParallel) {
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
visible: true,
|
||||
percent: this.percent,
|
||||
loadingFile: {
|
||||
uniqueId: this.files[indexOfFile].uniqueId,
|
||||
percent: chunks < 2 ? 50 : 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return this.uploadFileChunks(
|
||||
location,
|
||||
requestsDataArray,
|
||||
fileSize,
|
||||
indexOfFile,
|
||||
file,
|
||||
path,
|
||||
t,
|
||||
operationId,
|
||||
toFolderId
|
||||
);
|
||||
}
|
||||
)
|
||||
.catch((error) => {
|
||||
if (this.files[indexOfFile] === undefined) {
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarData({
|
||||
@ -1254,6 +1452,7 @@ class UploadDataStore {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
this.isParallel = true;
|
||||
this.asyncUploadObj = {};
|
||||
});
|
||||
const uploadedFiles = this.files.filter(
|
||||
(x) => x.action === "uploaded"
|
||||
@ -1287,6 +1486,7 @@ class UploadDataStore {
|
||||
this.isParallel = true;
|
||||
this.converted = true;
|
||||
this.uploadedFilesSize = 0;
|
||||
this.asyncUploadObj = {};
|
||||
|
||||
for (let item of this.tempFiles) {
|
||||
const { uploadFiles, folderId, t } = item;
|
||||
@ -1314,6 +1514,7 @@ class UploadDataStore {
|
||||
this.isParallel = true;
|
||||
this.converted = true;
|
||||
this.uploadedFilesSize = 0;
|
||||
this.asyncUploadObj = {};
|
||||
|
||||
const uploadData = {
|
||||
filesSize: 0,
|
||||
|
@ -136,7 +136,8 @@ class UsersStore {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
await this.getUsersList(filter, true);
|
||||
// await this.getUsersList(filter, true); // accounts loader
|
||||
await this.getUsersList(filter); // rooms
|
||||
|
||||
if (users && !this.needResetUserSelection) {
|
||||
this.peopleStore.selectionStore.updateSelection(this.peopleList);
|
||||
|
@ -185,6 +185,7 @@ authStore.infoPanelStore.filesStore = filesStore;
|
||||
authStore.infoPanelStore.peopleStore = peopleStore;
|
||||
authStore.infoPanelStore.selectedFolderStore = selectedFolderStore;
|
||||
authStore.infoPanelStore.treeFoldersStore = treeFoldersStore;
|
||||
authStore.infoPanelStore.publicRoomStore = publicRoomStore;
|
||||
|
||||
const createEditRoomStore = new CreateEditRoomStore(
|
||||
filesStore,
|
||||
|
@ -1,31 +0,0 @@
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
const StyledAlertComponent = styled.div`
|
||||
width: 100%;
|
||||
position: relative;
|
||||
border: ${(props) => `1px solid ${props.borderColor}`};
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
${(props) => !!props.onClick && "cursor:pointer"};
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: ${(props) =>
|
||||
props.needArrowIcon ? "1fr 16px" : "1fr"};
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.alert-component_title {
|
||||
color: ${(props) => props.titleColor};
|
||||
}
|
||||
.alert-component_icons {
|
||||
margin: auto 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledAlertComponent };
|
@ -1,122 +0,0 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { commonIconsStyles } from "@docspace/shared/utils";
|
||||
|
||||
import ArrowRightIcon from "PUBLIC_DIR/images/arrow.right.react.svg";
|
||||
import CrossReactSvg from "PUBLIC_DIR/images/cross.react.svg";
|
||||
|
||||
import Loaders from "../Loaders";
|
||||
import { StyledAlertComponent } from "./StyledComponent";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
|
||||
const StyledArrowRightIcon = styled(ArrowRightIcon)`
|
||||
margin: auto 0;
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl" && "transform: scaleX(-1);"}
|
||||
path {
|
||||
fill: ${(props) => props.theme.alertComponent.iconColor};
|
||||
}
|
||||
`;
|
||||
const StyledCrossIcon = styled(CrossReactSvg)`
|
||||
position: absolute;
|
||||
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
left: 0px;
|
||||
margin-left: 8px;
|
||||
`
|
||||
: css`
|
||||
right: 0px;
|
||||
margin-right: 8px;
|
||||
`}
|
||||
margin-top: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
${commonIconsStyles}
|
||||
path {
|
||||
fill: ${(props) => props.color};
|
||||
}
|
||||
`;
|
||||
|
||||
const AlertComponent = (props) => {
|
||||
const {
|
||||
id,
|
||||
description,
|
||||
title,
|
||||
titleFontSize,
|
||||
additionalDescription,
|
||||
needArrowIcon = false,
|
||||
needCloseIcon = false,
|
||||
link,
|
||||
onLinkClick,
|
||||
linkColor,
|
||||
linkTitle,
|
||||
onAlertClick,
|
||||
onCloseClick,
|
||||
titleColor,
|
||||
borderColor,
|
||||
theme,
|
||||
} = props;
|
||||
return (
|
||||
<StyledAlertComponent
|
||||
theme={theme}
|
||||
titleColor={titleColor}
|
||||
borderColor={borderColor}
|
||||
onClick={onAlertClick}
|
||||
needArrowIcon={needArrowIcon}
|
||||
id={id}
|
||||
>
|
||||
<div className="main-content">
|
||||
<Text
|
||||
className="alert-component_title"
|
||||
fontSize={titleFontSize ?? "12px"}
|
||||
fontWeight={600}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
{additionalDescription && (
|
||||
<Text fontWeight={600}>{additionalDescription}</Text>
|
||||
)}
|
||||
<Text
|
||||
noSelect
|
||||
fontSize="12px"
|
||||
color={theme.alertComponent.descriptionColor}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
{(link || onLinkClick) && (
|
||||
<Link
|
||||
type="page"
|
||||
href={link}
|
||||
onClick={onLinkClick}
|
||||
noHover
|
||||
color={linkColor}
|
||||
>
|
||||
{linkTitle}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
{needCloseIcon && (
|
||||
<StyledCrossIcon size="extraSmall" onClick={onCloseClick} />
|
||||
)}
|
||||
{needArrowIcon && (
|
||||
<StyledArrowRightIcon className="alert-component_arrow" />
|
||||
)}
|
||||
</StyledAlertComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore } = auth;
|
||||
|
||||
const { theme } = settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
};
|
||||
})(observer(AlertComponent));
|
@ -1,20 +0,0 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Provider as MobxProvider } from "mobx-react";
|
||||
import store from "client/store";
|
||||
import Article from "./";
|
||||
|
||||
const { auth: authStore } = store;
|
||||
|
||||
const ArticleWrapper = (props) => {
|
||||
useEffect(() => {
|
||||
authStore.init();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MobxProvider {...store}>
|
||||
<Article {...props} />
|
||||
</MobxProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ArticleWrapper;
|
@ -1,367 +0,0 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import PropTypes from "prop-types";
|
||||
import { isMobile, isMobileOnly, isIOS } from "react-device-detect";
|
||||
|
||||
import SubArticleBackdrop from "./sub-components/article-backdrop";
|
||||
import SubArticleHeader from "./sub-components/article-header";
|
||||
import SubArticleMainButton from "./sub-components/article-main-button";
|
||||
import SubArticleBody from "./sub-components/article-body";
|
||||
import ArticleProfile from "./sub-components/article-profile";
|
||||
import ArticleAlerts from "./sub-components/article-alerts";
|
||||
import ArticleLiveChat from "./sub-components/article-live-chat";
|
||||
import ArticleApps from "./sub-components/article-apps";
|
||||
import ArticleDevToolsBar from "./sub-components/article-dev-tools-bar";
|
||||
import { StyledArticle } from "./styled-article";
|
||||
import HideArticleMenuButton from "./sub-components/article-hide-menu-button";
|
||||
import { Portal } from "@docspace/shared/components/portal";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import ArticleProfileLoader from "../Loaders/ArticleProfileLoader/ArticleProfileLoader";
|
||||
|
||||
const Article = ({
|
||||
showText,
|
||||
setShowText,
|
||||
articleOpen,
|
||||
toggleShowText,
|
||||
toggleArticleOpen,
|
||||
setIsMobileArticle,
|
||||
children,
|
||||
|
||||
withMainButton,
|
||||
|
||||
hideProfileBlock,
|
||||
hideAppsBlock,
|
||||
|
||||
currentColorScheme,
|
||||
setArticleOpen,
|
||||
withSendAgain,
|
||||
mainBarVisible,
|
||||
isBannerVisible,
|
||||
|
||||
isLiveChatAvailable,
|
||||
|
||||
onLogoClickAction,
|
||||
theme,
|
||||
|
||||
currentDeviceType,
|
||||
showArticleLoader,
|
||||
isAdmin,
|
||||
withCustomArticleHeader,
|
||||
hideAlerts,
|
||||
...rest
|
||||
}) => {
|
||||
const [articleHeaderContent, setArticleHeaderContent] = React.useState(null);
|
||||
const [articleMainButtonContent, setArticleMainButtonContent] =
|
||||
React.useState(null);
|
||||
const [articleBodyContent, setArticleBodyContent] = React.useState(null);
|
||||
const [correctTabletHeight, setCorrectTabletHeight] = React.useState(null);
|
||||
const [isVirtualKeyboardOpen, setIsVirtualKeyboardOpen] =
|
||||
React.useState(false);
|
||||
const updateSizeRef = React.useRef(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
window.addEventListener("popstate", onMobileBack);
|
||||
return () => window.removeEventListener("popstate", onMobileBack);
|
||||
}, [onMobileBack]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const showArticle = JSON.parse(localStorage.getItem("showArticle"));
|
||||
|
||||
if (currentDeviceType === DeviceType.mobile) {
|
||||
setShowText(true);
|
||||
setIsMobileArticle(true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentDeviceType === DeviceType.tablet) {
|
||||
setIsMobileArticle(true);
|
||||
|
||||
if (showArticle) return;
|
||||
|
||||
setShowText(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setShowText(true);
|
||||
setIsMobileArticle(false);
|
||||
}, [setShowText, setIsMobileArticle, currentDeviceType]);
|
||||
|
||||
React.useEffect(() => {
|
||||
React.Children.forEach(children, (child) => {
|
||||
const childType =
|
||||
child && child.type && (child.type.displayName || child.type.name);
|
||||
|
||||
switch (childType) {
|
||||
case Article.Header.displayName:
|
||||
setArticleHeaderContent(child);
|
||||
break;
|
||||
case Article.MainButton.displayName:
|
||||
setArticleMainButtonContent(child);
|
||||
break;
|
||||
case Article.Body.displayName:
|
||||
setArticleBodyContent(child);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}, [children]);
|
||||
|
||||
const onMobileBack = React.useCallback(() => {
|
||||
//close article
|
||||
|
||||
if (currentDeviceType !== DeviceType.mobile) return;
|
||||
setArticleOpen(false);
|
||||
}, [setArticleOpen, currentDeviceType]);
|
||||
|
||||
// TODO: make some better
|
||||
const onResize = React.useCallback(
|
||||
(e) => {
|
||||
let correctTabletHeight = window.innerHeight;
|
||||
|
||||
if (mainBarVisible) {
|
||||
const mainBar = document.getElementById("main-bar");
|
||||
|
||||
if (!mainBar.offsetHeight)
|
||||
return (updateSizeRef.current = setTimeout(() => onResize(), 0));
|
||||
|
||||
correctTabletHeight -= mainBar.offsetHeight;
|
||||
}
|
||||
|
||||
const isTouchDevice =
|
||||
"ontouchstart" in window ||
|
||||
navigator.maxTouchPoints > 0 ||
|
||||
navigator.msMaxTouchPoints > 0;
|
||||
|
||||
const path = window.location.pathname.toLowerCase();
|
||||
|
||||
if (
|
||||
isBannerVisible &&
|
||||
isMobile &&
|
||||
isTouchDevice &&
|
||||
(path.includes("rooms") || path.includes("files"))
|
||||
) {
|
||||
correctTabletHeight -= 80;
|
||||
|
||||
if (e?.target?.height) {
|
||||
const diff = window.innerHeight - e.target.height;
|
||||
setIsVirtualKeyboardOpen(true);
|
||||
correctTabletHeight -= diff;
|
||||
} else {
|
||||
setIsVirtualKeyboardOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
setCorrectTabletHeight(correctTabletHeight);
|
||||
},
|
||||
[mainBarVisible, isBannerVisible]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
onResize();
|
||||
window.addEventListener("resize", onResize);
|
||||
if (isMobile && !isMobileOnly && isIOS) {
|
||||
window?.visualViewport?.addEventListener("resize", onResize);
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
window?.visualViewport?.removeEventListener("resize", onResize);
|
||||
clearTimeout(updateSizeRef.current);
|
||||
};
|
||||
}, [onResize]);
|
||||
|
||||
const withDevTools =
|
||||
!window.location.pathname.includes("portal-settings") &&
|
||||
!window.location.pathname.includes("management") &&
|
||||
isAdmin;
|
||||
|
||||
const articleComponent = (
|
||||
<>
|
||||
<StyledArticle
|
||||
id={"article-container"}
|
||||
showText={showText}
|
||||
articleOpen={articleOpen}
|
||||
$withMainButton={withMainButton}
|
||||
correctTabletHeight={correctTabletHeight}
|
||||
isMobile={currentDeviceType === DeviceType.mobile}
|
||||
{...rest}
|
||||
>
|
||||
<SubArticleHeader
|
||||
showText={showText}
|
||||
onLogoClickAction={onLogoClickAction}
|
||||
currentDeviceType={currentDeviceType}
|
||||
withCustomArticleHeader={withCustomArticleHeader}
|
||||
>
|
||||
{articleHeaderContent ? articleHeaderContent.props.children : null}
|
||||
</SubArticleHeader>
|
||||
|
||||
{articleMainButtonContent &&
|
||||
withMainButton &&
|
||||
currentDeviceType !== DeviceType.mobile ? (
|
||||
<SubArticleMainButton showText={showText}>
|
||||
{articleMainButtonContent.props.children}
|
||||
</SubArticleMainButton>
|
||||
) : null}
|
||||
|
||||
<SubArticleBody showText={showText}>
|
||||
{articleBodyContent ? articleBodyContent.props.children : null}
|
||||
{!showArticleLoader && (
|
||||
<>
|
||||
{!hideAlerts && <ArticleAlerts />}
|
||||
{withDevTools && (
|
||||
<ArticleDevToolsBar
|
||||
articleOpen={articleOpen}
|
||||
currentDeviceType={currentDeviceType}
|
||||
toggleArticleOpen={toggleArticleOpen}
|
||||
showText={showText}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
{!hideAppsBlock && (
|
||||
<ArticleApps
|
||||
withDevTools={withDevTools}
|
||||
showText={showText}
|
||||
theme={theme}
|
||||
/>
|
||||
)}
|
||||
{!isMobile && isLiveChatAvailable && (
|
||||
<ArticleLiveChat
|
||||
currentColorScheme={currentColorScheme}
|
||||
withMainButton={withMainButton && !!articleMainButtonContent}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</SubArticleBody>
|
||||
{!showArticleLoader && (
|
||||
<HideArticleMenuButton
|
||||
showText={showText}
|
||||
toggleShowText={toggleShowText}
|
||||
currentColorScheme={currentColorScheme}
|
||||
hideProfileBlock={hideProfileBlock}
|
||||
isVirtualKeyboardOpen={isVirtualKeyboardOpen}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!hideProfileBlock && currentDeviceType !== DeviceType.mobile && (
|
||||
<>
|
||||
{showArticleLoader ? (
|
||||
<ArticleProfileLoader />
|
||||
) : (
|
||||
<ArticleProfile
|
||||
showText={showText}
|
||||
currentDeviceType={currentDeviceType}
|
||||
isVirtualKeyboardOpen={isVirtualKeyboardOpen}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledArticle>
|
||||
{articleOpen && currentDeviceType === DeviceType.mobile && (
|
||||
<>
|
||||
<SubArticleBackdrop onClick={toggleArticleOpen} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{articleMainButtonContent && currentDeviceType === DeviceType.mobile ? (
|
||||
<SubArticleMainButton showText={showText}>
|
||||
{articleMainButtonContent.props.children}
|
||||
</SubArticleMainButton>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
||||
const renderPortalArticle = () => {
|
||||
const rootElement = document.getElementById("root");
|
||||
|
||||
return (
|
||||
<Portal
|
||||
element={articleComponent}
|
||||
appendTo={rootElement}
|
||||
visible={true}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// console.log("Article render", {
|
||||
// articleMainButton: !!articleMainButtonContent,
|
||||
// withMainButton,
|
||||
// });
|
||||
|
||||
return currentDeviceType === DeviceType.mobile
|
||||
? renderPortalArticle()
|
||||
: articleComponent;
|
||||
};
|
||||
|
||||
Article.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
setShowText: PropTypes.func,
|
||||
articleOpen: PropTypes.bool,
|
||||
toggleArticleOpen: PropTypes.func,
|
||||
setIsMobileArticle: PropTypes.func,
|
||||
children: PropTypes.any,
|
||||
hideProfileBlock: PropTypes.bool,
|
||||
};
|
||||
|
||||
Article.Header = () => {
|
||||
return null;
|
||||
};
|
||||
Article.Header.displayName = "Header";
|
||||
|
||||
Article.MainButton = () => {
|
||||
return null;
|
||||
};
|
||||
Article.MainButton.displayName = "MainButton";
|
||||
|
||||
Article.Body = () => {
|
||||
return null;
|
||||
};
|
||||
Article.Body.displayName = "Body";
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore, userStore, isLiveChatAvailable, bannerStore } = auth;
|
||||
|
||||
const { withSendAgain, user } = userStore;
|
||||
|
||||
const { isBannerVisible } = bannerStore;
|
||||
|
||||
const isAdmin = user?.isAdmin;
|
||||
|
||||
const {
|
||||
showText,
|
||||
setShowText,
|
||||
articleOpen,
|
||||
setIsMobileArticle,
|
||||
toggleShowText,
|
||||
toggleArticleOpen,
|
||||
currentColorScheme,
|
||||
setArticleOpen,
|
||||
mainBarVisible,
|
||||
theme,
|
||||
currentDeviceType,
|
||||
} = settingsStore;
|
||||
|
||||
return {
|
||||
showText,
|
||||
setShowText,
|
||||
articleOpen,
|
||||
setIsMobileArticle,
|
||||
toggleShowText,
|
||||
toggleArticleOpen,
|
||||
|
||||
currentColorScheme,
|
||||
setArticleOpen,
|
||||
withSendAgain,
|
||||
mainBarVisible,
|
||||
isBannerVisible,
|
||||
|
||||
isLiveChatAvailable,
|
||||
|
||||
theme,
|
||||
currentDeviceType,
|
||||
|
||||
isAdmin,
|
||||
};
|
||||
})(observer(Article));
|
@ -1,113 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import ArticleTeamTrainingAlert from "./article-team-training";
|
||||
import ArticleSubmitToFormGalleryAlert from "./article-submit-to-form-gallery";
|
||||
import ArticlePaymentAlert from "./article-payment-alert";
|
||||
import ArticleEnterpriseAlert from "./article-enterprise-alert";
|
||||
import { StyledArticleAlertsComponent } from "../styled-article";
|
||||
import { ARTICLE_ALERTS } from "@docspace/client/src/helpers/constants";
|
||||
|
||||
const ArticleAlerts = ({
|
||||
articleAlertsData,
|
||||
incrementIndexOfArticleAlertsData,
|
||||
|
||||
showText,
|
||||
isNonProfit,
|
||||
isGracePeriod,
|
||||
isFreeTariff,
|
||||
isPaymentPageAvailable,
|
||||
isTeamTrainingAlertAvailable,
|
||||
isSubmitToGalleryAlertAvailable,
|
||||
isLicenseExpiring,
|
||||
isLicenseDateExpired,
|
||||
isEnterprise,
|
||||
isTrial,
|
||||
standalone,
|
||||
}) => {
|
||||
const currentAlert = articleAlertsData.current;
|
||||
const availableAlerts = articleAlertsData.available;
|
||||
|
||||
useEffect(() => {
|
||||
incrementIndexOfArticleAlertsData();
|
||||
}, []);
|
||||
|
||||
const paymentsAlertsComponent = () => {
|
||||
if (!standalone) {
|
||||
return (
|
||||
isPaymentPageAvailable &&
|
||||
!isNonProfit &&
|
||||
(isFreeTariff || isGracePeriod) &&
|
||||
showText && <ArticlePaymentAlert isFreeTariff={isFreeTariff} />
|
||||
);
|
||||
}
|
||||
|
||||
const isVisibleStandaloneAlert =
|
||||
isTrial || isLicenseExpiring || isLicenseDateExpired;
|
||||
|
||||
return (
|
||||
isPaymentPageAvailable &&
|
||||
isEnterprise &&
|
||||
isVisibleStandaloneAlert &&
|
||||
showText && <ArticleEnterpriseAlert />
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledArticleAlertsComponent>
|
||||
{paymentsAlertsComponent()}
|
||||
|
||||
{isTeamTrainingAlertAvailable &&
|
||||
showText &&
|
||||
availableAlerts.includes(ARTICLE_ALERTS.TeamTraining) &&
|
||||
currentAlert === ARTICLE_ALERTS.TeamTraining && (
|
||||
<ArticleTeamTrainingAlert />
|
||||
)}
|
||||
|
||||
{isSubmitToGalleryAlertAvailable &&
|
||||
showText &&
|
||||
availableAlerts.includes(ARTICLE_ALERTS.SubmitToFormGallery) &&
|
||||
currentAlert === ARTICLE_ALERTS.SubmitToFormGallery && (
|
||||
<ArticleSubmitToFormGalleryAlert />
|
||||
)}
|
||||
</StyledArticleAlertsComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const {
|
||||
currentQuotaStore,
|
||||
settingsStore,
|
||||
isPaymentPageAvailable,
|
||||
isTeamTrainingAlertAvailable,
|
||||
isSubmitToGalleryAlertAvailable,
|
||||
currentTariffStatusStore,
|
||||
isEnterprise,
|
||||
} = auth;
|
||||
const { isFreeTariff, isNonProfit, isTrial } = currentQuotaStore;
|
||||
const { isGracePeriod, isLicenseExpiring, isLicenseDateExpired } =
|
||||
currentTariffStatusStore;
|
||||
const {
|
||||
showText,
|
||||
standalone,
|
||||
articleAlertsData,
|
||||
incrementIndexOfArticleAlertsData,
|
||||
} = settingsStore;
|
||||
|
||||
return {
|
||||
articleAlertsData,
|
||||
incrementIndexOfArticleAlertsData,
|
||||
isEnterprise,
|
||||
showText,
|
||||
isNonProfit,
|
||||
isGracePeriod,
|
||||
isFreeTariff,
|
||||
isPaymentPageAvailable,
|
||||
isTeamTrainingAlertAvailable,
|
||||
isSubmitToGalleryAlertAvailable,
|
||||
isLicenseExpiring,
|
||||
isLicenseDateExpired,
|
||||
isTrial,
|
||||
standalone,
|
||||
};
|
||||
})(observer(ArticleAlerts));
|
@ -1,115 +0,0 @@
|
||||
import WindowsReactSvgUrl from "PUBLIC_DIR/images/windows.react.svg?url";
|
||||
import MacOSReactSvgUrl from "PUBLIC_DIR/images/macOS.react.svg?url";
|
||||
import LinuxReactSvgUrl from "PUBLIC_DIR/images/linux.react.svg?url";
|
||||
import AndroidReactSvgUrl from "PUBLIC_DIR/images/android.react.svg?url";
|
||||
import IOSReactSvgUrl from "PUBLIC_DIR/images/iOS.react.svg?url";
|
||||
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { tablet, mobile } from "@docspace/shared/utils";
|
||||
|
||||
const StyledArticleApps = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
margin-top: ${(props) => (props.withDevTools ? "0" : "auto")};
|
||||
margin-bottom: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
${(props) =>
|
||||
props.showText &&
|
||||
css`
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl"
|
||||
? `margin-right: 8px;`
|
||||
: `margin-left: 8px;`}
|
||||
`}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
margin-top: ${(props) => (props.withDevTools ? "16px" : "32px")};
|
||||
}
|
||||
|
||||
.download-app-text {
|
||||
color: ${(props) => props.theme.filesArticleBody.downloadAppList.textColor};
|
||||
}
|
||||
|
||||
.download-app-list {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledArticleApps.defaultProps = { theme: Base };
|
||||
|
||||
const ArticleApps = React.memo(({ theme, showText, withDevTools }) => {
|
||||
const { t } = useTranslation(["Translations"]);
|
||||
|
||||
const desktopLink = "https://www.onlyoffice.com/desktop.aspx";
|
||||
const androidLink = "https://www.onlyoffice.com/office-for-android.aspx";
|
||||
const iosLink = "https://www.onlyoffice.com/office-for-ios.aspx";
|
||||
|
||||
if (!showText) return <></>;
|
||||
|
||||
return (
|
||||
<StyledArticleApps showText={showText} withDevTools={withDevTools}>
|
||||
<Text className="download-app-text" fontSize="14px" noSelect={true}>
|
||||
{t("Translations:DownloadApps")}
|
||||
</Text>
|
||||
<div className="download-app-list">
|
||||
<IconButton
|
||||
onClick={() => window.open(desktopLink)}
|
||||
iconName={WindowsReactSvgUrl}
|
||||
size="32"
|
||||
isFill={true}
|
||||
hoverColor={theme.filesArticleBody.downloadAppList.winHoverColor}
|
||||
title={t("Translations:MobileWin")}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={() => window.open(desktopLink)}
|
||||
iconName={MacOSReactSvgUrl}
|
||||
size="32"
|
||||
isFill={true}
|
||||
hoverColor={theme.filesArticleBody.downloadAppList.macHoverColor}
|
||||
title={t("Translations:MobileMac")}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={() => window.open(desktopLink)}
|
||||
iconName={LinuxReactSvgUrl}
|
||||
size="32"
|
||||
isFill={true}
|
||||
hoverColor={theme.filesArticleBody.downloadAppList.linuxHoverColor}
|
||||
title={t("Translations:MobileLinux")}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={() => window.open(androidLink)}
|
||||
iconName={AndroidReactSvgUrl}
|
||||
size="32"
|
||||
isFill={true}
|
||||
hoverColor={theme.filesArticleBody.downloadAppList.androidHoverColor}
|
||||
title={t("Translations:MobileAndroid")}
|
||||
/>
|
||||
<IconButton
|
||||
onClick={() => window.open(iosLink)}
|
||||
iconName={IOSReactSvgUrl}
|
||||
size="32"
|
||||
isFill={true}
|
||||
hoverColor={theme.filesArticleBody.downloadAppList.iosHoverColor}
|
||||
title={t("Translations:MobileIos")}
|
||||
/>
|
||||
</div>
|
||||
</StyledArticleApps>
|
||||
);
|
||||
});
|
||||
|
||||
ArticleApps.defaultProps = { theme: Base };
|
||||
|
||||
export default ArticleApps;
|
@ -1,29 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Backdrop } from "@docspace/shared/components/backdrop";
|
||||
|
||||
import { StyledControlContainer, StyledCrossIcon } from "../styled-article";
|
||||
|
||||
const ArticleBackdrop = ({ onClick, ...rest }) => {
|
||||
return (
|
||||
<>
|
||||
<StyledControlContainer onClick={onClick} {...rest}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
<Backdrop
|
||||
onClick={onClick}
|
||||
visible={true}
|
||||
zIndex={210}
|
||||
withBackground={true}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ArticleBackdrop.propTypes = {
|
||||
showText: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default React.memo(ArticleBackdrop);
|
@ -1,86 +0,0 @@
|
||||
import DeveloperReactSvgUrl from "PUBLIC_DIR/images/catalog.developer.react.svg?url";
|
||||
import ArrowReactSvgUrl from "PUBLIC_DIR/images/arrow.right.react.svg?url";
|
||||
import React from "react";
|
||||
|
||||
import styled from "styled-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { mobile } from "@docspace/shared/utils";
|
||||
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
margin-top: auto;
|
||||
margin-bottom: 16px;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
border: ${(props) => props.theme.filesArticleBody.devTools.border};
|
||||
border-radius: 6px;
|
||||
|
||||
@media ${mobile} {
|
||||
bottom: 0px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
height: 16px;
|
||||
margin-inline-start: auto;
|
||||
|
||||
svg {
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl" && "transform: scaleX(-1);"}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
color: ${(props) => props.theme.filesArticleBody.devTools.color};
|
||||
}
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.filesArticleBody.devTools.color};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ArticleDevToolsBar = ({
|
||||
showText,
|
||||
articleOpen,
|
||||
currentDeviceType,
|
||||
toggleArticleOpen,
|
||||
}) => {
|
||||
const { t } = useTranslation(["Settings"]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onClick = () => {
|
||||
navigate("/portal-settings/developer-tools");
|
||||
articleOpen &&
|
||||
currentDeviceType === DeviceType.mobile &&
|
||||
toggleArticleOpen();
|
||||
};
|
||||
|
||||
if (!showText) return <></>;
|
||||
|
||||
return (
|
||||
<StyledWrapper onClick={onClick}>
|
||||
<ReactSVG src={DeveloperReactSvgUrl} className="icon" />
|
||||
<Text fontWeight={600} fontSize="12px" className="label">
|
||||
{t("DeveloperTools")}
|
||||
</Text>
|
||||
<ReactSVG src={ArrowReactSvgUrl} className="arrow" />
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ArticleDevToolsBar;
|
@ -1,163 +0,0 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { desktop, mobile, tablet } from "@docspace/shared/utils";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
import ArticleHideMenuReactSvgUrl from "PUBLIC_DIR/images/article-hide-menu.react.svg?url";
|
||||
import ArticleShowMenuReactSvgUrl from "PUBLIC_DIR/images/article-show-menu.react.svg?url";
|
||||
|
||||
const StyledHideArticleMenuButton = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: ${(props) => (props.isVirtualKeyboardOpen ? "absolute" : "fixed")};
|
||||
height: 44px;
|
||||
z-index: 209;
|
||||
bottom: ${(props) => (props.hideProfileBlock ? "16px" : "89px")};
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: 0;
|
||||
`
|
||||
: css`
|
||||
left: 0;
|
||||
`}
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
|
||||
min-width: ${({ showText }) => (showText ? "243px" : "60px")};
|
||||
max-width: ${({ showText }) => (showText ? "243px" : "60px")};
|
||||
|
||||
@media ${desktop} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.article-hide-menu-container {
|
||||
align-items: center;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 16px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 16px;
|
||||
`}
|
||||
.article-hide-menu-text {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 8px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 8px;
|
||||
`}
|
||||
color: ${({ currentColorScheme }) => currentColorScheme?.main?.accent};
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
display: ${({ showText }) => (showText ? "flex" : "none")};
|
||||
}
|
||||
}
|
||||
|
||||
.article-show-menu-container {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
@media ${tablet} {
|
||||
display: ${({ showText }) => (showText ? "none" : "flex")};
|
||||
}
|
||||
}
|
||||
|
||||
.article-hide-menu-icon_svg,
|
||||
.article-show-menu-icon_svg {
|
||||
height: 20px;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
transform: scaleX(-1);
|
||||
`}
|
||||
}
|
||||
|
||||
.article-hide-menu-icon_svg {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
transform: scaleX(-1);
|
||||
`}
|
||||
svg {
|
||||
path {
|
||||
fill: ${({ currentColorScheme }) => currentColorScheme?.main?.accent};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.article-show-menu-icon_svg {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.article.catalogShowText};
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledHideArticleMenuButton.defaultProps = { theme: Base };
|
||||
|
||||
const HideArticleMenuButton = ({
|
||||
showText,
|
||||
toggleShowText,
|
||||
currentColorScheme,
|
||||
isVirtualKeyboardOpen,
|
||||
hideProfileBlock,
|
||||
}) => {
|
||||
const { t } = useTranslation("Common");
|
||||
|
||||
return (
|
||||
<StyledHideArticleMenuButton
|
||||
showText={showText}
|
||||
onClick={toggleShowText}
|
||||
currentColorScheme={currentColorScheme}
|
||||
isVirtualKeyboardOpen={isVirtualKeyboardOpen}
|
||||
hideProfileBlock={hideProfileBlock}
|
||||
>
|
||||
{showText ? (
|
||||
<div
|
||||
className="article-hide-menu-container"
|
||||
id="document_catalog-hide-menu"
|
||||
>
|
||||
<ReactSVG
|
||||
className="article-hide-menu-icon_svg"
|
||||
src={ArticleHideMenuReactSvgUrl}
|
||||
/>
|
||||
<Text
|
||||
className="article-hide-menu-text"
|
||||
fontWeight={600}
|
||||
fontSize="12px"
|
||||
noSelect
|
||||
truncate
|
||||
>
|
||||
{t("Common:HideArticleMenu")}
|
||||
</Text>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="article-show-menu-container"
|
||||
id="document_catalog-show-menu"
|
||||
>
|
||||
<ReactSVG
|
||||
className="article-show-menu-icon_svg"
|
||||
src={ArticleShowMenuReactSvgUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</StyledHideArticleMenuButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default HideArticleMenuButton;
|
@ -1,49 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import AlertComponent from "../../AlertComponent";
|
||||
import { RectangleSkeleton } from "@docspace/shared/skeletons";
|
||||
import { ARTICLE_ALERTS } from "@docspace/client/src/helpers/constants";
|
||||
|
||||
const ArticleTeamTrainingAlert = ({
|
||||
theme,
|
||||
bookTrainingEmail,
|
||||
removeAlertFromArticleAlertsData,
|
||||
}) => {
|
||||
const { t, ready } = useTranslation("Common");
|
||||
const isShowLoader = !ready;
|
||||
|
||||
const onClose = () =>
|
||||
removeAlertFromArticleAlertsData(ARTICLE_ALERTS.TeamTraining);
|
||||
|
||||
return isShowLoader ? (
|
||||
<RectangleSkeleton width="210px" height="88px" />
|
||||
) : (
|
||||
<AlertComponent
|
||||
titleColor={theme.catalog.teamTrainingAlert.titleColor}
|
||||
linkColor={theme.catalog.teamTrainingAlert.linkColor}
|
||||
borderColor={theme.catalog.teamTrainingAlert.borderColor}
|
||||
title={t("Common:UseLikePro")}
|
||||
description={t("Common:BookTeamTraining")}
|
||||
link={`mailto:${bookTrainingEmail}`}
|
||||
linkTitle={t("Common:BookNow")}
|
||||
onCloseClick={onClose}
|
||||
needCloseIcon
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore } = auth;
|
||||
|
||||
const { theme, bookTrainingEmail, removeAlertFromArticleAlertsData } =
|
||||
settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
bookTrainingEmail,
|
||||
removeAlertFromArticleAlertsData,
|
||||
};
|
||||
})(observer(ArticleTeamTrainingAlert));
|
@ -1,42 +0,0 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import {
|
||||
withKnobs,
|
||||
boolean,
|
||||
text,
|
||||
color,
|
||||
number,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import Section from "../../../../.storybook/decorators/section";
|
||||
|
||||
import Loaders from "..";
|
||||
import { LOADER_STYLE } from "@docspace/shared/constants";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
|
||||
storiesOf("Components|Loaders", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("main button loader", () => (
|
||||
<Section>
|
||||
<h1>Main Button Loader</h1>
|
||||
<Loaders.MainButton
|
||||
title={text("title", LOADER_STYLE.title)}
|
||||
width={text("width", "100%")}
|
||||
height={text("height", "32px")}
|
||||
borderRadius={text("border radius", "3")}
|
||||
backgroundColor={color("backgroundColor", LOADER_STYLE.backgroundColor)}
|
||||
foregroundColor={color("foregroundColor", LOADER_STYLE.foregroundColor)}
|
||||
backgroundOpacity={number(
|
||||
"backgroundOpacity",
|
||||
LOADER_STYLE.backgroundOpacity
|
||||
)}
|
||||
foregroundOpacity={number(
|
||||
"foregroundOpacity",
|
||||
LOADER_STYLE.foregroundOpacity
|
||||
)}
|
||||
speed={number("speed", LOADER_STYLE.speed)}
|
||||
animate={boolean("animate", LOADER_STYLE.animate)}
|
||||
/>
|
||||
</Section>
|
||||
));
|
@ -1,28 +0,0 @@
|
||||
# Main Button Loader
|
||||
|
||||
Component that displays main button loader
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Loaders.ArticleButton />
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------------- | :------: | :------: | :----: | :-------: | ------------------------------------------------ |
|
||||
| `title` | `string` | - | - | `` | It's used to describe what element it is. |
|
||||
| `width` | `string` | - | - | `100%` | Sets the width |
|
||||
| `height` | `string` | - | - | `32` | Sets the height |
|
||||
| `borderRadius` | `string` | - | - | `3` | Sets the corners rounding |
|
||||
| `backgroundColor` | `string` | - | - | `#000000` | Used as background of animation |
|
||||
| `foregroundColor` | `string` | - | - | `#000000` | Used as the foreground of animation |
|
||||
| `backgroundOpacity` | `number` | - | - | 0.2 | Background opacity (0 = transparent, 1 = opaque) |
|
||||
| `foregroundOpacity` | `number` | - | - | 0.15 | Animation opacity (0 = transparent, 1 = opaque) |
|
||||
| `speed` | `number` | - | - | 2 | Animation speed in seconds |
|
||||
| `animate` | `bool` | - | - | true | Opt-out of animations |
|
@ -1 +0,0 @@
|
||||
export default from "./ArticleButtonLoader";
|
@ -1 +0,0 @@
|
||||
export default from "./ArticleFolderLoader";
|
@ -1,44 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import {
|
||||
StyledContainer,
|
||||
StyledRectangleLoader,
|
||||
} from "./StyledArticleGroupsLoader";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
const ArticleGroupsLoader = ({ id, className, style, showText, ...rest }) => {
|
||||
return (
|
||||
<StyledContainer
|
||||
id={id}
|
||||
className={className}
|
||||
style={style}
|
||||
showText={showText}
|
||||
>
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
<StyledRectangleLoader {...rest} />
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
ArticleGroupsLoader.propTypes = {
|
||||
id: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
showText: PropTypes.bool,
|
||||
};
|
||||
|
||||
ArticleGroupsLoader.defaultProps = {
|
||||
id: undefined,
|
||||
className: undefined,
|
||||
style: undefined,
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => ({
|
||||
showText: auth.settingsStore.showText,
|
||||
}))(observer(ArticleGroupsLoader));
|
@ -1 +0,0 @@
|
||||
export default from "./ArticleGroupsLoader";
|
@ -1,42 +0,0 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import {
|
||||
withKnobs,
|
||||
boolean,
|
||||
text,
|
||||
color,
|
||||
number,
|
||||
} from "@storybook/addon-knobs/react";
|
||||
import Section from "../../../../.storybook/decorators/section";
|
||||
|
||||
import Loaders from "..";
|
||||
import { LOADER_STYLE } from "@docspace/shared/constants";
|
||||
import withReadme from "storybook-readme/with-readme";
|
||||
import Readme from "./README.md";
|
||||
|
||||
storiesOf("Components|Loaders", module)
|
||||
.addDecorator(withKnobs)
|
||||
.addDecorator(withReadme(Readme))
|
||||
.add("article header loader", () => (
|
||||
<Section>
|
||||
<h1>Article Header Loader</h1>
|
||||
<Loaders.ArticleHeader
|
||||
title={text("title", LOADER_STYLE.title)}
|
||||
width={text("width", "100%")}
|
||||
height={text("height", "32px")}
|
||||
borderRadius={text("border radius", "3")}
|
||||
backgroundColor={color("backgroundColor", LOADER_STYLE.backgroundColor)}
|
||||
foregroundColor={color("foregroundColor", LOADER_STYLE.foregroundColor)}
|
||||
backgroundOpacity={number(
|
||||
"backgroundOpacity",
|
||||
LOADER_STYLE.backgroundOpacity
|
||||
)}
|
||||
foregroundOpacity={number(
|
||||
"foregroundOpacity",
|
||||
LOADER_STYLE.foregroundOpacity
|
||||
)}
|
||||
speed={number("speed", LOADER_STYLE.speed)}
|
||||
animate={boolean("animate", LOADER_STYLE.animate)}
|
||||
/>
|
||||
</Section>
|
||||
));
|
@ -1,28 +0,0 @@
|
||||
# Article Header Loader
|
||||
|
||||
Component that displays article header loader
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Loaders.ArticleHeader />
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------------- | :------: | :------: | :----: | :-------: | ------------------------------------------------ |
|
||||
| `title` | `string` | - | - | `` | It's used to describe what element it is. |
|
||||
| `width` | `string` | - | - | `100%` | Sets the width |
|
||||
| `height` | `string` | - | - | `32` | Sets the height |
|
||||
| `borderRadius` | `string` | - | - | `3` | Sets the corners rounding |
|
||||
| `backgroundColor` | `string` | - | - | `#000000` | Used as background of animation |
|
||||
| `foregroundColor` | `string` | - | - | `#000000` | Used as the foreground of animation |
|
||||
| `backgroundOpacity` | `number` | - | - | 0.2 | Background opacity (0 = transparent, 1 = opaque) |
|
||||
| `foregroundOpacity` | `number` | - | - | 0.15 | Animation opacity (0 = transparent, 1 = opaque) |
|
||||
| `speed` | `number` | - | - | 2 | Animation speed in seconds |
|
||||
| `animate` | `bool` | - | - | true | Opt-out of animations |
|
@ -1 +0,0 @@
|
||||
export default from "./ArticleHeaderLoader";
|
@ -1,71 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { StyledContainer, StyledBlock } from "./StyledArticleProfileLoader";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { RectangleSkeleton } from "@docspace/shared/skeletons";
|
||||
|
||||
const ArticleProfileLoader = ({
|
||||
id,
|
||||
className,
|
||||
style,
|
||||
showText,
|
||||
isVisitor,
|
||||
...rest
|
||||
}) => {
|
||||
return (
|
||||
<StyledContainer
|
||||
id={id}
|
||||
className={className}
|
||||
style={style}
|
||||
showText={showText}
|
||||
>
|
||||
<StyledBlock showText={showText}>
|
||||
{showText ? (
|
||||
<>
|
||||
<RectangleSkeleton
|
||||
width={"40px"}
|
||||
height={"40px"}
|
||||
borderRadius={"50%"}
|
||||
/>
|
||||
<RectangleSkeleton
|
||||
width={"131px"}
|
||||
height={"18px"}
|
||||
className={"title"}
|
||||
/>
|
||||
<RectangleSkeleton
|
||||
width={"16px"}
|
||||
height={"16px"}
|
||||
className={"option-button"}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<RectangleSkeleton
|
||||
width={"32px"}
|
||||
height={"32px"}
|
||||
borderRadius={"50%"}
|
||||
/>
|
||||
)}
|
||||
</StyledBlock>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
ArticleProfileLoader.propTypes = {
|
||||
id: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
showText: PropTypes.bool,
|
||||
};
|
||||
|
||||
ArticleProfileLoader.defaultProps = {
|
||||
id: undefined,
|
||||
className: undefined,
|
||||
style: undefined,
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
return {
|
||||
showText: auth.settingsStore.showText,
|
||||
isVisitor: auth.userStore.user.isVisitor,
|
||||
};
|
||||
})(observer(ArticleProfileLoader));
|
@ -1 +0,0 @@
|
||||
export default from "./ArticleProfileLoader";
|
@ -1,28 +0,0 @@
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import Section from "../../../.storybook/decorators/section";
|
||||
|
||||
import Loaders from ".";
|
||||
|
||||
storiesOf("Components|TTT", module)
|
||||
.addParameters({ options: { showAddonPanel: false } })
|
||||
.add("all", () => (
|
||||
<Section>
|
||||
<h1>Base loader</h1>
|
||||
|
||||
<h1>Article Header Loader</h1>
|
||||
<Loaders.ArticleHeader />
|
||||
|
||||
<h1>Filter loader</h1>
|
||||
<Loaders.Filter />
|
||||
|
||||
<h1>Section Header loader</h1>
|
||||
<Loaders.SectionHeader />
|
||||
|
||||
<h1>Tree Folders loader</h1>
|
||||
<Loaders.TreeFolders />
|
||||
|
||||
<h1>Main Button loader</h1>
|
||||
<Loaders.MainButton />
|
||||
</Section>
|
||||
));
|
@ -1,10 +1,6 @@
|
||||
import Header from "./HeaderLoader";
|
||||
import SectionHeader from "./SectionHeaderLoader";
|
||||
import ArticleHeader from "./ArticleHeaderLoader";
|
||||
import ArticleButton from "./ArticleButtonLoader";
|
||||
import ArticleProfileLoader from "./ArticleProfileLoader";
|
||||
import ArticleFolder from "./ArticleFolderLoader";
|
||||
import ArticleGroup from "./ArticleGroupsLoader";
|
||||
|
||||
import TreeFolders from "./TreeFolderLoader";
|
||||
import NewTreeFolders from "./NewTreeFolderLoader";
|
||||
import TreeSettingsLoader from "./TreeSettingsLoader";
|
||||
@ -52,8 +48,7 @@ import SectionSubmenuLoader from "./SectionSubmenuLoader";
|
||||
export default {
|
||||
Header,
|
||||
SectionHeader,
|
||||
ArticleHeader,
|
||||
ArticleProfileLoader,
|
||||
|
||||
TreeFolders,
|
||||
TreeSettingsLoader,
|
||||
|
||||
@ -69,9 +64,7 @@ export default {
|
||||
|
||||
DialogLoader,
|
||||
DialogAsideLoader,
|
||||
ArticleButton,
|
||||
ArticleFolder,
|
||||
ArticleGroup,
|
||||
|
||||
ListLoader,
|
||||
NewTreeFolders,
|
||||
SharingPanelLoader,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/common",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "echo 'skip it'",
|
||||
|
@ -4,7 +4,11 @@ import moment from "moment";
|
||||
import { getUserById } from "@docspace/shared/api/people";
|
||||
import { getUserRole } from "@docspace/shared/utils/common";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { FolderType, ShareAccessRights } from "@docspace/shared/enums";
|
||||
import {
|
||||
EmployeeActivationStatus,
|
||||
FolderType,
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
import config from "PACKAGE_FILE";
|
||||
import Filter from "@docspace/shared/api/people/filter";
|
||||
import { getRoomInfo } from "@docspace/shared/api/rooms";
|
||||
@ -14,6 +18,7 @@ import {
|
||||
editExternalLink,
|
||||
addExternalLink,
|
||||
} from "@docspace/shared/api/files";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
const observedKeys = [
|
||||
"id",
|
||||
@ -34,15 +39,13 @@ class InfoPanelStore {
|
||||
isVisible = false;
|
||||
isMobileHidden = false;
|
||||
|
||||
selection = null;
|
||||
infoPanelSelection = null;
|
||||
selectionHistory = null;
|
||||
selectionParentRoom = null;
|
||||
selectionHistory = null;
|
||||
|
||||
roomsView = infoMembers;
|
||||
fileView = infoHistory;
|
||||
|
||||
updateRoomMembers = null;
|
||||
isScrollLocked = false;
|
||||
historyWithFileList = false;
|
||||
|
||||
@ -52,7 +55,12 @@ class InfoPanelStore {
|
||||
filesStore = null;
|
||||
selectedFolderStore = null;
|
||||
treeFoldersStore = null;
|
||||
membersList = null;
|
||||
publicRoomStore = null;
|
||||
|
||||
infoPanelMembers = null;
|
||||
infoPanelSelection = null;
|
||||
infoPanelRoom = null;
|
||||
membersIsLoading = false;
|
||||
|
||||
shareChanged = false;
|
||||
|
||||
@ -70,23 +78,12 @@ class InfoPanelStore {
|
||||
|
||||
setIsMobileHidden = (bool) => (this.isMobileHidden = bool);
|
||||
|
||||
setSelection = (selection) => {
|
||||
if (this.getIsAccounts() && (!selection.email || !selection.displayName)) {
|
||||
this.selection = selection.length
|
||||
? selection
|
||||
: { isSelectedFolder: true };
|
||||
return;
|
||||
}
|
||||
this.selection = selection;
|
||||
this.isScrollLocked = false;
|
||||
};
|
||||
|
||||
setSelectionParentRoom = (obj) => (this.selectionParentRoom = obj);
|
||||
setSelectionHistory = (obj) => (this.selectionHistory = obj);
|
||||
|
||||
setSelectionHistory = (obj) => {
|
||||
this.selectionHistory = obj;
|
||||
this.historyWithFileList = this.selection.isFolder || this.selection.isRoom;
|
||||
this.historyWithFileList =
|
||||
this.infoPanelSelection.isFolder || this.infoPanelSelection.isRoom;
|
||||
};
|
||||
|
||||
resetView = () => {
|
||||
@ -98,12 +95,9 @@ class InfoPanelStore {
|
||||
this.roomsView = view;
|
||||
this.fileView = view === infoMembers ? infoHistory : view;
|
||||
this.isScrollLocked = false;
|
||||
if (view !== infoMembers) this.setMembersList(null);
|
||||
};
|
||||
if (view !== infoMembers) this.setInfoPanelMembers(null);
|
||||
|
||||
setUpdateRoomMembers = (updateRoomMembers) => {
|
||||
this.setMembersList(null);
|
||||
this.updateRoomMembers = updateRoomMembers;
|
||||
this.setNewInfoPanelSelection();
|
||||
};
|
||||
|
||||
setIsScrollLocked = (isScrollLocked) => {
|
||||
@ -112,87 +106,105 @@ class InfoPanelStore {
|
||||
|
||||
// Selection helpers //
|
||||
|
||||
getSelectedItems = () => {
|
||||
const {
|
||||
selection: filesStoreSelection,
|
||||
bufferSelection: filesStoreBufferSelection,
|
||||
} = this.filesStore;
|
||||
get infoPanelSelectedItems() {
|
||||
const { selection: filesSelection, bufferSelection: filesBufferSelection } =
|
||||
this.filesStore;
|
||||
|
||||
const {
|
||||
selection: peopleStoreSelection,
|
||||
bufferSelection: peopleStoreBufferSelection,
|
||||
selection: peopleSelection,
|
||||
bufferSelection: peopleBufferSelection,
|
||||
} = this.peopleStore.selectionStore;
|
||||
|
||||
return this.getIsAccounts()
|
||||
? peopleStoreSelection.length
|
||||
? [...peopleStoreSelection]
|
||||
: peopleStoreBufferSelection
|
||||
? [peopleStoreBufferSelection]
|
||||
? peopleSelection.length
|
||||
? [...peopleSelection]
|
||||
: peopleBufferSelection
|
||||
? [peopleBufferSelection]
|
||||
: []
|
||||
: filesStoreSelection?.length > 0
|
||||
? [...filesStoreSelection]
|
||||
: filesStoreBufferSelection
|
||||
? [filesStoreBufferSelection]
|
||||
: filesSelection?.length > 0
|
||||
? [...filesSelection]
|
||||
: filesBufferSelection
|
||||
? [filesBufferSelection]
|
||||
: [];
|
||||
}
|
||||
|
||||
getInfoPanelSelectedFolder = () => {
|
||||
const isRooms = this.getIsRooms();
|
||||
|
||||
return this.roomsView === infoMembers && this.infoPanelRoom && isRooms
|
||||
? this.infoPanelRoom
|
||||
: this.selectedFolderStore.getSelectedFolder();
|
||||
};
|
||||
|
||||
getSelectedFolder = () => {
|
||||
const selectedFolderStore = { ...this.selectedFolderStore };
|
||||
get infoPanelCurrentSelection() {
|
||||
const { selection, bufferSelection } = this.filesStore;
|
||||
|
||||
return this.infoPanelSelection
|
||||
? this.infoPanelSelection
|
||||
: selection.length
|
||||
? selection[0]
|
||||
: bufferSelection
|
||||
? bufferSelection
|
||||
: null;
|
||||
}
|
||||
|
||||
get withPublicRoomBlock() {
|
||||
return (
|
||||
this.infoPanelCurrentSelection?.access ===
|
||||
ShareAccessRights.RoomManager ||
|
||||
this.infoPanelCurrentSelection?.access === ShareAccessRights.None
|
||||
);
|
||||
}
|
||||
|
||||
getViewItem = () => {
|
||||
const isRooms = this.getIsRooms();
|
||||
|
||||
if (
|
||||
isRooms &&
|
||||
this.roomsView === infoMembers &&
|
||||
!this.infoPanelSelectedItems[0]?.isRoom
|
||||
) {
|
||||
// if (!this.infoPanelSelection?.id) {
|
||||
return this.getInfoPanelSelectedFolder();
|
||||
// }
|
||||
} else {
|
||||
return this.infoPanelSelectedItems[0];
|
||||
}
|
||||
};
|
||||
|
||||
setNewInfoPanelSelection = () => {
|
||||
const selectedItems = this.infoPanelSelectedItems; //files list
|
||||
const selectedFolder = this.getInfoPanelSelectedFolder(); // root or current folder
|
||||
let newInfoPanelSelection = this.infoPanelSelection;
|
||||
|
||||
if (!selectedItems.length) {
|
||||
newInfoPanelSelection = this.normalizeSelection(selectedFolder);
|
||||
} else if (selectedItems.length === 1) {
|
||||
newInfoPanelSelection = this.normalizeSelection(
|
||||
this.getViewItem() ?? newInfoPanelSelection
|
||||
);
|
||||
} else {
|
||||
newInfoPanelSelection = [...Array(selectedItems.length).keys()];
|
||||
}
|
||||
|
||||
this.setInfoPanelSelection(newInfoPanelSelection);
|
||||
};
|
||||
|
||||
normalizeSelection = (infoPanelSelection) => {
|
||||
return {
|
||||
...selectedFolderStore,
|
||||
isFolder: true,
|
||||
isRoom: !!this.selectedFolderStore.roomType,
|
||||
};
|
||||
};
|
||||
|
||||
calculateSelection = (
|
||||
props = { selectedItems: [], selectedFolder: null }
|
||||
) => {
|
||||
const selectedItems = props.selectedItems.length
|
||||
? props.selectedItems
|
||||
: this.getSelectedItems();
|
||||
|
||||
const selectedFolder = props.selectedFolder
|
||||
? props.selectedFolder
|
||||
: this.getSelectedFolder();
|
||||
|
||||
return selectedItems.length === 0
|
||||
? this.normalizeSelection({
|
||||
...selectedFolder,
|
||||
isSelectedFolder: true,
|
||||
isSelectedItem: false,
|
||||
})
|
||||
: selectedItems.length === 1
|
||||
? this.normalizeSelection({
|
||||
...selectedItems[0],
|
||||
isSelectedFolder: false,
|
||||
isSelectedItem: true,
|
||||
})
|
||||
: [...Array(selectedItems.length).keys()];
|
||||
};
|
||||
|
||||
normalizeSelection = (selection) => {
|
||||
const isContextMenuSelection = selection.isContextMenuSelection;
|
||||
return {
|
||||
...selection,
|
||||
isRoom: selection.isRoom || !!selection.roomType,
|
||||
icon: this.getInfoPanelItemIcon(selection, 32),
|
||||
isContextMenuSelection: false,
|
||||
wasContextMenuSelection: !!isContextMenuSelection,
|
||||
...infoPanelSelection,
|
||||
isRoom: infoPanelSelection.isRoom || !!infoPanelSelection.roomType,
|
||||
icon: this.getInfoPanelItemIcon(infoPanelSelection, 32),
|
||||
canCopyPublicLink:
|
||||
selection.access === ShareAccessRights.RoomManager ||
|
||||
selection.access === ShareAccessRights.None,
|
||||
infoPanelSelection.access === ShareAccessRights.RoomManager ||
|
||||
infoPanelSelection.access === ShareAccessRights.None,
|
||||
};
|
||||
};
|
||||
|
||||
reloadSelection = () => {
|
||||
this.setSelection(this.calculateSelection());
|
||||
};
|
||||
|
||||
updateRoomLogoCacheBreaker = () => {
|
||||
const logo = this.selection.logo;
|
||||
this.setSelection({
|
||||
...this.selection,
|
||||
const logo = this.infoPanelSelection.logo;
|
||||
this.setInfoPanelSelection({
|
||||
...this.infoPanelSelection,
|
||||
logo: {
|
||||
small: logo.small.split("?")[0] + "?" + new Date().getTime(),
|
||||
medium: logo.medium.split("?")[0] + "?" + new Date().getTime(),
|
||||
@ -202,32 +214,35 @@ class InfoPanelStore {
|
||||
});
|
||||
};
|
||||
|
||||
reloadSelectionParentRoom = async () => {
|
||||
updateInfoPanelSelection = async (room) => {
|
||||
if (room) {
|
||||
this.setInfoPanelSelection(this.normalizeSelection(room));
|
||||
if (this.infoPanelRoom?.id === room?.id) {
|
||||
this.setInfoPanelRoom(this.normalizeSelection(room));
|
||||
}
|
||||
} else {
|
||||
this.setNewInfoPanelSelection();
|
||||
}
|
||||
|
||||
if (!this.getIsRooms) return;
|
||||
|
||||
const currentFolderRoomId =
|
||||
this.selectedFolderStore.pathParts &&
|
||||
this.selectedFolderStore.pathParts[1]?.id;
|
||||
// const prevRoomId = this.selectionParentRoom?.id;
|
||||
|
||||
// if (!currentFolderRoomId || currentFolderRoomId === prevRoomId) return;
|
||||
if (!currentFolderRoomId) return;
|
||||
|
||||
const newSelectionParentRoom = await getRoomInfo(currentFolderRoomId);
|
||||
|
||||
// if (prevRoomId === newSelectionParentRoom.id) return;
|
||||
const newInfoPanelSelection = await getRoomInfo(currentFolderRoomId);
|
||||
|
||||
const roomIndex = this.selectedFolderStore.navigationPath.findIndex(
|
||||
(f) => f.id === currentFolderRoomId
|
||||
);
|
||||
if (roomIndex > -1) {
|
||||
this.selectedFolderStore.navigationPath[roomIndex].title =
|
||||
newSelectionParentRoom.title;
|
||||
newInfoPanelSelection.title;
|
||||
}
|
||||
|
||||
this.setSelectionParentRoom(
|
||||
this.normalizeSelection(newSelectionParentRoom)
|
||||
);
|
||||
this.setInfoPanelSelection(this.normalizeSelection(newInfoPanelSelection));
|
||||
};
|
||||
|
||||
isItemChanged = (oldItem, newItem) => {
|
||||
@ -354,8 +369,159 @@ class InfoPanelStore {
|
||||
return pathname.indexOf("files/trash") !== -1;
|
||||
};
|
||||
|
||||
setMembersList = (membersList) => {
|
||||
this.membersList = membersList;
|
||||
setInfoPanelMembers = (infoPanelMembers) => {
|
||||
this.infoPanelMembers = infoPanelMembers;
|
||||
};
|
||||
|
||||
setInfoPanelSelection = (infoPanelSelection) => {
|
||||
if (isEqual(infoPanelSelection, this.infoPanelSelection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.getIsAccounts() &&
|
||||
(!infoPanelSelection.email || !infoPanelSelection.displayName)
|
||||
) {
|
||||
this.infoPanelSelection = infoPanelSelection.length
|
||||
? infoPanelSelection
|
||||
: null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.setInfoPanelMembers(null);
|
||||
this.infoPanelSelection = infoPanelSelection;
|
||||
this.isScrollLocked = false;
|
||||
};
|
||||
|
||||
setInfoPanelRoom = (infoPanelRoom) => {
|
||||
this.infoPanelRoom = infoPanelRoom
|
||||
? this.normalizeSelection(infoPanelRoom)
|
||||
: infoPanelRoom;
|
||||
};
|
||||
|
||||
setMembersIsLoading = (membersIsLoading) => {
|
||||
this.membersIsLoading = membersIsLoading;
|
||||
};
|
||||
|
||||
getHasPrevTitle = (array, type) => {
|
||||
return this.infoPanelMembers?.roomId === this.infoPanelSelection.id
|
||||
? array.findIndex((x) => x.id === type) > -1
|
||||
: false;
|
||||
};
|
||||
|
||||
addMembersTitle = (t, administrators, users, expectedMembers) => {
|
||||
let hasPrevAdminsTitle = this.getHasPrevTitle(
|
||||
administrators,
|
||||
"administration"
|
||||
);
|
||||
|
||||
if (administrators.length && !hasPrevAdminsTitle) {
|
||||
administrators.unshift({
|
||||
id: "administration",
|
||||
displayName: t("Administration"),
|
||||
isTitle: true,
|
||||
});
|
||||
}
|
||||
|
||||
let hasPrevUsersTitle = this.getHasPrevTitle(users, "user");
|
||||
|
||||
if (users.length && !hasPrevUsersTitle) {
|
||||
users.unshift({ id: "user", displayName: t("Users"), isTitle: true });
|
||||
}
|
||||
|
||||
let hasPrevExpectedTitle = this.getHasPrevTitle(
|
||||
expectedMembers,
|
||||
"expected"
|
||||
);
|
||||
|
||||
if (expectedMembers.length && !hasPrevExpectedTitle) {
|
||||
expectedMembers.unshift({
|
||||
id: "expected",
|
||||
displayName: t("ExpectUsers"),
|
||||
isTitle: true,
|
||||
isExpect: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
convertMembers = (t, members, clearFilter) => {
|
||||
const users = [];
|
||||
const administrators = [];
|
||||
const expectedMembers = [];
|
||||
|
||||
members?.map((fetchedMember) => {
|
||||
const member = {
|
||||
access: fetchedMember.access,
|
||||
canEditAccess: fetchedMember.canEditAccess,
|
||||
...fetchedMember.sharedTo,
|
||||
};
|
||||
|
||||
if (member.activationStatus === EmployeeActivationStatus.Pending) {
|
||||
member.isExpect = true;
|
||||
expectedMembers.push(member);
|
||||
} else if (
|
||||
member.access === ShareAccessRights.FullAccess ||
|
||||
member.access === ShareAccessRights.RoomManager
|
||||
) {
|
||||
administrators.push(member);
|
||||
} else {
|
||||
users.push(member);
|
||||
}
|
||||
});
|
||||
|
||||
if (clearFilter) {
|
||||
this.addMembersTitle(t, administrators, users, expectedMembers);
|
||||
}
|
||||
|
||||
return { administrators, users, expectedMembers };
|
||||
};
|
||||
|
||||
fetchMembers = async (t, clearFilter = true) => {
|
||||
if (this.membersIsLoading) return;
|
||||
const isPublic =
|
||||
this.infoPanelSelection?.roomType ?? this.infoPanelSelection?.roomType;
|
||||
const roomId = this.infoPanelSelection.id;
|
||||
|
||||
const requests = [this.filesStore.getRoomMembers(roomId, clearFilter)];
|
||||
|
||||
if (isPublic && clearFilter && this.withPublicRoomBlock) {
|
||||
requests.push(this.filesStore.getRoomLinks(roomId));
|
||||
}
|
||||
|
||||
let timerId;
|
||||
if (clearFilter)
|
||||
timerId = setTimeout(() => this.setMembersIsLoading(true), 300);
|
||||
|
||||
const [data, links] = await Promise.all(requests);
|
||||
clearFilter && this.setMembersIsLoading(false);
|
||||
clearTimeout(timerId);
|
||||
|
||||
links && this.publicRoomStore.setExternalLinks(links);
|
||||
|
||||
const { administrators, users, expectedMembers } = this.convertMembers(
|
||||
t,
|
||||
data,
|
||||
clearFilter
|
||||
);
|
||||
|
||||
return {
|
||||
users,
|
||||
administrators,
|
||||
expected: expectedMembers,
|
||||
roomId,
|
||||
};
|
||||
};
|
||||
|
||||
addInfoPanelMembers = (t, members, clearFilter) => {
|
||||
const newMembers = this.convertMembers(t, members, clearFilter);
|
||||
const { roomId, administrators, users, expected } = this.infoPanelMembers;
|
||||
|
||||
this.setInfoPanelMembers({
|
||||
roomId: roomId,
|
||||
administrators: [...administrators, ...newMembers.administrators],
|
||||
users: [...users, ...newMembers.users],
|
||||
expected: [...expected, ...newMembers.expectedMembers],
|
||||
});
|
||||
};
|
||||
|
||||
openShareTab = () => {
|
||||
|
@ -7,9 +7,18 @@ import { frameCallEvent } from "@docspace/shared/utils/common";
|
||||
import { setCookie } from "@docspace/shared/utils/cookie";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import FirebaseHelper from "@docspace/shared/utils/firebase";
|
||||
import { ThemeKeys, TenantStatus, DeviceType } from "@docspace/shared/enums";
|
||||
import {
|
||||
ThemeKeys,
|
||||
TenantStatus,
|
||||
DeviceType,
|
||||
ArticleAlerts,
|
||||
} from "@docspace/shared/enums";
|
||||
|
||||
import { LANGUAGE, COOKIE_EXPIRATION_YEAR } from "@docspace/shared/constants";
|
||||
import {
|
||||
LANGUAGE,
|
||||
COOKIE_EXPIRATION_YEAR,
|
||||
MEDIA_VIEW_URL,
|
||||
} from "@docspace/shared/constants";
|
||||
import { version } from "../package.json";
|
||||
import SocketIOHelper from "@docspace/shared/utils/socket";
|
||||
import { Dark, Base } from "@docspace/shared/themes";
|
||||
@ -20,7 +29,6 @@ import {
|
||||
getCookie,
|
||||
} from "@docspace/shared/utils";
|
||||
import { WRONG_PORTAL_NAME_URL } from "@docspace/shared/constants";
|
||||
import { ARTICLE_ALERTS } from "@docspace/client/src/helpers/constants";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
//import { getFromLocalStorage } from "@docspace/client/src/pages/PortalSettings/utils";
|
||||
|
||||
@ -36,7 +44,9 @@ const initArticleAlertsData = () => {
|
||||
const savedArticleAlertsData = localStorage.getItem("articleAlertsData");
|
||||
if (savedArticleAlertsData) return JSON.parse(savedArticleAlertsData);
|
||||
|
||||
const articleAlertsArray = Object.values(ARTICLE_ALERTS);
|
||||
const articleAlertsArray = Object.values(ArticleAlerts).filter(
|
||||
(item, index) => Object.values(ArticleAlerts).indexOf(item) === index
|
||||
);
|
||||
const defaultArticleAlertsData = {
|
||||
current: articleAlertsArray[0],
|
||||
available: articleAlertsArray,
|
||||
@ -428,10 +438,7 @@ class SettingsStore {
|
||||
else newSettings = await api.settings.getSettings(true);
|
||||
|
||||
if (window["AscDesktopEditor"] !== undefined || this.personal) {
|
||||
const dp = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
"/products/files/"
|
||||
);
|
||||
const dp = combineUrl(window.DocSpaceConfig?.proxy?.url, MEDIA_VIEW_URL);
|
||||
this.setDefaultPage(dp);
|
||||
}
|
||||
|
||||
|
@ -111,11 +111,13 @@ class UserStore {
|
||||
return email;
|
||||
};
|
||||
|
||||
updateUser = (newUser) => {
|
||||
this.user = { ...this.user, newUser };
|
||||
};
|
||||
|
||||
updateAvatarInfo = (avatar, avatarSmall, avatarMedium, avatarMax) => {
|
||||
this.user.avatar = avatar;
|
||||
this.user.avatarSmall = avatarSmall;
|
||||
this.user.avatarMedium = avatarMedium;
|
||||
this.user.avatarMax = avatarMax;
|
||||
this.updateUser({ avatar, avatarSmall, avatarMedium, avatarMax });
|
||||
};
|
||||
|
||||
get withActivationBar() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/editor",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"private": true,
|
||||
"homepage": "/doceditor",
|
||||
"scripts": {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user