Merge branch 'develop' into feature/active-sessions

This commit is contained in:
Elyor Djalilov 2024-01-29 12:17:45 +05:00
commit bc52d11ea9
323 changed files with 16478 additions and 18439 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

893
.yarn/releases/yarn-4.0.2.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,11 @@
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: "@yarnpkg/plugin-version"
- path: .yarn/plugins/@yarnpkg/plugin-licenses-audit.cjs
spec: "https://raw.githubusercontent.com/tophat/yarn-plugin-licenses/master/bundles/@yarnpkg/plugin-licenses-audit.js"
yarnPath: .yarn/releases/yarn-3.2.4.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs

View File

@ -1,6 +1,6 @@
{
"name": "docspace",
"version": "2.0.1",
"version": "2.0.2",
"private": true,
"workspaces": {
"packages": [
@ -8,8 +8,8 @@
]
},
"engines": {
"node": ">=18",
"yarn": ">=3"
"node": ">=20",
"yarn": ">=4"
},
"scripts": {
"build": "node ./common/scripts/before-build.js && yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/editor,@docspace/management}' run build",
@ -44,5 +44,5 @@
"shx": "^0.3.4",
"terser": "^5.16.6"
},
"packageManager": "yarn@3.2.4"
"packageManager": "yarn@4.0.2"
}

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/client",
"version": "2.0.1",
"version": "2.0.2",
"private": true,
"homepage": "",
"scripts": {

View File

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

View File

@ -203,7 +203,7 @@ export default function withFileActions(WrappedFileItem) {
item.foldersCount === 0
) {
setParentId(item.parentId);
setRoomType(item.roomType);
// setRoomType(item.roomType);
}
openFileAction(item);

View File

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

View File

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

View File

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

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

View File

@ -29,6 +29,7 @@ export type Item = {
security: Security;
roomType: number;
fileExst?: string;
shared: boolean;
};
export type BreadCrumb = {

View File

@ -13,6 +13,8 @@ import { Backdrop } from "@docspace/shared/components/backdrop";
import { Portal } from "@docspace/shared/components/portal";
import { toastr } from "@docspace/shared/components/toast";
import { RowLoader, SearchLoader } from "@docspace/shared/skeletons/selector";
import EmptyScreenFilterAltSvgUrl from "PUBLIC_DIR/images/empty_screen_filter_alt.svg?url";
import EmptyScreenFilterAltDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_filter_alt_dark.svg?url";
import EmptyScreenAltSvgUrl from "PUBLIC_DIR/images/empty_screen_alt.svg?url";
@ -224,6 +226,7 @@ const FilesSelector = ({
isRoom:
item.parentId === 0 && item.rootFolderType === FolderType.Rooms,
roomType: item.roomType,
shared: item.shared,
},
]);
setSelectedItemId(item.id);
@ -363,7 +366,7 @@ const FilesSelector = ({
onCloseAction();
};
const onSearchAction = (value: string) => {
const onSearchAction = (value: string, callback?: Function) => {
setIsFirstLoad(true);
setItems(null);
if (selectedItemType === "rooms") {
@ -373,9 +376,10 @@ const FilesSelector = ({
}
setSearchValue(value);
callback?.();
};
const onClearSearchAction = () => {
const onClearSearchAction = (callback?: Function) => {
setIsFirstLoad(true);
setItems(null);
if (selectedItemType === "rooms") {
@ -385,6 +389,7 @@ const FilesSelector = ({
}
setSearchValue("");
callback?.();
};
const onAcceptAction = (
@ -552,13 +557,13 @@ const FilesSelector = ({
isBreadCrumbsLoading={showBreadCrumbsLoader}
withSearch={!isRoot && items ? items.length > 0 : !isRoot && isFirstLoad}
rowLoader={
<Loaders.SelectorRowLoader
<RowLoader
isMultiSelect={false}
isUser={isRoot}
isContainer={showLoader}
/>
}
searchLoader={<Loaders.SelectorSearchLoader />}
searchLoader={<SearchLoader />}
breadCrumbsLoader={<Loaders.SelectorBreadCrumbsLoader />}
alwaysShowFooter={true}
isNextPageLoading={isNextPageLoading}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,286 +0,0 @@
import i18n from "./i18n";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import React, { useState, useEffect } from "react";
import { I18nextProvider, withTranslation } from "react-i18next";
import { Selector } from "@docspace/shared/components/selector";
import { getUserRole } from "@docspace/shared/utils/common";
import Filter from "@docspace/shared/api/people/filter";
import { getUserList } from "@docspace/shared/api/people";
import Loaders from "@docspace/common/components/Loaders";
import { EmployeeStatus } from "@docspace/shared/enums";
import { LOADER_TIMEOUT } from "@docspace/shared/constants";
import useLoadingWithTimeout from "SRC_DIR/Hooks/useLoadingWithTimeout";
import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
import EmptyScreenPersonsSvgUrl from "PUBLIC_DIR/images/empty_screen_persons.svg?url";
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import EmptyScreenPersonsSvgDarkUrl from "PUBLIC_DIR/images/empty_screen_persons_dark.svg?url";
const PeopleSelector = ({
acceptButtonLabel,
accessRights,
cancelButtonLabel,
className,
emptyScreenDescription,
emptyScreenHeader,
headerLabel,
id,
isMultiSelect,
items,
onAccept,
onAccessRightsChange,
onBackClick,
onCancel,
onSelect,
onSelectAll,
searchEmptyScreenDescription,
searchEmptyScreenHeader,
searchPlaceholder,
selectAllIcon,
selectAllLabel,
selectedAccessRight,
selectedItems,
style,
t,
withAccessRights,
withCancelButton,
withSelectAll,
filter,
excludeItems,
currentUserId,
theme,
withOutCurrentAuthorizedUser,
withAbilityCreateRoomUsers,
withFooterCheckbox,
footerCheckboxLabel,
isChecked,
setIsChecked,
filterUserId,
}) => {
const [itemsList, setItemsList] = useState(items);
const [searchValue, setSearchValue] = useState("");
const [total, setTotal] = useState(0);
const [hasNextPage, setHasNextPage] = useState(true);
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
const [isLoading, setIsLoading] = useLoadingWithTimeout(
LOADER_TIMEOUT,
false
);
useEffect(() => {
loadNextPage(0);
}, []);
const toListItem = (item) => {
const {
id,
email,
avatar,
icon,
displayName,
hasAvatar,
isOwner,
isAdmin,
isVisitor,
isCollaborator,
} = item;
const role = getUserRole(item);
const userAvatar = hasAvatar ? avatar : DefaultUserPhoto;
return {
id,
email,
avatar: userAvatar,
icon,
label: displayName || email,
role,
isOwner,
isAdmin,
isVisitor,
isCollaborator,
hasAvatar,
};
};
const moveCurrentUserToTopOfList = (listUser) => {
const currentUserIndex = listUser.findIndex(
(user) => user.id === currentUserId
);
// return if the current user is already at the top of the list or not found
if (currentUserIndex < 1) return listUser;
const [currentUser] = listUser.splice(currentUserIndex, 1);
listUser.splice(0, 0, currentUser);
return listUser;
};
const removeCurrentUserFromList = (listUser) => {
if (filterUserId) {
return listUser.filter((user) => user.id !== filterUserId);
}
return listUser.filter((user) => user.id !== currentUserId);
};
const loadNextPage = (startIndex, search = searchValue) => {
const pageCount = 100;
setIsNextPageLoading(true);
if (startIndex === 0) {
setIsLoading(true);
}
const currentFilter =
typeof filter === "function" ? filter() : filter ?? Filter.getDefault();
currentFilter.page = startIndex / pageCount;
currentFilter.pageCount = pageCount;
if (!!search.length) {
currentFilter.search = search;
}
getUserList(currentFilter)
.then((response) => {
let newItems = startIndex ? itemsList : [];
let totalDifferent = startIndex ? response.total - total : 0;
const items = response.items
.filter((item) => {
const excludeUser =
withAbilityCreateRoomUsers &&
((!item.isAdmin && !item.isOwner && !item.isRoomAdmin) ||
item.status === EmployeeStatus.Disabled);
if (excludeItems.includes(item.id) || excludeUser) {
totalDifferent++;
return false;
} else {
return true;
}
})
.map((item) => toListItem(item));
const tempItems = [...newItems, ...items];
newItems = withOutCurrentAuthorizedUser
? removeCurrentUserFromList(tempItems)
: moveCurrentUserToTopOfList(tempItems);
const newTotal = withOutCurrentAuthorizedUser
? response.total - totalDifferent - 1
: response.total - totalDifferent;
setHasNextPage(newItems.length < newTotal);
setItemsList(newItems);
setTotal(newTotal);
setIsNextPageLoading(false);
setIsLoading(false);
})
.catch((error) => console.log(error));
};
const onSearch = (value) => {
setSearchValue(value);
loadNextPage(0, value);
};
const onClearSearch = () => {
setSearchValue("");
loadNextPage(0, "");
};
const emptyScreenImage = theme.isBase
? EmptyScreenPersonsSvgUrl
: EmptyScreenPersonsSvgDarkUrl;
return (
<Selector
id={id}
className={className}
style={style}
headerLabel={headerLabel || t("ListAccounts")}
onBackClick={onBackClick}
searchPlaceholder={searchPlaceholder || t("Common:Search")}
searchValue={searchValue}
onSearch={onSearch}
onClearSearch={onClearSearch}
items={itemsList}
isMultiSelect={isMultiSelect}
selectedItems={selectedItems}
acceptButtonLabel={acceptButtonLabel || t("Common:SelectAction")}
onAccept={onAccept}
withSelectAll={withSelectAll}
selectAllLabel={selectAllLabel || t("AllAccounts")}
selectAllIcon={selectAllIcon}
withAccessRights={withAccessRights}
accessRights={accessRights}
selectedAccessRight={selectedAccessRight}
withCancelButton={withCancelButton}
cancelButtonLabel={cancelButtonLabel || t("Common:CancelButton")}
onCancel={onCancel}
emptyScreenImage={emptyScreenImage}
emptyScreenHeader={emptyScreenHeader || t("EmptyHeader")}
emptyScreenDescription={emptyScreenDescription || t("EmptyDescription")}
searchEmptyScreenImage={emptyScreenImage}
searchEmptyScreenHeader={
searchEmptyScreenHeader || t("People:NotFoundUsers")
}
searchEmptyScreenDescription={
searchEmptyScreenDescription || t("People:NotFoundUsersDescription")
}
hasNextPage={hasNextPage}
isNextPageLoading={isNextPageLoading}
loadNextPage={loadNextPage}
totalItems={total}
isLoading={isLoading}
withFooterCheckbox={withFooterCheckbox}
footerCheckboxLabel={footerCheckboxLabel}
isChecked={isChecked}
setIsChecked={setIsChecked}
searchLoader={<Loaders.SelectorSearchLoader />}
isSearchLoading={isLoading}
rowLoader={<Loaders.SelectorRowLoader isUser isContainer={isLoading} />}
/>
);
};
PeopleSelector.propTypes = { excludeItems: PropTypes.array };
PeopleSelector.defaultProps = {
excludeItems: [],
selectAllIcon: CatalogAccountsReactSvgUrl,
};
const ExtendedPeopleSelector = inject(({ auth }) => {
return {
theme: auth.settingsStore.theme,
currentUserId: auth.userStore.user.id,
};
})(
observer(
withTranslation([
"PeopleSelector",
"PeopleTranslations",
"People",
"Common",
])(PeopleSelector)
)
);
export default (props) => (
<I18nextProvider i18n={i18n}>
<ExtendedPeopleSelector {...props} />
</I18nextProvider>
);

View File

@ -1,62 +0,0 @@
import React from "react";
import PropTypes from "prop-types";
import { Avatar } from "@docspace/shared/components/avatar";
import { Text } from "@docspace/shared/components/text";
import StyledUserTooltip from "./StyledUserTooltip";
const UserTooltip = ({ avatarUrl, label, email, position, theme }) => (
<StyledUserTooltip theme={theme}>
<div className="block-avatar">
<Avatar
theme={theme}
className="user-avatar"
size="min"
role="user"
source={avatarUrl}
userName=""
editing={false}
/>
</div>
<div className="block-info">
<Text
theme={theme}
isBold={true}
fontSize="13px"
fontWeight={600}
truncate={true}
title={label}
>
{label}
</Text>
<Text
theme={theme}
color={theme.peopleSelector.textColor}
fontSize="13px"
className="email-text"
truncate={true}
title={email}
>
{email}
</Text>
<Text
theme={theme}
fontSize="13px"
fontWeight={600}
truncate={true}
title={position}
>
{position}
</Text>
</div>
</StyledUserTooltip>
);
UserTooltip.propTypes = {
avatarUrl: PropTypes.string,
label: PropTypes.string,
email: PropTypes.string,
position: PropTypes.string,
};
export default UserTooltip;

View File

@ -4,7 +4,7 @@ import { inject, observer } from "mobx-react";
import { ReactSVG } from "react-svg";
import { withTranslation } from "react-i18next";
import PeopleSelector from "SRC_DIR/components/PeopleSelector";
import PeopleSelector from "@docspace/shared/selectors/People";
import Filter from "@docspace/shared/api/people/filter";
@ -118,6 +118,7 @@ const ChangePortalOwnerDialog = ({
onAccept={onAccept}
onCancel={onBackClick}
onBackClick={onBackClick}
currentUserId={id}
/>
</ModalDialog.Container>
)}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import styled from "styled-components";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import PeopleSelector from "@docspace/client/src/components/PeopleSelector";
import PeopleSelector from "@docspace/shared/selectors/People";
import { toastr } from "@docspace/shared/components/toast";
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
import { Backdrop } from "@docspace/shared/components/backdrop";
@ -177,23 +177,24 @@ const DataReassignmentDialog = ({
visible={visible}
onClose={onClosePeopleSelector}
containerVisible={selectorVisible}
withFooterBorder={true}
withBodyScroll={true}
withFooterBorder
withBodyScroll
>
<Backdrop
onClick={onClosePeopleSelector}
visible={selectorVisible}
isAside={true}
isAside
/>
<ModalDialog.Container>
<PeopleSelector
acceptButtonLabel={t("Common:SelectAction")}
excludeItems={[user.id]}
currentUserId={user.id}
onAccept={onAccept}
onCancel={onClosePeopleSelector}
onBackClick={onTogglePeopleSelector}
withCancelButton={true}
withAbilityCreateRoomUsers={true}
withCancelButton
withAbilityCreateRoomUsers
/>
</ModalDialog.Container>
</StyledModalDialog>
@ -206,8 +207,8 @@ const DataReassignmentDialog = ({
visible={visible}
onClose={onClose}
containerVisible={selectorVisible}
withFooterBorder={true}
withBodyScroll={true}
withFooterBorder
withBodyScroll
>
<ModalDialog.Header>
{t("DataReassignmentDialog:DataReassignment")}

View File

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

View File

@ -12,7 +12,7 @@ import { getUserRole } from "@docspace/shared/utils/common";
import Filter from "@docspace/shared/api/people/filter";
import Loaders from "@docspace/common/components/Loaders";
import { getMembersList } from "@docspace/shared/api/people";
import useLoadingWithTimeout from "SRC_DIR/Hooks/useLoadingWithTimeout";
import useLoadingWithTimeout from "@docspace/shared/hooks/useLoadingWithTimeout";
import { ShareAccessRights } from "@docspace/shared/enums";
import { LOADER_TIMEOUT } from "@docspace/shared/constants";
@ -23,6 +23,7 @@ import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.pn
import EmptyScreenPersonsSvgUrl from "PUBLIC_DIR/images/empty_screen_persons.svg?url";
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import EmptyScreenPersonsSvgDarkUrl from "PUBLIC_DIR/images/empty_screen_persons_dark.svg?url";
import { RowLoader, SearchLoader } from "@docspace/shared/skeletons/selector";
const AddUsersPanel = ({
isEncrypted,
@ -257,10 +258,10 @@ const AddUsersPanel = ({
loadNextPage={loadNextPage}
totalItems={total}
isLoading={isLoading}
searchLoader={<Loaders.SelectorSearchLoader />}
searchLoader={<SearchLoader />}
isSearchLoading={isLoading && !isLoadingSearch}
rowLoader={
<Loaders.SelectorRowLoader
<RowLoader
isUser
count={15}
isContainer={isLoading}

View File

@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
import styled, { css } from "styled-components";
import { Aside } from "@docspace/shared/components/aside";
import { Backdrop } from "@docspace/shared/components/backdrop";
import PeopleSelector from "@docspace/client/src/components/PeopleSelector";
import PeopleSelector from "@docspace/shared/selectors/People";
import { withTranslation } from "react-i18next";
import Filter from "@docspace/shared/api/people/filter";
import { EmployeeType, DeviceType } from "@docspace/shared/enums";
@ -45,6 +45,8 @@ const ChangeRoomOwner = (props) => {
currentDeviceType,
roomOwnerId,
changeRoomOwner,
userId,
updateInfoPanelSelection,
} = props;
const [isLoading, setIsLoading] = useState(false);
@ -70,6 +72,7 @@ const ChangeRoomOwner = (props) => {
setIsLoading(true);
await changeRoomOwner(t, user[0]?.id, isChecked);
updateInfoPanelSelection();
setIsLoading(false);
}
onClose();
@ -120,6 +123,7 @@ const ChangeRoomOwner = (props) => {
setIsChecked={setIsChecked}
withOutCurrentAuthorizedUser
filterUserId={roomOwnerId}
currentUserId={userId}
/>
</Aside>
</StyledChangeRoomOwner>
@ -145,9 +149,10 @@ export default inject(
setChangeRoomOwnerIsVisible,
changeRoomOwnerData,
} = dialogsStore;
const { settingsStore } = auth;
const { settingsStore, userStore, infoPanelStore } = auth;
const { selection, bufferSelection } = filesStore;
const { currentDeviceType } = settingsStore;
const { updateInfoPanelSelection } = infoPanelStore;
const room = selection.length
? selection[0]
@ -155,7 +160,7 @@ export default inject(
? bufferSelection
: selectedFolderStore;
const { currentDeviceType } = settingsStore;
const { id } = userStore.user;
return {
visible: changeRoomOwnerIsVisible,
@ -165,6 +170,8 @@ export default inject(
roomOwnerId: room?.createdBy?.id,
currentDeviceType,
changeRoomOwner: filesActionsStore.changeRoomOwner,
userId: id,
updateInfoPanelSelection,
};
}
)(observer(withTranslation(["Files"])(ChangeRoomOwner)));

View File

@ -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 ?? "",

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import React from "react";
import { useLocation, Navigate } from "react-router-dom";
import { AuthenticatedAction, ValidationResult } from "./../helpers/constants";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { checkConfirmLink } from "@docspace/shared/api/user"; //TODO: Move AuthStore
import { getObjectByLocation } from "@docspace/shared/utils/common";
import { combineUrl } from "@docspace/shared/utils/combineUrl";

View File

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

View File

@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { I18nextProvider, withTranslation } from "react-i18next";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import i18n from "./i18n";

View File

@ -1,7 +1,7 @@
import React from "react";
import PropTypes from "prop-types";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import tryRedirectTo from "@docspace/shared/utils/tryRedirectTo";
import { inject, observer } from "mobx-react";

View File

@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { loginWithConfirmKey } from "@docspace/shared/api/user";
import { useSearchParams } from "react-router-dom";
import { combineUrl } from "@docspace/shared/utils/combineUrl";

View File

@ -2,7 +2,7 @@ import React from "react";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import tryRedirectTo from "@docspace/shared/utils/tryRedirectTo";
import SectionWrapper from "SRC_DIR/components/Section";

View File

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

View File

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

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from "react";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { observer, inject } from "mobx-react";
import { useLocation, useNavigate, useParams } from "react-router-dom";

View File

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

View File

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

View File

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

View File

@ -9,13 +9,13 @@ import { Button } from "@docspace/shared/components/button";
import { Text } from "@docspace/shared/components/text";
import { MAX_FILE_COMMENT_LENGTH } from "@docspace/shared/constants";
// import infoPanel from "@docspace/common/components/Section/sub-components/info-panel";
// import infoPanel from "@docspace/shared/components/section/sub-components/info-panel";
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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"])(

View File

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

View File

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

View File

@ -8,7 +8,7 @@ import result from "lodash/result";
import { isTablet, isMobile } from "@docspace/shared/utils";
import { RoomsTypeValues } from "@docspace/shared/utils/common";
import FilterInput from "@docspace/common/components/FilterInput";
import FilterInput from "@docspace/shared/components/filter";
import Loaders from "@docspace/common/components/Loaders";
import { withLayoutSize } from "@docspace/shared/HOC/withLayoutSize";
import { getUser } from "@docspace/shared/api/people";
@ -43,6 +43,7 @@ import ViewRowsReactSvgUrl from "PUBLIC_DIR/images/view-rows.react.svg?url";
import ViewTilesReactSvgUrl from "PUBLIC_DIR/images/view-tiles.react.svg?url";
import { getRoomInfo } from "@docspace/shared/api/rooms";
import { FilterLoader } from "@docspace/shared/skeletons/filter";
const getAccountLoginType = (filterValues) => {
const accountLoginType = result(
@ -383,7 +384,7 @@ const SectionFilterContent = ({
newFilter.withSubfolders =
withSubfolders === FilterKeys.excludeSubfolders ? null : "true";
console.log(data);
newFilter.searchInContent = withContent === "true" ? "true" : null;
const path = location.pathname.split("/filter")[0];
@ -1201,7 +1202,7 @@ const SectionFilterContent = ({
isHeader: true,
isLast: isLastTypeOptionsRooms,
},
...Object.values(RoomsTypeValues).map((roomType) => {
...RoomsTypeValues.map((roomType) => {
switch (roomType) {
case RoomsType.FillingFormsRoom:
return {
@ -2031,11 +2032,10 @@ const SectionFilterContent = ({
}
};
if (showFilterLoader) return <Loaders.Filter />;
if (showFilterLoader) return <FilterLoader />;
return (
<FilterInput
t={t}
onFilter={onFilter}
getFilterData={getFilterData}
getSelectedFilterData={getSelectedFilterData}
@ -2064,6 +2064,7 @@ const SectionFilterContent = ({
setClearSearch={setClearSearch}
onSortButtonClick={onSortButtonClick}
currentDeviceType={currentDeviceType}
userId={userId}
/>
);
};

View File

@ -930,6 +930,7 @@ const SectionHeaderContent = (props) => {
: "",
};
setSelected("none");
setIsLoading(true);
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, { state });

View File

@ -6,7 +6,7 @@ import { withTranslation } from "react-i18next";
import { showLoader, hideLoader } from "@docspace/shared/utils/common";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import SectionWrapper from "SRC_DIR/components/Section";
import DragTooltip from "SRC_DIR/components/DragTooltip";

View File

@ -4,6 +4,7 @@ import { Paging } from "@docspace/shared/components/paging";
import Loaders from "@docspace/common/components/Loaders";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { FilterLoader } from "@docspace/shared/skeletons/filter";
const SectionPagingContent = ({
fetchPeople,
@ -147,7 +148,7 @@ const SectionPagingContent = ({
/>
)
) : (
<Loaders.Filter />
<FilterLoader />
);
};

View File

@ -1,9 +1,9 @@
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";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import withLoading from "SRC_DIR/HOCs/withLoading";
import SectionWrapper from "SRC_DIR/components/Section";
@ -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>
);
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import { Text } from "@docspace/shared/components/text";
import { Link } from "@docspace/shared/components/link";
import { Button } from "@docspace/shared/components/button";
import { Loader } from "@docspace/shared/components/loader";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import SectionWrapper from "SRC_DIR/components/Section";
import { mobile, tablet } from "@docspace/shared/utils";
import { I18nextProvider, Trans, withTranslation } from "react-i18next";

View File

@ -1,6 +1,6 @@
import React from "react";
import PropTypes from "prop-types";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import SectionWrapper from "SRC_DIR/components/Section";
import { SectionHeaderContent, SectionBodyContent } from "./Section";

View File

@ -1,7 +1,7 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { useLocation, Outlet } from "react-router-dom";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import SectionHeaderContent from "../Home/Section/Header";
import SectionFilterContent from "../Home/Section/Filter";
import FilesPanels from "../../components/FilesPanels";

View File

@ -1,7 +1,7 @@
import React, { useEffect } from "react";
import { observer, inject } from "mobx-react";
import { useNavigate, useLocation } from "react-router-dom";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { Loader } from "@docspace/shared/components/loader";
import { ValidationStatus } from "../../helpers/constants";
import SectionWrapper from "SRC_DIR/components/Section";

View File

@ -4,7 +4,7 @@ import { useParams } from "react-router-dom";
import { Button } from "@docspace/shared/components/button";
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
import AppLoader from "@docspace/common/components/AppLoader";
import RoomSelector from "../../components/RoomSelector";
import RoomSelector from "@docspace/shared/selectors/Room";
import FilesSelector from "../../components/FilesSelector";
import {
frameCallEvent,
@ -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));

View File

@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { getObjectByLocation } from "@docspace/shared/utils/common";
import ErrorContainer from "@docspace/common/components/ErrorContainer";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import { RectangleSkeleton } from "@docspace/shared/skeletons";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import SectionWrapper from "SRC_DIR/components/Section";

View File

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

View File

@ -1,6 +1,6 @@
import React from "react";
import Section from "@docspace/common/components/Section";
import Section from "@docspace/shared/components/section";
import Loaders from "@docspace/common/components/Loaders";
import { withTranslation } from "react-i18next";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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";
@ -124,7 +124,7 @@ class ProfileActionsStore {
};
onSpacesClick = () => {
this.selectedFolderStore.setSelectedFolder(null);
// this.selectedFolderStore.setSelectedFolder(null);
window.open(SPACES_URL, "_blank");
};

View File

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

View File

@ -36,6 +36,7 @@ class SettingsStore {
keepNewFileName = null;
thumbnails1280x720 = window.DocSpaceConfig?.thumbnails1280x720 || false;
chunkUploadSize = 1024 * 1023; // 1024 * 1023; //~0.999mb
chunkUploadCount = 5;
settingsIsLoaded = false;

View File

@ -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,95 @@ class UploadDataStore {
}
};
uploadFileChunks = async (
location,
requestsDataArray,
checkChunkUpload = (
t,
res,
fileSize,
index,
indexOfFile,
file,
path,
t
length,
resolve,
reject,
isAsyncUpload = false,
isFinalize = 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 = isFinalize
? 0
: fileSize <= this.settingsStore.chunkUploadSize
? fileSize
: 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 +1001,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 +1015,196 @@ 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 finalizeIndex =
this.asyncUploadObj[operationId].chunksArray.length - 1;
const finalizeRes =
await this.asyncUploadObj[operationId].chunksArray[
finalizeChunkIndex
].onUpload();
this.checkChunkUpload(
t,
finalizeRes,
fileSize,
finalizeIndex,
indexOfFile,
path,
length,
resolve,
reject,
true, // isAsyncUpload
true //isFinalize
);
}
}
} 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 +1228,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 +1264,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 +1286,7 @@ class UploadDataStore {
if (!this.uploaded && this.files.length === 0) {
this.uploaded = true;
this.isParallel = true;
this.asyncUploadObj = {};
//setUploadData(uploadData);
return;
}
@ -1145,6 +1329,7 @@ class UploadDataStore {
.then((res) => {
const location = res.data.location;
const path = res.data.path;
const operationId = res.data.id;
const requestsDataArray = [];
@ -1158,37 +1343,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 +1458,7 @@ class UploadDataStore {
runInAction(() => {
this.uploaded = true;
this.isParallel = true;
this.asyncUploadObj = {};
});
const uploadedFiles = this.files.filter(
(x) => x.action === "uploaded"
@ -1287,6 +1492,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 +1520,7 @@ class UploadDataStore {
this.isParallel = true;
this.converted = true;
this.uploadedFilesSize = 0;
this.asyncUploadObj = {};
const uploadData = {
filesSize: 0,

View File

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

View File

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

View File

@ -308,9 +308,6 @@ module.exports = (env, argv) => {
"./src/components/FilesSelector/FilesSelectorWrapper",
"./SelectFolderDialog":
"./src/components/FilesSelector/FilesSelectorWrapper",
"./PeopleSelector": "./src/components/PeopleSelector",
"./PeopleSelector/UserTooltip":
"./src/components/PeopleSelector/sub-components/UserTooltip.js",
"./BrandingPage":
"./src/pages/PortalSettings/categories/common/branding.js",
"./WhiteLabelPage":

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