Merge branch 'hotfix/v2.6.1' into feature/terms-condition
This commit is contained in:
commit
4643144e83
@ -73,6 +73,7 @@
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.0",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@types/element-resize-detector": "^1.1.6",
|
||||
"@types/eslint": "^8.44.7",
|
||||
"@types/he": "^1.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
|
@ -23,10 +23,12 @@
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
import { useContext } from "react";
|
||||
|
||||
import { observer, inject } from "mobx-react";
|
||||
//import { useLocation } from "react-router-dom";
|
||||
|
||||
import { Context } from "@docspace/shared/utils";
|
||||
import { Events, FileExtensions } from "@docspace/shared/enums";
|
||||
|
||||
import RootFolderContainer from "./RootFolderContainer";
|
||||
@ -49,7 +51,6 @@ const EmptyContainer = ({
|
||||
theme,
|
||||
type,
|
||||
|
||||
sectionWidth,
|
||||
isRoomNotFoundOrMoved,
|
||||
isGracePeriod,
|
||||
setQuotaWarningDialogVisible,
|
||||
@ -60,6 +61,8 @@ const EmptyContainer = ({
|
||||
}) => {
|
||||
//const location = useLocation();
|
||||
|
||||
const { sectionWidth } = useContext(Context);
|
||||
|
||||
linkStyles.color = theme.filesEmptyContainer.linkColor;
|
||||
|
||||
const onCreate = (e) => {
|
||||
|
@ -29,12 +29,15 @@ import {
|
||||
TFilesSettings,
|
||||
TFolder,
|
||||
} from "@docspace/shared/api/files/types";
|
||||
import { TBreadCrumb } from "@docspace/shared/components/selector/Selector.types";
|
||||
import {
|
||||
TBreadCrumb,
|
||||
TSelectorHeader,
|
||||
} from "@docspace/shared/components/selector/Selector.types";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import { TTheme } from "@docspace/shared/themes";
|
||||
import SocketIOHelper from "@docspace/shared/utils/socket";
|
||||
|
||||
export type FilesSelectorProps = {
|
||||
export type FilesSelectorProps = TSelectorHeader & {
|
||||
isPanelVisible: boolean;
|
||||
// withoutImmediatelyClose: boolean;
|
||||
isThirdParty: boolean;
|
||||
|
@ -140,6 +140,7 @@ const FilesSelectorWrapper = ({
|
||||
openRoot,
|
||||
|
||||
filesSettings,
|
||||
headerProps,
|
||||
}: FilesSelectorProps) => {
|
||||
const { t }: { t: TTranslation } = useTranslation([
|
||||
"Files",
|
||||
@ -392,6 +393,7 @@ const FilesSelectorWrapper = ({
|
||||
getFilesArchiveError={getFilesArchiveError}
|
||||
withCreate={(isMove || isCopy || isRestore || isRestoreAll) ?? false}
|
||||
filesSettings={filesSettings}
|
||||
headerProps={headerProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -76,10 +76,12 @@ const Main = (props) => {
|
||||
if (mainBarVisible && isMobileUtils()) {
|
||||
const mainBar = document.getElementById("main-bar");
|
||||
|
||||
if (!mainBar.offsetHeight)
|
||||
return (updateSizeRef.current = setTimeout(() => onResize(), 0));
|
||||
if (mainBar) {
|
||||
if (!mainBar?.offsetHeight)
|
||||
return (updateSizeRef.current = setTimeout(() => onResize(), 0));
|
||||
|
||||
correctHeight -= mainBar.offsetHeight;
|
||||
correctHeight -= mainBar?.offsetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
const isTouchDevice =
|
||||
|
@ -105,7 +105,7 @@ const RoomsSelectorInput = (props) => {
|
||||
submitButtonLabel={submitButtonLabel}
|
||||
onSubmit={handleOnSubmit}
|
||||
withHeader={withHeader}
|
||||
headerProps={headerProps}
|
||||
headerProps={{ ...headerProps, onCloseClick: onClose }}
|
||||
setIsDataReady={setIsDataReady}
|
||||
roomType={roomType}
|
||||
/>
|
||||
@ -137,6 +137,7 @@ const RoomsSelectorInput = (props) => {
|
||||
withoutBodyScroll
|
||||
zIndex={310}
|
||||
onClose={onClose}
|
||||
withoutHeader
|
||||
>
|
||||
{SelectorBody}
|
||||
</Aside>
|
||||
|
@ -154,6 +154,7 @@ const ChangePortalOwnerDialog = ({
|
||||
disableSubmitButton={false}
|
||||
withHeader
|
||||
headerProps={{
|
||||
onCloseClick: onCloseAction,
|
||||
onBackClick,
|
||||
withoutBackButton: false,
|
||||
headerLabel: "",
|
||||
|
@ -97,11 +97,7 @@ const ChangePricingPlanDialog = ({
|
||||
isLarge
|
||||
isLoading={!ready}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text isBold fontSize="21px">
|
||||
{t("ChangePricingPlan")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("ChangePricingPlan")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text fontSize="13px" isBold className="cannot-downgrade-plan">
|
||||
{t("CannotChangePlan")}
|
||||
|
@ -1,36 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import styled from "styled-components";
|
||||
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
|
||||
const StyledModalDialog = styled(ModalDialog)`
|
||||
p {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
export default StyledModalDialog;
|
@ -34,7 +34,6 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { setTenantQuotaSettings } from "@docspace/shared/api/settings";
|
||||
|
||||
import QuotaForm from "../../../components/QuotaForm";
|
||||
import StyledModalDialog from "./StyledComponent";
|
||||
|
||||
const ChangeStorageQuotaDialog = (props) => {
|
||||
const {
|
||||
@ -115,7 +114,7 @@ const ChangeStorageQuotaDialog = (props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledModalDialog visible={isVisible} onClose={onCloseClick}>
|
||||
<ModalDialog visible={isVisible} onClose={onCloseClick}>
|
||||
<ModalDialog.Header>
|
||||
{isDisableQuota
|
||||
? t("Common:DisableStorageQuota")
|
||||
@ -159,7 +158,7 @@ const ChangeStorageQuotaDialog = (props) => {
|
||||
scale
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</StyledModalDialog>
|
||||
</ModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,6 @@ import TagHandler from "./handlers/TagHandler";
|
||||
|
||||
import SetRoomParams from "./sub-components/SetRoomParams";
|
||||
import RoomTypeList from "./sub-components/RoomTypeList";
|
||||
import DialogHeader from "./sub-components/DialogHeader";
|
||||
|
||||
const StyledModalDialog = styled(ModalDialog)`
|
||||
.header-with-button {
|
||||
@ -161,6 +160,10 @@ const CreateRoomDialog = ({
|
||||
onClose();
|
||||
};
|
||||
|
||||
const dialogHeader = roomParams.type
|
||||
? t("ChooseRoomType")
|
||||
: t("Files:CreateRoom");
|
||||
|
||||
return (
|
||||
<StyledModalDialog
|
||||
displayType="aside"
|
||||
@ -170,14 +173,10 @@ const CreateRoomDialog = ({
|
||||
isScrollLocked={isScrollLocked}
|
||||
withFooterBorder
|
||||
isOauthWindowOpen={isOauthWindowOpen}
|
||||
isBackButton={roomParams.type}
|
||||
onBackClick={goBack}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<DialogHeader
|
||||
disabledIcon={Boolean(startRoomType)}
|
||||
isChooseRoomType={!roomParams.type}
|
||||
onArrowClick={goBack}
|
||||
/>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{dialogHeader}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
{!roomParams.type ? (
|
||||
|
@ -28,7 +28,6 @@ import React, { useState, useEffect, useRef, useCallback } from "react";
|
||||
|
||||
import TagHandler from "./handlers/TagHandler";
|
||||
import SetRoomParams from "./sub-components/SetRoomParams";
|
||||
import DialogHeader from "./sub-components/DialogHeader";
|
||||
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
@ -132,9 +131,7 @@ const EditRoomDialog = ({
|
||||
isScrollLocked={isScrollLocked}
|
||||
withFooterBorder
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<DialogHeader isEdit />
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("RoomEditing")}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
<SetRoomParams
|
||||
|
@ -1,67 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import ArrowPathReactSvgUrl from "PUBLIC_DIR/images/arrow.path.react.svg?url";
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import withLoader from "@docspace/client/src/HOCs/withLoader";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import CreateEditRoomDilogHeaderLoader from "@docspace/shared/skeletons/create-edit-room/DilogHeader";
|
||||
|
||||
const DialogHeader = ({
|
||||
t,
|
||||
isEdit,
|
||||
isChooseRoomType,
|
||||
onArrowClick,
|
||||
disabledIcon,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{isEdit ? (
|
||||
<span>{t("RoomEditing")}</span>
|
||||
) : isChooseRoomType ? (
|
||||
<span>{t("ChooseRoomType")}</span>
|
||||
) : (
|
||||
<div className="header-with-button">
|
||||
{!disabledIcon && (
|
||||
<IconButton
|
||||
size={17}
|
||||
iconName={ArrowPathReactSvgUrl}
|
||||
className="sharing_panel-arrow"
|
||||
onClick={onArrowClick}
|
||||
/>
|
||||
)}
|
||||
<div>{t("Files:CreateRoom")}</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation(["CreateEditRoomDialog", "Files"])(
|
||||
withLoader(DialogHeader)(<CreateEditRoomDilogHeaderLoader />),
|
||||
);
|
@ -227,6 +227,7 @@ const DataReassignmentDialog = ({
|
||||
withCancelButton
|
||||
cancelButtonLabel=""
|
||||
headerProps={{
|
||||
onCloseClick: onClose,
|
||||
onBackClick: onClosePeopleSelector,
|
||||
withoutBackButton: false,
|
||||
headerLabel: "",
|
||||
|
@ -43,7 +43,7 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { getUserRoleOptions } from "@docspace/shared/utils/room-members/getUserRoleOptions";
|
||||
import { ShareAccessRights } from "@docspace/shared/enums";
|
||||
import { getUserRole } from "@docspace/shared/utils/common";
|
||||
import { getUserRole, getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
import { TGroupMemberInvitedInRoom } from "@docspace/shared/api/groups/types";
|
||||
|
||||
import * as Styled from "./index.styled";
|
||||
@ -59,7 +59,7 @@ const GroupMember = ({ member, infoPanelSelection }: GroupMemberProps) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { t } = useTranslation("Common");
|
||||
|
||||
const userRole = user.isOwner
|
||||
const userRole = member.owner
|
||||
? getUserRoleOptions(t).portalAdmin
|
||||
: getUserRoleOptionsByUserAccess(
|
||||
t,
|
||||
@ -74,6 +74,10 @@ const GroupMember = ({ member, infoPanelSelection }: GroupMemberProps) => {
|
||||
|
||||
const userRoleOptions = filterUserRoleOptions(fullRoomRoleOptions, user);
|
||||
|
||||
const hasIndividualRightsInRoom =
|
||||
member.owner ||
|
||||
(member.userAccess && member.userAccess !== member.groupAccess);
|
||||
|
||||
let type;
|
||||
if (user.isOwner) type = "owner";
|
||||
else if (user.isAdmin) type = "admin";
|
||||
@ -83,6 +87,11 @@ const GroupMember = ({ member, infoPanelSelection }: GroupMemberProps) => {
|
||||
|
||||
const role = getUserRole(user, userRole?.type);
|
||||
|
||||
const typeLabel = getUserTypeLabel(
|
||||
role as "owner" | "admin" | "user" | "collaborator" | "manager",
|
||||
t,
|
||||
);
|
||||
|
||||
let selectedUserRoleCBOption;
|
||||
if (user.isOwner)
|
||||
selectedUserRoleCBOption = {
|
||||
@ -140,26 +149,25 @@ const GroupMember = ({ member, infoPanelSelection }: GroupMemberProps) => {
|
||||
{decode(user.displayName)}
|
||||
</Text>
|
||||
<Text className="email" noSelect>
|
||||
{user.email}
|
||||
<span dir="auto">{typeLabel}</span> |{" "}
|
||||
<span dir="ltr">{user.email}</span>
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="individual-rights-tooltip">
|
||||
{member.userAccess &&
|
||||
member.userAccess !== member.groupAccess &&
|
||||
!user.isOwner && (
|
||||
<HelpButton
|
||||
place="left"
|
||||
offsetRight={0}
|
||||
openOnClick={false}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px" fontWeight={600}>
|
||||
{t("PeopleTranslations:IndividualRights")}
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{hasIndividualRightsInRoom && (
|
||||
<HelpButton
|
||||
place="left"
|
||||
offsetRight={0}
|
||||
openOnClick={false}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px" fontWeight={600}>
|
||||
{t("PeopleTranslations:IndividualRights")}
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{userRole && userRoleOptions && (
|
||||
|
@ -529,6 +529,7 @@ const AddUsersPanel = ({
|
||||
visible={visible}
|
||||
onClose={onClosePanels}
|
||||
withoutBodyScroll
|
||||
withoutHeader
|
||||
>
|
||||
<Selector
|
||||
withHeader
|
||||
@ -539,6 +540,7 @@ const AddUsersPanel = ({
|
||||
withoutBackButton: false,
|
||||
withoutBorder: true,
|
||||
onBackClick,
|
||||
onCloseClick: onClosePanels,
|
||||
}}
|
||||
onSelect={onSelect}
|
||||
renderCustomItem={renderCustomItem}
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
import React from "react";
|
||||
import { Backdrop } from "@docspace/shared/components/backdrop";
|
||||
import { Heading } from "@docspace/shared/components/heading";
|
||||
import { Aside } from "@docspace/shared/components/aside";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
@ -38,7 +37,6 @@ import {
|
||||
StyledAsidePanel,
|
||||
StyledContent,
|
||||
StyledFooter,
|
||||
StyledHeaderContent,
|
||||
StyledBody,
|
||||
} from "../StyledPanels";
|
||||
import { inject, observer } from "mobx-react";
|
||||
@ -116,13 +114,9 @@ class ChangeOwnerComponent extends React.Component {
|
||||
className="header_aside-panel"
|
||||
visible={visible}
|
||||
onClose={this.onClose}
|
||||
header={t("ChangeOwner", { fileName })}
|
||||
>
|
||||
<StyledContent>
|
||||
<StyledHeaderContent>
|
||||
<Heading className="sharing_panel-header" size="medium" truncate>
|
||||
{t("ChangeOwner", { fileName })}
|
||||
</Heading>
|
||||
</StyledHeaderContent>
|
||||
<StyledBody>
|
||||
<div className="change-owner_body">
|
||||
<Link
|
||||
|
@ -120,6 +120,7 @@ const ChangeRoomOwner = (props) => {
|
||||
className="header_aside-panel"
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
withoutHeader
|
||||
withoutBodyScroll
|
||||
>
|
||||
<PeopleSelector
|
||||
@ -133,6 +134,7 @@ const ChangeRoomOwner = (props) => {
|
||||
disableSubmitButton={false}
|
||||
withHeader
|
||||
headerProps={{
|
||||
onCloseClick: onClose,
|
||||
onBackClick,
|
||||
withoutBackButton: !showBackButton,
|
||||
headerLabel: t("Files:ChangeTheRoomOwner"),
|
||||
|
@ -28,10 +28,6 @@ import styled, { css } from "styled-components";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
|
||||
const StyledModalDialog = styled(ModalDialog)`
|
||||
.modal-header {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -43,16 +43,6 @@ const StyledHotkeysPanel = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.hotkeys_header {
|
||||
padding: 0 16px;
|
||||
border-bottom: ${(props) => props.theme.filesPanels.sharing.borderBottom};
|
||||
|
||||
.hotkeys_heading {
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.hotkeys_sub-header {
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
|
@ -90,10 +90,8 @@ const HotkeyPanel = ({
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
withoutBodyScroll={true}
|
||||
header={t("Common:Hotkeys")}
|
||||
>
|
||||
<div className="hotkeys_header">
|
||||
<Heading className="hotkeys_heading">{t("Common:Hotkeys")}</Heading>
|
||||
</div>
|
||||
<StyledScrollbar ref={scrollRef}>
|
||||
<Heading className="hotkeys_sub-header">
|
||||
{t("HotkeysNavigation")}
|
||||
|
@ -38,7 +38,6 @@ import { ToggleButton } from "@docspace/shared/components/toggle-button";
|
||||
import { mobile, commonIconsStyles } from "@docspace/shared/utils";
|
||||
import CheckIcon from "PUBLIC_DIR/images/check.edit.react.svg";
|
||||
import CrossIcon from "PUBLIC_DIR/images/cross.edit.react.svg";
|
||||
import CrossIconMobile from "PUBLIC_DIR/images/cross.react.svg";
|
||||
import DeleteIcon from "PUBLIC_DIR/images/mobile.actions.remove.react.svg";
|
||||
import { isMobile, desktop, commonInputStyles } from "@docspace/shared/utils";
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
@ -124,24 +123,15 @@ const ScrollList = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledBlock = styled.div`
|
||||
padding: ${(props) => (props.noPadding ? "0px" : "0 16px")};
|
||||
const StyledExternalLink = styled.div`
|
||||
border-bottom: ${(props) => props.theme.filesPanels.sharing.borderBottom};
|
||||
`;
|
||||
|
||||
StyledBlock.defaultProps = { theme: Base };
|
||||
|
||||
const StyledInviteUserBody = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
const StyledHeading = styled(Heading)`
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
`;
|
||||
|
||||
const StyledSubHeader = styled(Heading)`
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
@ -440,14 +430,6 @@ StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
const StyledDeleteIcon = styled(DeleteIcon)`
|
||||
cursor: pointer;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: auto;
|
||||
`
|
||||
: css`
|
||||
margin-left: auto;
|
||||
`}
|
||||
|
||||
${iconStyles}
|
||||
`;
|
||||
@ -501,25 +483,6 @@ const StyledToggleButton = styled(ToggleButton)`
|
||||
margin-top: -4px;
|
||||
`;
|
||||
|
||||
const StyledControlContainer = styled.div`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
position: absolute;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 450;
|
||||
|
||||
@media ${mobile} {
|
||||
display: flex;
|
||||
|
||||
top: -27px;
|
||||
right: 10px;
|
||||
left: unset;
|
||||
}
|
||||
`;
|
||||
const StyledInviteLanguage = styled.div`
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
@ -574,19 +537,17 @@ const StyledInviteLanguage = styled.div`
|
||||
gap: 2px;
|
||||
}
|
||||
`;
|
||||
const StyledCrossIconMobile = styled(CrossIconMobile)`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
z-index: 455;
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.control.fill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
const ErrorWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
margin-inline-start: auto;
|
||||
`;
|
||||
|
||||
export {
|
||||
StyledBlock,
|
||||
StyledHeading,
|
||||
StyledInvitePanel,
|
||||
StyledRow,
|
||||
StyledSubHeader,
|
||||
@ -608,7 +569,7 @@ export {
|
||||
StyledToggleButton,
|
||||
StyledDescription,
|
||||
StyledInviteLanguage,
|
||||
StyledControlContainer,
|
||||
StyledCrossIconMobile,
|
||||
StyledInviteUserBody,
|
||||
StyledExternalLink,
|
||||
ErrorWrapper,
|
||||
};
|
||||
|
@ -38,20 +38,13 @@ import { DeviceType, EmployeeType } from "@docspace/shared/enums";
|
||||
import { LOADER_TIMEOUT } from "@docspace/shared/constants";
|
||||
|
||||
import { Backdrop } from "@docspace/shared/components/backdrop";
|
||||
import { Aside } from "@docspace/shared/components/aside";
|
||||
import { Aside, AsideHeader } from "@docspace/shared/components/aside";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { Portal } from "@docspace/shared/components/portal";
|
||||
import { isDesktop, isMobile, size } from "@docspace/shared/utils";
|
||||
|
||||
import {
|
||||
StyledBlock,
|
||||
StyledHeading,
|
||||
StyledInvitePanel,
|
||||
StyledButtons,
|
||||
StyledControlContainer,
|
||||
StyledCrossIconMobile,
|
||||
} from "./StyledInvitePanel";
|
||||
import { StyledInvitePanel, StyledButtons } from "./StyledInvitePanel";
|
||||
|
||||
import ItemsList from "./sub-components/ItemsList";
|
||||
import InviteInput from "./sub-components/InviteInput";
|
||||
@ -60,7 +53,7 @@ import { Scrollbar } from "@docspace/shared/components/scrollbar";
|
||||
|
||||
import InfoBar from "./sub-components/InfoBar";
|
||||
import InvitePanelLoader from "./sub-components/InvitePanelLoader";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
|
||||
@ -429,9 +422,6 @@ const InvitePanel = ({
|
||||
|
||||
const invitePanelNode = (
|
||||
<>
|
||||
<StyledBlock>
|
||||
<StyledHeading>{t("Common:InviteUsers")}</StyledHeading>
|
||||
</StyledBlock>
|
||||
{invitePanelIsLoding ? (
|
||||
<InvitePanelLoader />
|
||||
) : (
|
||||
@ -479,9 +469,11 @@ const InvitePanel = ({
|
||||
>
|
||||
{isMobileView ? (
|
||||
<div className="invite_panel" ref={invitePanelRef}>
|
||||
<StyledControlContainer onClick={onClose}>
|
||||
<StyledCrossIconMobile />
|
||||
</StyledControlContainer>
|
||||
<AsideHeader
|
||||
header={t("Common:InviteUsers")}
|
||||
onCloseClick={onClose}
|
||||
/>
|
||||
|
||||
{invitePanelNode}
|
||||
</div>
|
||||
) : (
|
||||
@ -498,6 +490,7 @@ const InvitePanel = ({
|
||||
onClose={onClose}
|
||||
withoutBodyScroll
|
||||
zIndex={310}
|
||||
header={t("Common:InviteUsers")}
|
||||
>
|
||||
{invitePanelNode}
|
||||
</Aside>
|
||||
|
@ -45,12 +45,12 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import AccessSelector from "../../../AccessSelector";
|
||||
import PaidQuotaLimitError from "../../../PaidQuotaLimitError";
|
||||
import {
|
||||
StyledBlock,
|
||||
StyledSubHeader,
|
||||
StyledInviteInput,
|
||||
StyledInviteInputContainer,
|
||||
StyledToggleButton,
|
||||
StyledDescription,
|
||||
StyledExternalLink,
|
||||
} from "../StyledInvitePanel";
|
||||
|
||||
import { getFreeUsersRoleArray, getFreeUsersTypeArray } from "../utils";
|
||||
@ -212,7 +212,7 @@ const ExternalLinks = ({
|
||||
roomId === -1 ? getFreeUsersTypeArray() : getFreeUsersRoleArray();
|
||||
|
||||
return (
|
||||
<StyledBlock noPadding ref={inputsRef}>
|
||||
<StyledExternalLink noPadding ref={inputsRef}>
|
||||
<StyledSubHeader inline>
|
||||
{t("InviteViaLink")}
|
||||
{false && ( //TODO: Change to linksVisible after added link information from backend
|
||||
@ -285,7 +285,7 @@ const ExternalLinks = ({
|
||||
/>
|
||||
</StyledInviteInputContainer>
|
||||
)}
|
||||
</StyledBlock>
|
||||
</StyledExternalLink>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -49,6 +49,7 @@ import {
|
||||
StyledHelpButton,
|
||||
StyledDeleteIcon,
|
||||
StyledInviteUserBody,
|
||||
ErrorWrapper,
|
||||
} from "../StyledInvitePanel";
|
||||
import { filterGroupRoleOptions, filterUserRoleOptions } from "SRC_DIR/helpers";
|
||||
import AccessSelector from "../../../AccessSelector";
|
||||
@ -229,7 +230,7 @@ const Item = ({
|
||||
</StyledInviteUserBody>
|
||||
|
||||
{hasError ? (
|
||||
<>
|
||||
<ErrorWrapper>
|
||||
<StyledHelpButton
|
||||
iconName={InfoEditReactSvgUrl}
|
||||
displayType="auto"
|
||||
@ -244,7 +245,7 @@ const Item = ({
|
||||
size="medium"
|
||||
onClick={removeItem}
|
||||
/>
|
||||
</>
|
||||
</ErrorWrapper>
|
||||
) : (
|
||||
<>
|
||||
{warning && (
|
||||
|
@ -256,39 +256,6 @@ const StyledContent = styled.div`
|
||||
|
||||
StyledContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledHeaderContent = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: -16px;
|
||||
`
|
||||
: css`
|
||||
margin-right: -16px;
|
||||
`}
|
||||
|
||||
border-bottom: ${(props) => props.theme.filesPanels.sharing.borderBottom};
|
||||
|
||||
.files-operations-header,
|
||||
.sharing_panel-header {
|
||||
font-weight: 700;
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
@media ${desktop} {
|
||||
.files-operations-header,
|
||||
.sharing_panel-header {
|
||||
margin: 12px 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledHeaderContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledBody = styled.div`
|
||||
&.files-operations-body {
|
||||
${(props) =>
|
||||
@ -711,13 +678,6 @@ const StyledLink = styled(Link)`
|
||||
|
||||
StyledModalRowContainer.defaultProps = { theme: Base };
|
||||
|
||||
const StyledUploadHeader = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
const StyledUploadBody = styled.div`
|
||||
width: calc(100% + 16px);
|
||||
height: 100%;
|
||||
@ -732,13 +692,11 @@ export {
|
||||
StyledEmbeddingPanel,
|
||||
StyledVersionHistoryPanel,
|
||||
StyledContent,
|
||||
StyledHeaderContent,
|
||||
StyledBody,
|
||||
StyledFooter,
|
||||
StyledLinkRow,
|
||||
StyledModalRowContainer,
|
||||
StyledLink,
|
||||
StyledNewFilesBody,
|
||||
StyledUploadHeader,
|
||||
StyledUploadBody,
|
||||
};
|
||||
|
@ -39,9 +39,10 @@ import {
|
||||
} from "@docspace/shared/components/modal-dialog";
|
||||
import { DialogAsideSkeleton } from "@docspace/shared/skeletons/dialog";
|
||||
|
||||
import { StyledUploadHeader, StyledUploadBody } from "../StyledPanels";
|
||||
import { StyledUploadBody } from "../StyledPanels";
|
||||
import FileList from "./FileList";
|
||||
import withLoader from "../../../HOCs/withLoader";
|
||||
import { AsideHeader } from "@docspace/shared/components/aside";
|
||||
|
||||
const StyledModal = styled(ModalDialog)`
|
||||
.heading {
|
||||
@ -124,34 +125,24 @@ class UploadPanelComponent extends React.Component {
|
||||
? t("UploadAndConvert")
|
||||
: t("Files:Convert");
|
||||
|
||||
const url =
|
||||
uploaded && converted ? ClearReactSvgUrl : ButtonCancelReactSvgUrl;
|
||||
|
||||
const clickEvent =
|
||||
uploaded && converted
|
||||
? this.clearUploadPanel
|
||||
: uploaded
|
||||
? cancelConversion
|
||||
: this.onCancelUpload;
|
||||
|
||||
return (
|
||||
<StyledModal
|
||||
visible={visible}
|
||||
onClose={this.onClose}
|
||||
displayType={ModalDialogType.aside}
|
||||
headerIcons={[{ key: "upload-panel", url, onClick: clickEvent }]}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<StyledUploadHeader>
|
||||
<div>{title}</div>
|
||||
<div>
|
||||
{uploaded && converted ? (
|
||||
<IconButton
|
||||
size={17}
|
||||
iconName={ClearReactSvgUrl}
|
||||
isClickable
|
||||
onClick={this.clearUploadPanel}
|
||||
/>
|
||||
) : (
|
||||
<IconButton
|
||||
size="20"
|
||||
iconName={ButtonCancelReactSvgUrl}
|
||||
isClickable
|
||||
onClick={uploaded ? cancelConversion : this.onCancelUpload}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</StyledUploadHeader>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{title}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<StyledUploadBody>
|
||||
<FileList />
|
||||
|
@ -27,7 +27,6 @@
|
||||
import React from "react";
|
||||
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 { FloatingButton } from "@docspace/shared/components/floating-button";
|
||||
@ -37,13 +36,11 @@ import { withTranslation } from "react-i18next";
|
||||
import {
|
||||
StyledVersionHistoryPanel,
|
||||
StyledContent,
|
||||
StyledHeaderContent,
|
||||
StyledBody,
|
||||
} from "../StyledPanels";
|
||||
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 = () => {
|
||||
@ -85,26 +82,10 @@ class PureVersionHistoryPanel extends React.Component {
|
||||
visible={visible}
|
||||
onClose={this.onClose}
|
||||
withoutBodyScroll
|
||||
isLoading={!versions && !isLoading}
|
||||
header={versions ? versions[0].title : ""}
|
||||
>
|
||||
<StyledContent>
|
||||
<StyledHeaderContent className="version-history-panel-header">
|
||||
{versions && !isLoading ? (
|
||||
<Heading
|
||||
className="version-history-panel-heading"
|
||||
size="medium"
|
||||
truncate
|
||||
>
|
||||
{versions[0].title}
|
||||
</Heading>
|
||||
) : (
|
||||
<ArticleHeaderLoader
|
||||
className="loader-version-history"
|
||||
height="28"
|
||||
width="688"
|
||||
/>
|
||||
)}
|
||||
</StyledHeaderContent>
|
||||
|
||||
<StyledBody className="version-history-panel-body">
|
||||
<SectionBodyContent onClose={this.onClose} />
|
||||
</StyledBody>
|
||||
|
@ -98,6 +98,7 @@ const SortFilter = ({ t, oformsFilter, sortOforms }) => {
|
||||
fillIcon={false}
|
||||
options={[]}
|
||||
selectedOption={{}}
|
||||
manualWidth={"auto"}
|
||||
advancedOptions={
|
||||
<>
|
||||
{sortData?.map((item) => (
|
||||
|
@ -24,14 +24,10 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import CrossReactSvgUrl from "PUBLIC_DIR/images/icons/17/cross.react.svg?url";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import { Tabs } from "@docspace/shared/components/tabs";
|
||||
import {
|
||||
isDesktop as isDesktopUtils,
|
||||
@ -43,6 +39,7 @@ import { StyledInfoPanelHeader } from "./styles/common";
|
||||
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/enums";
|
||||
import { FolderType } from "@docspace/shared/enums";
|
||||
import { AsideHeader } from "@docspace/shared/components/aside";
|
||||
|
||||
const InfoPanelHeaderContent = (props) => {
|
||||
const {
|
||||
@ -194,25 +191,12 @@ const InfoPanelHeaderContent = (props) => {
|
||||
|
||||
return (
|
||||
<StyledInfoPanelHeader isTablet={isTablet} withTabs={withTabs}>
|
||||
<div className="main">
|
||||
<Text className="header-text" fontSize="21px" fontWeight="700">
|
||||
{t("Common:Info")}
|
||||
</Text>
|
||||
|
||||
{!isTablet && (
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
isStroke
|
||||
size="17"
|
||||
onClick={closeInfoPanel}
|
||||
iconName={CrossReactSvgUrl}
|
||||
title={t("Common:InfoPanel")}
|
||||
className="info-panel-toggle"
|
||||
id="info-panel-toggle--close"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<AsideHeader
|
||||
header={t("Common:Info")}
|
||||
onCloseClick={closeInfoPanel}
|
||||
withoutBorder
|
||||
className="header-text"
|
||||
/>
|
||||
|
||||
{withTabs && (
|
||||
<div className="tabs">
|
||||
|
@ -28,11 +28,11 @@ import styled, { css } from "styled-components";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { tablet } from "@docspace/shared/utils";
|
||||
|
||||
const getHeaderHeight = ({ withTabs, isTablet }) => {
|
||||
let res = isTablet ? 53 : 69;
|
||||
if (withTabs) res += 32;
|
||||
return `${res}px`;
|
||||
};
|
||||
// const getHeaderHeight = ({ withTabs, isTablet }) => {
|
||||
// let res = isTablet ? 54 : 70;
|
||||
// if (withTabs) res += 32;
|
||||
// return `${res}px`;
|
||||
// };
|
||||
|
||||
const getMainHeight = ({ isTablet }) => {
|
||||
let res = isTablet ? 52 : 68;
|
||||
@ -43,52 +43,17 @@ const StyledInfoPanelHeader = styled.div`
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
|
||||
height: ${(props) => getHeaderHeight(props)};
|
||||
min-height: ${(props) => getHeaderHeight(props)};
|
||||
@media ${tablet} {
|
||||
height: ${(props) => getHeaderHeight({ ...props, isTablet: true })};
|
||||
min-height: ${(props) => getHeaderHeight({ ...props, isTablet: true })};
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: ${(props) =>
|
||||
props.withTabs ? "none" : `1px solid ${props.theme.infoPanel.borderColor}`};
|
||||
.main {
|
||||
|
||||
.header-text {
|
||||
height: ${(props) => getMainHeight(props)};
|
||||
min-height: ${(props) => getMainHeight(props)};
|
||||
@media ${tablet} {
|
||||
height: ${(props) => getMainHeight({ ...props, isTablet: true })};
|
||||
min-height: ${(props) => getMainHeight({ ...props, isTablet: true })};
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.header-text {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 20px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 20px;
|
||||
`}
|
||||
}
|
||||
}
|
||||
|
||||
.info-panel-toggle-bg {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: 20px;
|
||||
`
|
||||
: css`
|
||||
margin-right: 20px;
|
||||
`}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
@ -25,12 +25,13 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import styled from "styled-components";
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useContext } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import useViewEffect from "SRC_DIR/Hooks/useViewEffect";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { Context } from "@docspace/shared/utils";
|
||||
import { RowContainer } from "@docspace/shared/components/row-container";
|
||||
|
||||
import SimpleFilesRow from "./SimpleFilesRow";
|
||||
@ -62,7 +63,6 @@ StyledRowContainer.defaultProps = { theme: Base };
|
||||
|
||||
const FilesRowContainer = ({
|
||||
filesList,
|
||||
sectionWidth,
|
||||
viewAs,
|
||||
setViewAs,
|
||||
infoPanelVisible,
|
||||
@ -75,6 +75,8 @@ const FilesRowContainer = ({
|
||||
highlightFile,
|
||||
currentDeviceType,
|
||||
}) => {
|
||||
const { sectionWidth } = useContext(Context);
|
||||
|
||||
useViewEffect({
|
||||
view: viewAs,
|
||||
setView: setViewAs,
|
||||
|
@ -28,13 +28,20 @@ import { inject, observer } from "mobx-react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import elementResizeDetectorMaker from "element-resize-detector";
|
||||
import React, { useEffect, useRef, useCallback, useMemo } from "react";
|
||||
import React, {
|
||||
useEffect,
|
||||
useRef,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useContext,
|
||||
} from "react";
|
||||
|
||||
import useViewEffect from "SRC_DIR/Hooks/useViewEffect";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { TableContainer } from "@docspace/shared/components/table";
|
||||
import { TableBody } from "@docspace/shared/components/table";
|
||||
import { Context } from "@docspace/shared/utils";
|
||||
|
||||
import TableRow from "./TableRow";
|
||||
import TableHeader from "./TableHeader";
|
||||
@ -121,7 +128,6 @@ const elementResizeDetector = elementResizeDetectorMaker({
|
||||
|
||||
const Table = ({
|
||||
filesList,
|
||||
sectionWidth,
|
||||
viewAs,
|
||||
setViewAs,
|
||||
setFirsElemChecked,
|
||||
@ -142,6 +148,8 @@ const Table = ({
|
||||
const [tagCount, setTagCount] = React.useState(null);
|
||||
const [hideColumns, setHideColumns] = React.useState(false);
|
||||
|
||||
const { sectionWidth } = useContext(Context);
|
||||
|
||||
const ref = useRef(null);
|
||||
const tagRef = useRef(null);
|
||||
|
||||
|
@ -24,14 +24,17 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useContext } from "react";
|
||||
import styled from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import DragAndDrop from "@docspace/shared/components/drag-and-drop/DragAndDrop";
|
||||
// import { Context } from "@docspace/shared/utils";
|
||||
|
||||
import Tile from "./sub-components/Tile";
|
||||
import FilesTileContent from "./FilesTileContent";
|
||||
import { FileTileContext } from "./FileTile.provider";
|
||||
|
||||
import withFileActions from "../../../../../HOCs/withFileActions";
|
||||
import withQuickButtons from "../../../../../HOCs/withQuickButtons";
|
||||
@ -45,7 +48,6 @@ const StyledDragAndDrop = styled(DragAndDrop)`
|
||||
const FileTile = (props) => {
|
||||
const {
|
||||
item,
|
||||
sectionWidth,
|
||||
dragging,
|
||||
onContentFileSelect,
|
||||
fileContextClick,
|
||||
@ -70,12 +72,12 @@ const FileTile = (props) => {
|
||||
t,
|
||||
getContextModel,
|
||||
onHideContextMenu,
|
||||
thumbSize,
|
||||
// thumbSize,
|
||||
setSelection,
|
||||
id,
|
||||
onSelectTag,
|
||||
onSelectOption,
|
||||
columnCount,
|
||||
// columnCount,
|
||||
isRooms,
|
||||
withCtrlSelect,
|
||||
withShiftSelect,
|
||||
@ -86,6 +88,10 @@ const FileTile = (props) => {
|
||||
badgeUrl,
|
||||
} = props;
|
||||
|
||||
// const { sectionWidth } = useContext(Context);
|
||||
|
||||
const { columnCount, thumbSize } = useContext(FileTileContext);
|
||||
|
||||
const temporaryExtension =
|
||||
item.id === -1 ? `.${item.fileExst}` : item.fileExst;
|
||||
|
||||
@ -145,7 +151,7 @@ const FileTile = (props) => {
|
||||
: thumbnailUrl
|
||||
}
|
||||
element={element}
|
||||
sectionWidth={sectionWidth}
|
||||
// sectionWidth={sectionWidth}
|
||||
contentElement={quickButtonsComponent}
|
||||
onSelect={onContentFileSelect}
|
||||
tileContextClick={fileContextClick}
|
||||
@ -177,7 +183,7 @@ const FileTile = (props) => {
|
||||
>
|
||||
<FilesTileContent
|
||||
item={item}
|
||||
sectionWidth={sectionWidth}
|
||||
// sectionWidth={sectionWidth}
|
||||
onFilesClick={onFilesClick}
|
||||
/>
|
||||
{badgesComponent}
|
||||
|
@ -0,0 +1,28 @@
|
||||
import { createContext, PropsWithChildren, useMemo } from "react";
|
||||
|
||||
type FileTileContextType = {
|
||||
thumbSize: string;
|
||||
columnCount: null | number;
|
||||
};
|
||||
|
||||
export const FileTileContext = createContext<FileTileContextType>({
|
||||
columnCount: null,
|
||||
thumbSize: "",
|
||||
});
|
||||
|
||||
export const FileTileProvider = ({
|
||||
children,
|
||||
columnCount,
|
||||
thumbSize,
|
||||
}: PropsWithChildren<FileTileContextType>) => {
|
||||
const value = useMemo(
|
||||
() => ({ columnCount, thumbSize }),
|
||||
[thumbSize, columnCount],
|
||||
);
|
||||
|
||||
return (
|
||||
<FileTileContext.Provider value={value}>
|
||||
{children}
|
||||
</FileTileContext.Provider>
|
||||
);
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
import elementResizeDetectorMaker from "element-resize-detector";
|
||||
|
||||
export const getThumbSize = (width: number): string => {
|
||||
let imgWidth = 216;
|
||||
|
||||
if (width >= 240 && width < 264) {
|
||||
imgWidth = 240;
|
||||
} else if (width >= 264 && width < 288) {
|
||||
imgWidth = 264;
|
||||
} else if (width >= 288 && width < 312) {
|
||||
imgWidth = 288;
|
||||
} else if (width >= 312 && width < 336) {
|
||||
imgWidth = 312;
|
||||
} else if (width >= 336 && width < 360) {
|
||||
imgWidth = 336;
|
||||
} else if (width >= 360 && width < 400) {
|
||||
imgWidth = 360;
|
||||
} else if (width >= 400 && width < 440) {
|
||||
imgWidth = 400;
|
||||
} else if (width >= 440) {
|
||||
imgWidth = 440;
|
||||
}
|
||||
|
||||
return `${imgWidth}x156`;
|
||||
};
|
||||
|
||||
export const elementResizeDetector = elementResizeDetectorMaker({
|
||||
strategy: "scroll",
|
||||
callOnAdd: false,
|
||||
});
|
@ -30,45 +30,21 @@ import React, {
|
||||
useCallback,
|
||||
useState,
|
||||
useMemo,
|
||||
useContext,
|
||||
} from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import elementResizeDetectorMaker from "element-resize-detector";
|
||||
import TileContainer from "./sub-components/TileContainer";
|
||||
|
||||
import { Context } from "@docspace/shared/utils";
|
||||
|
||||
import FileTile from "./FileTile";
|
||||
import { FileTileProvider } from "./FileTile.provider";
|
||||
import { elementResizeDetector, getThumbSize } from "./FileTile.utils";
|
||||
|
||||
const getThumbSize = (width) => {
|
||||
let imgWidth = 216;
|
||||
|
||||
if (width >= 240 && width < 264) {
|
||||
imgWidth = 240;
|
||||
} else if (width >= 264 && width < 288) {
|
||||
imgWidth = 264;
|
||||
} else if (width >= 288 && width < 312) {
|
||||
imgWidth = 288;
|
||||
} else if (width >= 312 && width < 336) {
|
||||
imgWidth = 312;
|
||||
} else if (width >= 336 && width < 360) {
|
||||
imgWidth = 336;
|
||||
} else if (width >= 360 && width < 400) {
|
||||
imgWidth = 360;
|
||||
} else if (width >= 400 && width < 440) {
|
||||
imgWidth = 400;
|
||||
} else if (width >= 440) {
|
||||
imgWidth = 440;
|
||||
}
|
||||
|
||||
return `${imgWidth}x156`;
|
||||
};
|
||||
|
||||
const elementResizeDetector = elementResizeDetectorMaker({
|
||||
strategy: "scroll",
|
||||
callOnAdd: false,
|
||||
});
|
||||
import TileContainer from "./sub-components/TileContainer";
|
||||
|
||||
const FilesTileContainer = ({
|
||||
filesList,
|
||||
t,
|
||||
sectionWidth,
|
||||
withPaging,
|
||||
thumbnails1280x720,
|
||||
}) => {
|
||||
@ -78,6 +54,8 @@ const FilesTileContainer = ({
|
||||
const [thumbSize, setThumbSize] = useState("");
|
||||
const [columnCount, setColumnCount] = useState(null);
|
||||
|
||||
const { sectionWidth } = useContext(Context);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
isMountedRef.current = false;
|
||||
@ -139,10 +117,7 @@ const FilesTileContainer = ({
|
||||
}
|
||||
item={item}
|
||||
itemIndex={index}
|
||||
sectionWidth={sectionWidth}
|
||||
selectableRef={onSetTileRef}
|
||||
thumbSize={thumbSize}
|
||||
columnCount={columnCount}
|
||||
withRef={true}
|
||||
/>
|
||||
) : (
|
||||
@ -153,24 +128,23 @@ const FilesTileContainer = ({
|
||||
}
|
||||
item={item}
|
||||
itemIndex={index}
|
||||
sectionWidth={sectionWidth}
|
||||
thumbSize={thumbSize}
|
||||
columnCount={columnCount}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}, [filesList, sectionWidth, onSetTileRef, thumbSize, columnCount]);
|
||||
}, [filesList, onSetTileRef, sectionWidth]);
|
||||
|
||||
return (
|
||||
<TileContainer
|
||||
className="tile-container"
|
||||
draggable
|
||||
useReactWindow={!withPaging}
|
||||
headingFolders={t("Translations:Folders")}
|
||||
headingFiles={t("Translations:Files")}
|
||||
>
|
||||
{filesListNode}
|
||||
</TileContainer>
|
||||
<FileTileProvider columnCount={columnCount} thumbSize={thumbSize}>
|
||||
<TileContainer
|
||||
className="tile-container"
|
||||
draggable
|
||||
useReactWindow={!withPaging}
|
||||
headingFolders={t("Translations:Folders")}
|
||||
headingFiles={t("Translations:Files")}
|
||||
>
|
||||
{filesListNode}
|
||||
</TileContainer>
|
||||
</FileTileProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -26,9 +26,8 @@
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
import { observer, inject } from "mobx-react";
|
||||
|
||||
import FilesRowContainer from "./RowsView/FilesRowContainer";
|
||||
import FilesTileContainer from "./TilesView/FilesTileContainer";
|
||||
import EmptyContainer from "../../../../components/EmptyContainer";
|
||||
@ -37,7 +36,6 @@ import TableView from "./TableView/TableContainer";
|
||||
import withHotkeys from "../../../../HOCs/withHotkeys";
|
||||
import {
|
||||
clearEdgeScrollingTimer,
|
||||
Consumer,
|
||||
isMobile,
|
||||
isTablet,
|
||||
onEdgeScrolling,
|
||||
@ -307,36 +305,18 @@ const SectionBodyContent = (props) => {
|
||||
|
||||
if (isEmptyFilesList && movingInProgress) return <></>;
|
||||
|
||||
const showEmptyPage = isEmptyFilesList;
|
||||
if (isEmptyFilesList) return <EmptyContainer isEmptyPage={isEmptyPage} />;
|
||||
|
||||
return (
|
||||
<Consumer>
|
||||
{(context) =>
|
||||
showEmptyPage ? (
|
||||
<>
|
||||
<EmptyContainer
|
||||
sectionWidth={context.sectionWidth}
|
||||
isEmptyPage={isEmptyPage}
|
||||
/>
|
||||
</>
|
||||
) : viewAs === "tile" ? (
|
||||
<>
|
||||
<FilesTileContainer sectionWidth={context.sectionWidth} t={t} />
|
||||
</>
|
||||
) : viewAs === "table" ? (
|
||||
<>
|
||||
<TableView sectionWidth={context.sectionWidth} tReady={tReady} />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FilesRowContainer
|
||||
sectionWidth={context.sectionWidth}
|
||||
tReady={tReady}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</Consumer>
|
||||
<>
|
||||
{viewAs === "tile" ? (
|
||||
<FilesTileContainer t={t} />
|
||||
) : viewAs === "table" ? (
|
||||
<TableView tReady={tReady} />
|
||||
) : (
|
||||
<FilesRowContainer tReady={tReady} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,7 @@ const DataImport = ({
|
||||
getMigrationStatus,
|
||||
isMigrationInit,
|
||||
setIsMigrationInit,
|
||||
tReady,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -109,10 +110,13 @@ const DataImport = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("DataImport"));
|
||||
handleMigrationCheck();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (tReady) setDocumentTitle(t("DataImport"));
|
||||
}, [tReady]);
|
||||
|
||||
const redirectToWorkspace = (title) => {
|
||||
switch (title) {
|
||||
case "GoogleWorkspace":
|
||||
|
@ -66,7 +66,7 @@ const { EveryDayType, EveryWeekType, EveryMonthType } = AutoBackupPeriod;
|
||||
class AutomaticBackup extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { t, language } = props;
|
||||
const { t, tReady, language } = props;
|
||||
moment.locale(language);
|
||||
|
||||
this.state = {
|
||||
@ -96,7 +96,7 @@ class AutomaticBackup extends React.PureComponent {
|
||||
this.maxNumberCopiesArray = [];
|
||||
this.weekdaysLabelArray = [];
|
||||
|
||||
setDocumentTitle(t("AutoBackup"));
|
||||
if (tReady) setDocumentTitle(t("AutoBackup"));
|
||||
|
||||
this.getTime();
|
||||
this.getMonthNumbers();
|
||||
@ -170,6 +170,12 @@ class AutomaticBackup extends React.PureComponent {
|
||||
this.setBasicSettings();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { t, tReady } = this.props;
|
||||
if (prevProps.tReady !== tReady && tReady)
|
||||
setDocumentTitle(t("AutoBackup"));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { clearProgressInterval } = this.props;
|
||||
clearTimeout(this.timerId);
|
||||
|
@ -70,9 +70,9 @@ class ManualBackup extends React.Component {
|
||||
|
||||
this.timerId = null;
|
||||
|
||||
const { t } = props;
|
||||
const { t, tReady } = props;
|
||||
|
||||
setDocumentTitle(t("DataBackup"));
|
||||
if (tReady) setDocumentTitle(t("DataBackup"));
|
||||
|
||||
this.state = {
|
||||
selectedFolder: "",
|
||||
@ -150,6 +150,13 @@ class ManualBackup extends React.Component {
|
||||
this.setBasicSettings();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { t, tReady } = this.props;
|
||||
|
||||
if (prevProps.tReady !== tReady && tReady)
|
||||
setDocumentTitle(t("DataBackup"));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { clearProgressInterval } = this.props;
|
||||
clearTimeout(this.timerId);
|
||||
|
@ -230,11 +230,7 @@ const BackupListModalDialog = (props) => {
|
||||
onClose={onModalClose}
|
||||
withFooterBorder
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text fontSize="21px" fontWeight={700}>
|
||||
{t("BackupList")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("BackupList")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<StyledBackupList
|
||||
isCopyingToLocal={isCopyingToLocal}
|
||||
|
@ -118,7 +118,7 @@ const PresetsContainer = styled.div`
|
||||
`;
|
||||
|
||||
const PortalIntegration = (props) => {
|
||||
const { t, currentColorScheme, sdkLink, theme } = props;
|
||||
const { t, currentColorScheme, sdkLink, theme, tReady } = props;
|
||||
|
||||
const isSmall = useRef(
|
||||
(() => {
|
||||
@ -130,8 +130,6 @@ const PortalIntegration = (props) => {
|
||||
|
||||
const [isFlex, setIsFlex] = useState(isSmall.current);
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const navigateToPortal = () => navigate("docspace");
|
||||
@ -191,6 +189,10 @@ const PortalIntegration = (props) => {
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (tReady) setDocumentTitle(t("JavascriptSdk"));
|
||||
}, [tReady]);
|
||||
|
||||
const onResize = (entries) => {
|
||||
const belowThreshold = entries[0].contentRect.width <= 600;
|
||||
if (belowThreshold !== isSmall.current) {
|
||||
|
@ -47,11 +47,15 @@ const PluginSDK = ({
|
||||
isEmptyList,
|
||||
theme,
|
||||
}) => {
|
||||
const { t } = useTranslation(["WebPlugins", "VersionHistory", "Common"]);
|
||||
const { t, ready } = useTranslation([
|
||||
"WebPlugins",
|
||||
"VersionHistory",
|
||||
"Common",
|
||||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setDocumentTitle(t("WebPlugins:PluginSDK"));
|
||||
}, []);
|
||||
if (ready) setDocumentTitle(t("WebPlugins:PluginSDK"));
|
||||
}, [ready]);
|
||||
|
||||
const isMobile = currentDeviceType === "mobile";
|
||||
|
||||
|
@ -57,8 +57,6 @@ const SMTPSettings = (props) => {
|
||||
setIsInit(true);
|
||||
};
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Settings:SMTPSettings"));
|
||||
|
||||
timerId = setTimeout(() => {
|
||||
setIsLoading(true);
|
||||
}, 400);
|
||||
@ -71,6 +69,10 @@ const SMTPSettings = (props) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (ready) setDocumentTitle(t("Settings:SMTPSettings"));
|
||||
}, [ready]);
|
||||
|
||||
const isLoadingContent = isLoading || !ready;
|
||||
|
||||
if (!isLoading && !isInit) return <></>;
|
||||
|
@ -55,14 +55,17 @@ const SingleSignOn = (props) => {
|
||||
isInit,
|
||||
currentDeviceType,
|
||||
} = props;
|
||||
const { t } = useTranslation(["SingleSignOn", "Settings"]);
|
||||
const { t, ready } = useTranslation(["SingleSignOn", "Settings"]);
|
||||
const isMobileView = currentDeviceType === DeviceType.mobile;
|
||||
|
||||
useEffect(() => {
|
||||
isSSOAvailable && !isInit && init();
|
||||
setDocumentTitle(t("Settings:SingleSignOn"));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (ready) setDocumentTitle(t("Settings:SingleSignOn"));
|
||||
}, [ready]);
|
||||
|
||||
if (!isInit && !isMobileView && isSSOAvailable) return <SSOLoader />;
|
||||
|
||||
return (
|
||||
|
@ -111,9 +111,9 @@ const RootContainer = styled(Box)`
|
||||
class ThirdPartyServices extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { t } = props;
|
||||
const { t, tReady } = props;
|
||||
|
||||
setDocumentTitle(`${t("ThirdPartyAuthorization")}`);
|
||||
if (tReady) setDocumentTitle(`${t("ThirdPartyAuthorization")}`);
|
||||
|
||||
this.state = {
|
||||
dialogVisible: false,
|
||||
@ -135,6 +135,12 @@ class ThirdPartyServices extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { t, tReady } = this.props;
|
||||
if (prevProps.tReady !== tReady && tReady)
|
||||
setDocumentTitle(t("ThirdPartyAuthorization"));
|
||||
}
|
||||
|
||||
onChangeLoading = (status) => {
|
||||
this.setState({
|
||||
isLoading: status,
|
||||
|
@ -30,7 +30,9 @@ import ImageReactSvgUrl from "PUBLIC_DIR/images/image.react.svg?url";
|
||||
import CatalogTrashReactSvgUrl from "PUBLIC_DIR/images/catalog.trash.react.svg?url";
|
||||
import ArrowPathReactSvgUrl from "PUBLIC_DIR/images/arrow.path.react.svg?url";
|
||||
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { inject, observer } from "mobx-react";
|
||||
@ -39,6 +41,7 @@ import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { ContextMenuButton } from "@docspace/shared/components/context-menu-button";
|
||||
import Headline from "@docspace/shared/components/headline/Headline";
|
||||
import { SectionHeaderSkeleton } from "@docspace/shared/skeletons/sections";
|
||||
import { checkDialogsOpen } from "@docspace/shared/utils/checkDialogsOpen";
|
||||
import { DeleteSelfProfileDialog } from "SRC_DIR/components/dialogs";
|
||||
import { DeleteOwnerProfileDialog } from "SRC_DIR/components/dialogs";
|
||||
|
||||
@ -72,6 +75,7 @@ const Header = (props) => {
|
||||
showProfileLoader,
|
||||
setIsLoading,
|
||||
userId,
|
||||
enabledHotkeys,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -152,6 +156,11 @@ const Header = (props) => {
|
||||
// setFilter(filter);
|
||||
};
|
||||
|
||||
useHotkeys("Backspace", onClickBack, {
|
||||
filter: () => !checkDialogsOpen() && enabledHotkeys,
|
||||
filterPreventDefault: false,
|
||||
});
|
||||
|
||||
if (showProfileLoader) return <SectionHeaderSkeleton />;
|
||||
|
||||
return (
|
||||
@ -219,6 +228,8 @@ export default inject(
|
||||
peopleStore,
|
||||
clientLoadingStore,
|
||||
profileActionsStore,
|
||||
filesStore,
|
||||
mediaViewerDataStore,
|
||||
}) => {
|
||||
const { isAdmin } = authStore;
|
||||
|
||||
@ -234,6 +245,9 @@ export default inject(
|
||||
|
||||
const { profileClicked } = profileActionsStore;
|
||||
|
||||
const { enabledHotkeys } = filesStore;
|
||||
const { visible: mediaViewerIsVisible } = mediaViewerDataStore;
|
||||
|
||||
const { setChangePasswordVisible, setChangeAvatarVisible } =
|
||||
targetUserStore;
|
||||
|
||||
@ -258,6 +272,8 @@ export default inject(
|
||||
|
||||
showProfileLoader,
|
||||
profileClicked,
|
||||
enabledHotkeys:
|
||||
enabledHotkeys && !mediaViewerIsVisible && !showProfileLoader,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -262,7 +262,10 @@ const Sdk = ({
|
||||
: {};
|
||||
|
||||
const headerProps = frameConfig?.showSelectorHeader
|
||||
? { withHeader: true, headerProps: { headerLabel: "" } }
|
||||
? {
|
||||
withHeader: true,
|
||||
headerProps: { headerLabel: "", isCloseable: false },
|
||||
}
|
||||
: {};
|
||||
|
||||
component = (
|
||||
@ -301,6 +304,7 @@ const Sdk = ({
|
||||
currentFolderId={frameConfig?.id}
|
||||
openRoot={selectorOpenRoot}
|
||||
descriptionText={formatsDescription[frameConfig?.filterParam] || ""}
|
||||
headerProps={{ isCloseable: false }}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
@ -692,7 +692,7 @@ class HotkeyStore {
|
||||
|
||||
const files = await getFilesFromEvent(event);
|
||||
|
||||
createFoldersTree(files, uploadToFolder).then((f) => {
|
||||
createFoldersTree(files).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
};
|
||||
|
@ -25,13 +25,19 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { permanentRedirect, redirect } from "next/navigation";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import { getBaseUrl } from "@docspace/shared/utils/next-ssr-helper";
|
||||
import { EditorConfigErrorType } from "@docspace/shared/enums";
|
||||
|
||||
import { createFile, fileCopyAs, getEditorUrl } from "@/utils/actions";
|
||||
import CreateFileError from "@/components/CreateFileError";
|
||||
import Editor from "@/components/Editor";
|
||||
import { EditorConfigErrorType } from "@docspace/shared/enums";
|
||||
|
||||
const Editor = dynamic(() => import("@/components/Editor"), {
|
||||
ssr: false,
|
||||
});
|
||||
const CreateFileError = dynamic(() => import("@/components/CreateFileError"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
type TSearchParams = {
|
||||
parentId: string;
|
||||
|
@ -55,18 +55,14 @@ export default async function RootLayout({
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const startDate = new Date();
|
||||
const [user, settings, colorTheme] = await Promise.all([
|
||||
getUser(),
|
||||
getSettings(),
|
||||
getColorTheme(),
|
||||
]);
|
||||
const timer = new Date().getTime() - startDate.getTime();
|
||||
|
||||
if (settings === "access-restricted") redirect(`${getBaseUrl()}/${settings}`);
|
||||
|
||||
const api_host = process.env.API_HOST?.trim();
|
||||
|
||||
return (
|
||||
<html lang="en" translate="no">
|
||||
<head>
|
||||
@ -82,11 +78,7 @@ export default async function RootLayout({
|
||||
</head>
|
||||
<body>
|
||||
<StyledComponentsRegistry>
|
||||
<Providers
|
||||
contextData={{ user, settings, systemTheme, colorTheme }}
|
||||
api_host={api_host}
|
||||
timer={timer}
|
||||
>
|
||||
<Providers contextData={{ user, settings, systemTheme, colorTheme }}>
|
||||
{children}
|
||||
</Providers>
|
||||
</StyledComponentsRegistry>
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import { headers } from "next/headers";
|
||||
import Script from "next/script";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import { getSelectorsByUserAgent } from "react-device-detect";
|
||||
|
||||
@ -34,7 +35,10 @@ import { ValidationStatus } from "@docspace/shared/enums";
|
||||
import { getData, validatePublicRoomKey } from "@/utils/actions";
|
||||
import { RootPageProps } from "@/types";
|
||||
import Root from "@/components/Root";
|
||||
import FilePassword from "@/components/file-password";
|
||||
|
||||
const FilePassword = dynamic(() => import("@/components/file-password"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const initialSearchParams: RootPageProps["searchParams"] = {
|
||||
fileId: undefined,
|
||||
|
@ -27,7 +27,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { DocumentEditor } from "@onlyoffice/document-editor-react";
|
||||
@ -51,7 +51,6 @@ import {
|
||||
} from "@/utils/events";
|
||||
import useInit from "@/hooks/useInit";
|
||||
import useEditorEvents from "@/hooks/useEditorEvents";
|
||||
import useFilesSettings from "@/hooks/useFilesSettings";
|
||||
|
||||
type IConfigType = IConfig & {
|
||||
events?: {
|
||||
@ -77,6 +76,8 @@ const Editor = ({
|
||||
errorMessage,
|
||||
isSkipError,
|
||||
|
||||
filesSettings,
|
||||
|
||||
onDownloadAs,
|
||||
onSDKRequestSharingSettings,
|
||||
onSDKRequestSaveAs,
|
||||
@ -88,9 +89,7 @@ const Editor = ({
|
||||
}: EditorProps) => {
|
||||
const { t, i18n } = useTranslation(["Common", "Editor", "DeepLink"]);
|
||||
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const { filesSettings } = useFilesSettings({});
|
||||
|
||||
const openOnNewPage = IS_ZOOM ? false : !filesSettings?.openEditorInSameTab;
|
||||
|
||||
|
@ -9,7 +9,6 @@ import type { TFirebaseSettings } from "@docspace/shared/api/settings/types";
|
||||
import useI18N from "@/hooks/useI18N";
|
||||
import useTheme from "@/hooks/useTheme";
|
||||
import useDeviceType from "@/hooks/useDeviceType";
|
||||
import useWhiteLabel from "@/hooks/useWhiteLabel";
|
||||
|
||||
import pkg from "../../../package.json";
|
||||
|
||||
@ -18,7 +17,7 @@ import { ErrorProps } from "./Error.types";
|
||||
const Error = ({ settings, user, error }: ErrorProps) => {
|
||||
const { i18n } = useI18N({ settings, user });
|
||||
const { currentDeviceType } = useDeviceType();
|
||||
const { logoUrls } = useWhiteLabel();
|
||||
|
||||
const { theme } = useTheme({ user });
|
||||
|
||||
const firebaseHelper = useMemo(() => {
|
||||
@ -32,7 +31,6 @@ const Error = ({ settings, user, error }: ErrorProps) => {
|
||||
errorLog={error}
|
||||
version={pkg.version}
|
||||
user={user ?? ({} as TUser)}
|
||||
whiteLabelLogoUrls={logoUrls}
|
||||
firebaseHelper={firebaseHelper}
|
||||
currentDeviceType={currentDeviceType}
|
||||
/>
|
||||
|
@ -25,15 +25,21 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
"use client";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import ErrorContainer from "@docspace/shared/components/error-container/ErrorContainer";
|
||||
const ErrorContainer = dynamic(
|
||||
() => import("@docspace/shared/components/error-container/ErrorContainer"),
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
|
||||
import { TResponse } from "@/types";
|
||||
import useError from "@/hooks/useError";
|
||||
|
||||
import useError from "@/hooks/useError";
|
||||
import useRootInit from "@/hooks/useRootInit";
|
||||
import useDeepLink from "@/hooks/useDeepLink";
|
||||
import useSelectFileDialog from "@/hooks/useSelectFileDialog";
|
||||
@ -44,14 +50,31 @@ import useFilesSettings from "@/hooks/useFilesSettings";
|
||||
import useUpdateSearchParamId from "@/hooks/useUpdateSearchParamId";
|
||||
import useStartFillingSelectDialog from "@/hooks/useStartFillingSelectDialog";
|
||||
|
||||
import DeepLink from "./deep-link";
|
||||
import Editor from "./Editor";
|
||||
import SelectFileDialog from "./SelectFileDialog";
|
||||
import SelectFolderDialog from "./SelectFolderDialog";
|
||||
import SharingDialog from "./ShareDialog";
|
||||
|
||||
const DeepLink = dynamic(() => import("./deep-link"), {
|
||||
ssr: false,
|
||||
});
|
||||
const SelectFileDialog = dynamic(() => import("./SelectFileDialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
const SelectFolderDialog = dynamic(() => import("./SelectFolderDialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
const SharingDialog = dynamic(() => import("./ShareDialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
const StartFillingSelectorDialog = dynamic(
|
||||
() => import("./StartFillingSelectDialog"),
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
const ConflictResolveDialog = dynamic(() => import("./ConflictResolveDialog"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
import { calculateAsideHeight } from "@/utils";
|
||||
import StartFillingSelectorDialog from "./StartFillingSelectDialog";
|
||||
import ConflictResolveDialog from "./ConflictResolveDialog";
|
||||
|
||||
const Root = ({
|
||||
settings,
|
||||
@ -64,7 +87,6 @@ const Root = ({
|
||||
doc,
|
||||
fileId,
|
||||
hash,
|
||||
timer,
|
||||
}: TResponse) => {
|
||||
const editorRef = React.useRef<null | HTMLElement>(null);
|
||||
|
||||
@ -81,11 +103,6 @@ const Root = ({
|
||||
|
||||
const { t } = useTranslation(["Editor", "Common"]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("editor timer: ", timer);
|
||||
console.log("openEdit timer: ", config?.timer);
|
||||
}, [config?.timer, timer]);
|
||||
|
||||
useRootInit({
|
||||
documentType: config?.documentType,
|
||||
});
|
||||
@ -214,6 +231,7 @@ const Root = ({
|
||||
errorMessage={error?.message}
|
||||
isSkipError={!!isSkipError}
|
||||
onDownloadAs={onDownloadAs}
|
||||
filesSettings={filesSettings}
|
||||
onSDKRequestSharingSettings={onSDKRequestSharingSettings}
|
||||
onSDKRequestSaveAs={onSDKRequestSaveAs}
|
||||
onSDKRequestInsertImage={onSDKRequestInsertImage}
|
||||
|
@ -37,7 +37,7 @@ const Scripts = () => {
|
||||
<>
|
||||
<Script
|
||||
id="browser-detector"
|
||||
strategy="beforeInteractive"
|
||||
// strategy="beforeInteractive"
|
||||
src={`/static/scripts/browserDetector.js?hash=${runtime?.checksums?.["browserDetector.js"] ?? hashDate}`}
|
||||
/>
|
||||
|
||||
|
@ -178,7 +178,7 @@ const FilePassword = ({ shareKey, title, entryTitle }: FilePasswordProps) => {
|
||||
id="password"
|
||||
inputName="password"
|
||||
placeholder={t("Common:Password")}
|
||||
type={InputType.password}
|
||||
inputType={InputType.password}
|
||||
inputValue={password}
|
||||
hasError={!!errorMessage}
|
||||
size={InputSize.large}
|
||||
|
@ -30,28 +30,21 @@ import { getSettingsFiles } from "@docspace/shared/api/files";
|
||||
import { TFilesSettings } from "@docspace/shared/api/files/types";
|
||||
|
||||
const useFilesSettings = ({}) => {
|
||||
const [settings, setSettings] = React.useState({} as TFilesSettings);
|
||||
|
||||
const requestRunning = React.useRef(false);
|
||||
|
||||
const initSettings = React.useCallback(async () => {
|
||||
if (requestRunning.current) return;
|
||||
|
||||
requestRunning.current = true;
|
||||
|
||||
const res = await getSettingsFiles();
|
||||
|
||||
setSettings(res);
|
||||
requestRunning.current = false;
|
||||
}, []);
|
||||
const [settings, setSettings] = React.useState<TFilesSettings>(
|
||||
{} as TFilesSettings,
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (settings.extsArchive) return;
|
||||
const initSettings = async () => {
|
||||
const res = await getSettingsFiles();
|
||||
|
||||
setSettings(res);
|
||||
};
|
||||
|
||||
initSettings();
|
||||
}, [initSettings, settings.extsArchive]);
|
||||
}, []);
|
||||
|
||||
return { filesSettings: settings };
|
||||
};
|
||||
|
||||
export default useFilesSettings;
|
||||
|
||||
|
@ -95,7 +95,7 @@ const useSocketHelper = ({ socketUrl, user }: UseSocketHelperProps) => {
|
||||
});
|
||||
|
||||
setSocketHelper(socketIOHelper);
|
||||
}, [socketHelper, socketUrl]);
|
||||
}, [socketHelper, socketUrl, user?.id, user?.loginEventId]);
|
||||
|
||||
return { socketHelper };
|
||||
};
|
||||
|
@ -90,17 +90,17 @@ const useTheme = ({
|
||||
const isRequestRunning = React.useRef(false);
|
||||
|
||||
const getCurrentColorTheme = React.useCallback(async () => {
|
||||
if (isRequestRunning.current) return;
|
||||
if (isRequestRunning.current || colorTheme) return;
|
||||
isRequestRunning.current = true;
|
||||
const colorThemes = await getAppearanceTheme();
|
||||
|
||||
const colorTheme = colorThemes.themes.find(
|
||||
const curColorTheme = colorThemes.themes.find(
|
||||
(t) => t.id === colorThemes.selected,
|
||||
);
|
||||
|
||||
isRequestRunning.current = false;
|
||||
if (colorTheme) setCurrentColorTheme(colorTheme);
|
||||
}, []);
|
||||
if (curColorTheme) setCurrentColorTheme(curColorTheme);
|
||||
}, [colorTheme]);
|
||||
|
||||
const getUserTheme = React.useCallback(() => {
|
||||
const SYSTEM_THEME = getSystemTheme();
|
||||
|
@ -44,16 +44,9 @@ const TranslationProvider = ({
|
||||
children,
|
||||
settings,
|
||||
user,
|
||||
api_host,
|
||||
timer,
|
||||
}: TTranslationProvider) => {
|
||||
const { i18n } = useI18N({ settings, user });
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log("API_HOST: ", api_host);
|
||||
console.log("LAYOUT API timer:", timer);
|
||||
}, [api_host, timer]);
|
||||
|
||||
return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
|
||||
};
|
||||
|
||||
|
@ -48,9 +48,9 @@ export type TProviders = {
|
||||
contextData: TContextData;
|
||||
};
|
||||
|
||||
const Providers = ({ children, contextData, api_host, timer }: TProviders) => {
|
||||
const Providers = ({ children, contextData }: TProviders) => {
|
||||
return (
|
||||
<TranslationProvider {...contextData} api_host={api_host} timer={timer}>
|
||||
<TranslationProvider {...contextData}>
|
||||
<ThemeProvider {...contextData}>
|
||||
<ErrorProvider {...contextData}>
|
||||
{children}
|
||||
|
@ -229,6 +229,7 @@ export type EditorProps = {
|
||||
isSharingAccess?: boolean;
|
||||
errorMessage?: string;
|
||||
isSkipError?: boolean;
|
||||
filesSettings: TFilesSettings;
|
||||
|
||||
onDownloadAs?: (obj: object) => void;
|
||||
onSDKRequestSharingSettings?: () => void;
|
||||
|
@ -65,8 +65,6 @@ export async function getFillingSession(
|
||||
);
|
||||
|
||||
try {
|
||||
console.log({ request });
|
||||
|
||||
const response = await fetch(request);
|
||||
|
||||
if (response.ok) return await response.json();
|
||||
|
@ -37,6 +37,7 @@ import { Providers } from "@/providers";
|
||||
import { getColorTheme, getSettings } from "@/utils/actions";
|
||||
|
||||
import "../styles/globals.scss";
|
||||
import Scripts from "@/components/Scripts";
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
@ -136,6 +137,7 @@ export default async function RootLayout({
|
||||
{children}
|
||||
</Providers>
|
||||
</StyledComponentsRegistry>
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
@ -118,11 +118,7 @@ const ForgotPasswordModalDialog = ({
|
||||
onClose={onDialogClose}
|
||||
id="forgot-password-modal"
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text isBold fontSize="21px">
|
||||
{t("PasswordRecoveryTitle")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("PasswordRecoveryTitle")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text
|
||||
key="text-body"
|
||||
|
@ -97,11 +97,7 @@ const RegisterModalDialog = ({
|
||||
onClose={onRegisterModalClose}
|
||||
isLarge
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text isBold fontSize="21px">
|
||||
{t("RegisterTitle")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("RegisterTitle")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text key="text-body" isBold={false} fontSize="13px" noSelect>
|
||||
{getDomainsBlock()}
|
||||
|
@ -27,8 +27,6 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import CrossReactSvg from "PUBLIC_DIR/images/cross.react.svg";
|
||||
|
||||
import { Base } from "../../themes";
|
||||
import { MOBILE_FOOTER_HEIGHT } from "../../constants";
|
||||
import { tablet, mobile } from "../../utils";
|
||||
@ -114,66 +112,57 @@ const StyledAside = styled(Container)`
|
||||
`;
|
||||
StyledAside.defaultProps = { theme: Base };
|
||||
|
||||
const StyledControlContainer = styled.div`
|
||||
const StyledHeaderContainer = styled.div<{ withoutBorder?: boolean }>`
|
||||
display: flex;
|
||||
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
position: absolute;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 450;
|
||||
justify-content: space-between;
|
||||
margin: 0 16px;
|
||||
height: 53px;
|
||||
min-height: 53px;
|
||||
position: relative;
|
||||
|
||||
top: 18px;
|
||||
.additional-icons-container {
|
||||
display: flex;
|
||||
margin-inline: 16px 16px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-family: ${(props) => props.theme.fontFamily};
|
||||
color: ${(props) => props.theme.modalDialog.textColor};
|
||||
font-weight: 700;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.arrow-button {
|
||||
margin-inline: 0 12px;
|
||||
|
||||
svg {
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl" && `transform: scaleX(-1);`}
|
||||
}
|
||||
}
|
||||
.close-button {
|
||||
margin-inline: auto 0;
|
||||
min-width: 17px;
|
||||
}
|
||||
.header-component {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" ? `right: -27px;` : `left: -27px;`}
|
||||
|
||||
@media ${tablet} {
|
||||
display: flex;
|
||||
|
||||
top: 18px;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? `right: -27px;`
|
||||
: `left: -27px;`}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
display: flex;
|
||||
|
||||
top: -27px;
|
||||
right: 10px;
|
||||
left: unset;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: unset;
|
||||
left: 10px;
|
||||
`
|
||||
: css`
|
||||
right: 10px;
|
||||
left: unset;
|
||||
`}
|
||||
}
|
||||
!props.withoutBorder &&
|
||||
css`
|
||||
::after {
|
||||
content: "";
|
||||
border-bottom: ${(props) =>
|
||||
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
|
||||
width: calc(100% + 32px);
|
||||
position: absolute;
|
||||
inset-inline-end: -16px;
|
||||
bottom: 0;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
StyledControlContainer.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCrossIcon = styled(CrossReactSvg)`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
z-index: 455;
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.control.fill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
export { StyledAside, StyledControlContainer, StyledCrossIcon };
|
||||
export { StyledAside, StyledHeaderContainer };
|
||||
|
@ -27,13 +27,9 @@
|
||||
import React from "react";
|
||||
|
||||
import { Scrollbar } from "../scrollbar";
|
||||
|
||||
import {
|
||||
StyledAside,
|
||||
StyledControlContainer,
|
||||
StyledCrossIcon,
|
||||
} from "./Aside.styled";
|
||||
import { StyledAside } from "./Aside.styled";
|
||||
import { AsideProps } from "./Aside.types";
|
||||
import { AsideHeader } from "./AsideHeader";
|
||||
|
||||
const AsidePure = (props: AsideProps) => {
|
||||
const {
|
||||
@ -45,6 +41,8 @@ const AsidePure = (props: AsideProps) => {
|
||||
contentPaddingBottom,
|
||||
withoutBodyScroll = false,
|
||||
onClose,
|
||||
withoutHeader = false,
|
||||
...rest
|
||||
} = props;
|
||||
const contentRef = React.useRef<HTMLElement | null>(null);
|
||||
|
||||
@ -58,14 +56,8 @@ const AsidePure = (props: AsideProps) => {
|
||||
forwardRef={contentRef}
|
||||
data-testid="aside"
|
||||
>
|
||||
{/* <CloseButton displayType="aside" zIndex={zIndex}/> */}
|
||||
{!withoutHeader && <AsideHeader onCloseClick={onClose} {...rest} />}
|
||||
{withoutBodyScroll ? children : <Scrollbar>{children}</Scrollbar>}
|
||||
|
||||
{visible && (
|
||||
<StyledControlContainer className="close-button" onClick={onClose}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
)}
|
||||
</StyledAside>
|
||||
);
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
export interface AsideProps {
|
||||
export type AsideProps = AsideHeaderProps & {
|
||||
visible: boolean;
|
||||
scale?: boolean;
|
||||
className?: string;
|
||||
@ -33,8 +33,22 @@ export interface AsideProps {
|
||||
children: React.ReactNode;
|
||||
withoutBodyScroll?: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
withoutHeader: boolean;
|
||||
};
|
||||
export interface AsideHeaderProps {
|
||||
header: string | React.ReactNode;
|
||||
className?: string;
|
||||
id?: string;
|
||||
isBackButton?: boolean;
|
||||
isCloseable?: boolean;
|
||||
headerIcons?: { key: string; url: string; onClick: () => void }[];
|
||||
onBackClick?: () => void;
|
||||
onCloseClick?: () => void;
|
||||
style?: React.CSSProperties;
|
||||
isLoading?: boolean;
|
||||
withoutBorder?: boolean;
|
||||
}
|
||||
export interface StyledAsideProps {
|
||||
visible: boolean;
|
||||
scale?: boolean;
|
||||
|
117
packages/shared/components/aside/AsideHeader.tsx
Normal file
117
packages/shared/components/aside/AsideHeader.tsx
Normal file
@ -0,0 +1,117 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import ArrowPathReactSvgUrl from "PUBLIC_DIR/images/arrow.path.react.svg?url";
|
||||
import CrossReactSvgUrl from "PUBLIC_DIR/images/icons/17/cross.react.svg?url";
|
||||
|
||||
import { IconButton } from "../icon-button";
|
||||
import { Text } from "../text";
|
||||
import { AsideHeaderProps } from "./Aside.types";
|
||||
import { StyledHeaderContainer } from "./Aside.styled";
|
||||
import { RectangleSkeleton } from "../../skeletons/rectangle";
|
||||
import { Heading, HeadingSize } from "../heading";
|
||||
|
||||
const AsideHeader = (props: AsideHeaderProps) => {
|
||||
const {
|
||||
isBackButton = false,
|
||||
onBackClick,
|
||||
onCloseClick,
|
||||
header,
|
||||
headerIcons = [],
|
||||
isCloseable = true,
|
||||
className,
|
||||
id,
|
||||
style,
|
||||
isLoading,
|
||||
withoutBorder = false,
|
||||
} = props;
|
||||
|
||||
const backButtonRender = (
|
||||
<IconButton
|
||||
className="arrow-button"
|
||||
iconName={ArrowPathReactSvgUrl}
|
||||
size={17}
|
||||
onClick={onBackClick}
|
||||
/>
|
||||
);
|
||||
|
||||
const closeIconRender = (
|
||||
<IconButton
|
||||
size={17}
|
||||
className="close-button"
|
||||
iconName={CrossReactSvgUrl}
|
||||
onClick={onCloseClick}
|
||||
isClickable
|
||||
/>
|
||||
);
|
||||
|
||||
// TODO: Heading is temporary until all dialogues are checked
|
||||
|
||||
const mainComponent = (
|
||||
<>
|
||||
{isBackButton && backButtonRender}
|
||||
{typeof header === "string" ? (
|
||||
<Text fontSize="21px" fontWeight={700} className="header-component">
|
||||
{header}
|
||||
</Text>
|
||||
) : (
|
||||
<Heading className="heading" size={HeadingSize.medium} truncate>
|
||||
{header}
|
||||
</Heading>
|
||||
)}
|
||||
{headerIcons.length > 0 && (
|
||||
<div className="additional-icons-container">
|
||||
{headerIcons.map((item) => (
|
||||
<IconButton
|
||||
key={item.key}
|
||||
size={17}
|
||||
className="close-button"
|
||||
iconName={item.url}
|
||||
onClick={item.onClick}
|
||||
isClickable
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{isCloseable && closeIconRender}
|
||||
</>
|
||||
);
|
||||
|
||||
const loaderComponent = <RectangleSkeleton height="28" width="100%" />;
|
||||
|
||||
return (
|
||||
<StyledHeaderContainer
|
||||
id={id}
|
||||
className={className}
|
||||
style={style}
|
||||
withoutBorder={withoutBorder}
|
||||
>
|
||||
{isLoading ? loaderComponent : mainComponent}
|
||||
</StyledHeaderContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export { AsideHeader };
|
@ -25,3 +25,4 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
export { Aside } from "./Aside";
|
||||
export { AsideHeader } from "./AsideHeader";
|
||||
|
@ -73,13 +73,13 @@ const StyledContent = styled.div`
|
||||
`;
|
||||
StyledContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledHeaderContent = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: ${(props) =>
|
||||
props.theme.contextMenuButton.headerContent.borderBottom};
|
||||
`;
|
||||
StyledHeaderContent.defaultProps = { theme: Base };
|
||||
// const StyledHeaderContent = styled.div`
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// border-bottom: ${(props) =>
|
||||
// props.theme.contextMenuButton.headerContent.borderBottom};
|
||||
// `;
|
||||
// StyledHeaderContent.defaultProps = { theme: Base };
|
||||
|
||||
const StyledBodyContent = styled.div`
|
||||
position: relative;
|
||||
@ -101,4 +101,4 @@ const StyledBodyContent = styled.div`
|
||||
`;
|
||||
StyledBodyContent.defaultProps = { theme: Base };
|
||||
|
||||
export { StyledBodyContent, StyledHeaderContent, StyledContent, StyledOuter };
|
||||
export { StyledBodyContent, StyledContent, StyledOuter };
|
||||
|
@ -38,13 +38,11 @@ import { DropDown } from "../drop-down";
|
||||
import { IconButton } from "../icon-button";
|
||||
import { Backdrop } from "../backdrop";
|
||||
import { Aside } from "../aside";
|
||||
import { Heading, HeadingLevel, HeadingSize } from "../heading";
|
||||
import { Link } from "../link";
|
||||
import { ContextMenuModel } from "../context-menu";
|
||||
|
||||
import {
|
||||
StyledBodyContent,
|
||||
StyledHeaderContent,
|
||||
StyledContent,
|
||||
StyledOuter,
|
||||
} from "./ContextMenuButton.styled";
|
||||
@ -297,9 +295,10 @@ const ContextMenuButtonPure = ({
|
||||
scale={false}
|
||||
zIndex={310}
|
||||
onClose={onCloseAction}
|
||||
header={asideHeader}
|
||||
>
|
||||
<StyledContent>
|
||||
<StyledHeaderContent>
|
||||
{/* <StyledHeaderContent>
|
||||
<Heading
|
||||
className="header"
|
||||
size={HeadingSize.medium}
|
||||
@ -308,7 +307,7 @@ const ContextMenuButtonPure = ({
|
||||
>
|
||||
{asideHeader}
|
||||
</Heading>
|
||||
</StyledHeaderContent>
|
||||
</StyledHeaderContent> */}
|
||||
<StyledBodyContent>
|
||||
{state.data.map(
|
||||
(item: ContextMenuModel, index: number) =>
|
||||
|
@ -54,6 +54,7 @@ const StyledDropdown = styled.div<{
|
||||
`}
|
||||
height: fit-content;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
|
||||
${(props) => props.manualWidth && `width: ${props.manualWidth};`}
|
||||
${(props) =>
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import CrossIcon from "PUBLIC_DIR/images/cross.react.svg";
|
||||
|
||||
import { tablet, mobile } from "../../utils";
|
||||
import { Base } from "../../themes";
|
||||
import { TViewAs } from "../../types";
|
||||
@ -218,44 +216,6 @@ const StyledFilterBlock = styled.div`
|
||||
|
||||
StyledFilterBlock.defaultProps = { theme: Base };
|
||||
|
||||
const StyledFilterBlockHeader = styled.div<{ isSelector?: boolean }>`
|
||||
height: 53px;
|
||||
min-height: 53px;
|
||||
|
||||
padding: 0 16px;
|
||||
margin: 0;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
border-bottom: ${(props) =>
|
||||
props.isSelector ? "none" : props.theme.filterInput.filter.border};
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: ${(props) => (props.isSelector ? "start" : "space-between")};
|
||||
|
||||
h1 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.arrow-button {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: 12px;
|
||||
`
|
||||
: css`
|
||||
margin-right: 12px;
|
||||
`}
|
||||
}
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledFilterBlockHeader.defaultProps = { theme: Base };
|
||||
|
||||
const StyledFilterBlockItem = styled.div<{
|
||||
withoutHeader: boolean;
|
||||
isFirst?: boolean;
|
||||
@ -490,59 +450,6 @@ const StyledFilterBlockFooter = styled.div`
|
||||
|
||||
StyledFilterBlockFooter.defaultProps = { theme: Base };
|
||||
|
||||
const StyledControlContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 450;
|
||||
|
||||
top: 14px;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: -34px;
|
||||
`
|
||||
: css`
|
||||
left: -34px;
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
top: -34px;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
left: 10px;
|
||||
right: unset;
|
||||
`
|
||||
: css`
|
||||
right: 10px;
|
||||
|
||||
left: unset;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledControlContainer.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCrossIcon = styled(CrossIcon)`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
z-index: 455;
|
||||
path {
|
||||
fill: ${(props) => props.theme.catalog.control.fill};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
const selectedViewIcon = css`
|
||||
svg {
|
||||
path {
|
||||
@ -712,7 +619,6 @@ StyledSortButton.defaultProps = { theme: Base };
|
||||
export {
|
||||
StyledSortButton,
|
||||
StyledFilterBlock,
|
||||
StyledFilterBlockHeader,
|
||||
StyledFilterBlockItem,
|
||||
StyledFilterBlockItemHeader,
|
||||
StyledFilterBlockItemContent,
|
||||
@ -726,8 +632,6 @@ export {
|
||||
StyledFilterBlockItemCheckboxContainer,
|
||||
StyledFilterBlockItemSeparator,
|
||||
StyledFilterBlockFooter,
|
||||
StyledControlContainer,
|
||||
StyledCrossIcon,
|
||||
};
|
||||
|
||||
export { StyledFilterInput, StyledSearchInput, StyledButton };
|
||||
|
@ -37,19 +37,11 @@ import { FilterBlockLoader } from "../../../skeletons/filter";
|
||||
|
||||
import { Backdrop } from "../../backdrop";
|
||||
import { Button, ButtonSize } from "../../button";
|
||||
import { Heading, HeadingLevel, HeadingSize } from "../../heading";
|
||||
import { IconButton } from "../../icon-button";
|
||||
import { Scrollbar } from "../../scrollbar";
|
||||
import { Portal } from "../../portal";
|
||||
import { TSelectorItem } from "../../selector";
|
||||
|
||||
import {
|
||||
StyledControlContainer,
|
||||
StyledCrossIcon,
|
||||
StyledFilterBlock,
|
||||
StyledFilterBlockFooter,
|
||||
StyledFilterBlockHeader,
|
||||
} from "../Filter.styled";
|
||||
import { StyledFilterBlock, StyledFilterBlockFooter } from "../Filter.styled";
|
||||
|
||||
import { FilterBlockProps, TGroupItem, TItem } from "../Filter.types";
|
||||
import {
|
||||
@ -58,6 +50,7 @@ import {
|
||||
} from "../Filter.utils";
|
||||
|
||||
import FilterBlockItem from "./FilterBlockItem";
|
||||
import { AsideHeader } from "../../aside";
|
||||
|
||||
const FilterBlock = ({
|
||||
selectedFilterValue,
|
||||
@ -496,10 +489,12 @@ const FilterBlock = ({
|
||||
withHeader
|
||||
headerProps={{
|
||||
onBackClick: onArrowClick,
|
||||
onCloseClick: hideFilterBlock,
|
||||
headerLabel: selectorLabel,
|
||||
withoutBackButton: false,
|
||||
}}
|
||||
currentUserId={userId}
|
||||
onClose={hideFilterBlock}
|
||||
/>
|
||||
) : showSelector.type === FilterSelectorTypes.groups ? (
|
||||
<GroupsSelector
|
||||
@ -508,9 +503,11 @@ const FilterBlock = ({
|
||||
withHeader
|
||||
headerProps={{
|
||||
onBackClick: onArrowClick,
|
||||
onCloseClick: hideFilterBlock,
|
||||
headerLabel: selectorLabel,
|
||||
withoutBackButton: false,
|
||||
}}
|
||||
onClose={hideFilterBlock}
|
||||
/>
|
||||
) : (
|
||||
<RoomSelector
|
||||
@ -519,34 +516,33 @@ const FilterBlock = ({
|
||||
withHeader
|
||||
headerProps={{
|
||||
onBackClick: onArrowClick,
|
||||
onCloseClick: hideFilterBlock,
|
||||
headerLabel: selectorLabel,
|
||||
withoutBackButton: false,
|
||||
}}
|
||||
isMultiSelect={false}
|
||||
withSearch
|
||||
disableThirdParty={disableThirdParty}
|
||||
onClose={hideFilterBlock}
|
||||
/>
|
||||
)}
|
||||
<StyledControlContainer onClick={hideFilterBlock}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
</StyledFilterBlock>
|
||||
) : (
|
||||
<StyledFilterBlock>
|
||||
<StyledFilterBlockHeader>
|
||||
<Heading size={HeadingSize.medium} level={HeadingLevel.h1}>
|
||||
{filterHeader}
|
||||
</Heading>
|
||||
{showClearFilterBtn && (
|
||||
<IconButton
|
||||
id="filter_search-options-clear"
|
||||
iconName={ClearReactSvgUrl}
|
||||
isFill
|
||||
onClick={onClearFilter}
|
||||
size={17}
|
||||
/>
|
||||
)}
|
||||
</StyledFilterBlockHeader>
|
||||
<AsideHeader
|
||||
header={filterHeader}
|
||||
onCloseClick={hideFilterBlock}
|
||||
{...(showClearFilterBtn && {
|
||||
headerIcons: [
|
||||
{
|
||||
key: "filter-icon",
|
||||
url: ClearReactSvgUrl,
|
||||
onClick: onClearFilter,
|
||||
},
|
||||
],
|
||||
})}
|
||||
/>
|
||||
|
||||
<div className="filter-body">
|
||||
{isLoading ? (
|
||||
<FilterBlockLoader
|
||||
@ -598,10 +594,6 @@ const FilterBlock = ({
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</StyledFilterBlockFooter>
|
||||
|
||||
<StyledControlContainer id="filter_close" onClick={hideFilterBlock}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
</StyledFilterBlock>
|
||||
)}
|
||||
|
||||
|
@ -147,24 +147,6 @@ const Content = styled.div.attrs((props: { modalSwipeOffset?: number }) => ({
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledHeader = styled.div<{ currentDisplayType?: ModalDialogType }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: ${(props) =>
|
||||
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
|
||||
height: 52px;
|
||||
margin-bottom: ${(props) =>
|
||||
props.currentDisplayType === "aside" ? "0px" : "16px"};
|
||||
padding: 0 16px 0;
|
||||
|
||||
.heading {
|
||||
font-family: ${(props) => props.theme.fontFamily};
|
||||
color: ${(props) => props.theme.modalDialog.textColor};
|
||||
font-weight: 700;
|
||||
font-size: 21px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledBody = styled(Box)<{
|
||||
currentDisplayType?: ModalDialogType;
|
||||
hasFooter?: boolean;
|
||||
@ -241,7 +223,6 @@ const StyledFooter = styled.div<{
|
||||
`;
|
||||
|
||||
Dialog.defaultProps = { theme: Base };
|
||||
StyledHeader.defaultProps = { theme: Base };
|
||||
Content.defaultProps = { theme: Base };
|
||||
|
||||
export { StyledModal, StyledHeader, Content, Dialog, StyledBody, StyledFooter };
|
||||
export { StyledModal, Content, Dialog, StyledBody, StyledFooter };
|
||||
|
@ -87,6 +87,8 @@ const ModalDialog = ({
|
||||
withBodyScroll = false,
|
||||
withFooterBorder = false,
|
||||
containerVisible = false,
|
||||
|
||||
...rest
|
||||
}: ModalDialogProps) => {
|
||||
const onCloseEvent = React.useCallback(() => {
|
||||
if (embedded) return;
|
||||
@ -173,6 +175,7 @@ const ModalDialog = ({
|
||||
isCloseable={isCloseable && !embedded}
|
||||
embedded={embedded}
|
||||
blur={blur}
|
||||
{...rest}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
@ -24,6 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { AsideHeaderProps } from "../aside/Aside.types";
|
||||
import { ModalDialogType } from "./ModalDialog.enums";
|
||||
|
||||
export type ModalDialogTypeDetailed = {
|
||||
@ -134,7 +135,7 @@ export interface ModalDialogBackdropProps {
|
||||
modalSwipeOffset?: number;
|
||||
}
|
||||
|
||||
export interface ModalSubComponentsProps {
|
||||
export type ModalSubComponentsProps = AsideHeaderProps & {
|
||||
id?: string;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
@ -160,4 +161,4 @@ export interface ModalSubComponentsProps {
|
||||
embedded?: boolean;
|
||||
withForm?: boolean;
|
||||
blur?: number;
|
||||
}
|
||||
};
|
||||
|
@ -1,117 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import CrossIconReactSvgUrl from "PUBLIC_DIR/images/icons/17/cross.react.svg?url";
|
||||
|
||||
import { IconButton } from "../../icon-button";
|
||||
import { mobile } from "../../../utils";
|
||||
import { Base } from "../../../themes";
|
||||
|
||||
import { ModalDialogCloseButtonProps } from "../ModalDialog.types";
|
||||
import { ModalDialogType } from "../ModalDialog.enums";
|
||||
|
||||
const StyledCloseButtonWrapper = styled.div<{
|
||||
currentDisplayType: ModalDialogType;
|
||||
}>`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
|
||||
${(props) =>
|
||||
props.currentDisplayType === "modal"
|
||||
? css`
|
||||
top: 18px;
|
||||
|
||||
${props.theme.interfaceDirection === "rtl"
|
||||
? `left: -30px;`
|
||||
: `right: -30px;`}
|
||||
|
||||
@media ${mobile} {
|
||||
${props.theme.interfaceDirection === "rtl"
|
||||
? `left: 10px;`
|
||||
: `right: 10px;`}
|
||||
top: -27px;
|
||||
}
|
||||
`
|
||||
: css`
|
||||
top: 18px;
|
||||
${props.theme.interfaceDirection === "rtl"
|
||||
? `right: -27px;`
|
||||
: `left: -27px;`}
|
||||
@media ${mobile} {
|
||||
top: -27px;
|
||||
${props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: auto;
|
||||
left: 10px;
|
||||
`
|
||||
: css`
|
||||
left: auto;
|
||||
right: 10px;
|
||||
`}
|
||||
}
|
||||
`}
|
||||
|
||||
.close-button, .close-button:hover {
|
||||
cursor: pointer;
|
||||
path {
|
||||
stroke: ${(props) => props.theme.modalDialog.closeButton.fillColor};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledCloseButtonWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const CloseButton = ({
|
||||
currentDisplayType,
|
||||
|
||||
onClick,
|
||||
}: ModalDialogCloseButtonProps) => {
|
||||
return (
|
||||
<StyledCloseButtonWrapper
|
||||
onClick={onClick}
|
||||
currentDisplayType={currentDisplayType}
|
||||
className="modal-close"
|
||||
>
|
||||
<IconButton
|
||||
size={17}
|
||||
className="close-button"
|
||||
iconName={CrossIconReactSvgUrl}
|
||||
/>
|
||||
</StyledCloseButtonWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export { CloseButton };
|
@ -30,18 +30,15 @@ import { isIOS, isMobileOnly, isSafari } from "react-device-detect";
|
||||
import { classNames } from "../../../utils";
|
||||
import { DialogSkeleton, DialogAsideSkeleton } from "../../../skeletons";
|
||||
|
||||
import { Heading, HeadingSize } from "../../heading";
|
||||
import { Scrollbar } from "../../scrollbar";
|
||||
|
||||
import { AsideHeader } from "../../aside";
|
||||
import {
|
||||
StyledModal,
|
||||
StyledHeader,
|
||||
Content,
|
||||
Dialog,
|
||||
StyledBody,
|
||||
StyledFooter,
|
||||
} from "../ModalDialog.styled";
|
||||
import { CloseButton } from "./CloseButton";
|
||||
import { ModalBackdrop } from "./ModalBackdrop";
|
||||
import { FormWrapper } from "./FormWrapper";
|
||||
import { ModalSubComponentsProps } from "../ModalDialog.types";
|
||||
@ -68,10 +65,12 @@ const Modal = ({
|
||||
modalSwipeOffset,
|
||||
containerVisible,
|
||||
isDoubleFooterLine,
|
||||
isCloseable,
|
||||
|
||||
embedded,
|
||||
withForm,
|
||||
blur,
|
||||
|
||||
...rest
|
||||
}: ModalSubComponentsProps) => {
|
||||
const contentRef = React.useRef<null | HTMLDivElement>(null);
|
||||
|
||||
@ -158,12 +157,6 @@ const Modal = ({
|
||||
embedded={embedded}
|
||||
ref={contentRef}
|
||||
>
|
||||
{isCloseable && (
|
||||
<CloseButton
|
||||
currentDisplayType={currentDisplayType}
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
{isLoading ? (
|
||||
currentDisplayType === "modal" ? (
|
||||
<DialogSkeleton
|
||||
@ -184,25 +177,21 @@ const Modal = ({
|
||||
) : (
|
||||
<FormWrapper withForm={withForm || false}>
|
||||
{header && (
|
||||
<StyledHeader
|
||||
<AsideHeader
|
||||
id="modal-header-swipe"
|
||||
className={
|
||||
classNames(["modal-header", headerProps.className]) ||
|
||||
"modal-header"
|
||||
}
|
||||
{...headerProps}
|
||||
currentDisplayType={currentDisplayType}
|
||||
>
|
||||
<Heading
|
||||
level={1}
|
||||
className="heading"
|
||||
size={HeadingSize.medium}
|
||||
truncate
|
||||
>
|
||||
{headerComponent}
|
||||
</Heading>
|
||||
</StyledHeader>
|
||||
header={headerComponent}
|
||||
onCloseClick={onClose}
|
||||
{...(currentDisplayType === "modal" && {
|
||||
style: { marginBottom: "16px" },
|
||||
})}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
|
||||
{body && (
|
||||
<StyledBody
|
||||
className={
|
||||
|
@ -127,11 +127,7 @@ const RecoverAccessModalDialog: React.FC<IRecoverAccessModalDialogProps> = ({
|
||||
onClose={onRecoverModalClose}
|
||||
displayType={ModalDialogType.modal}
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
<Text isBold fontSize="21px">
|
||||
{t("Common:RecoverTitle")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Header>{t("Common:RecoverTitle")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text
|
||||
key="text-body"
|
||||
|
@ -25,7 +25,7 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import React from "react";
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
|
||||
import { Provider } from "../../utils";
|
||||
import { DeviceType } from "../../enums";
|
||||
@ -153,6 +153,16 @@ const Section = (props: SectionProps) => {
|
||||
isSectionBodyAvailable ||
|
||||
isSectionPagingAvailable;
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const computedStyles = window.getComputedStyle(containerRef.current, null);
|
||||
const width = +computedStyles.getPropertyValue("width").replace("px", "");
|
||||
const height = +computedStyles.getPropertyValue("height").replace("px", "");
|
||||
|
||||
setSectionSize(() => ({ width, height }));
|
||||
}, [isInfoPanelVisible]);
|
||||
|
||||
const onResize = React.useCallback(() => {
|
||||
if (timerRef.current) clearTimeout(timerRef.current);
|
||||
|
||||
@ -188,14 +198,17 @@ const Section = (props: SectionProps) => {
|
||||
|
||||
const showTwoProgress = showPrimaryProgressBar && showSecondaryProgressBar;
|
||||
|
||||
const providerValue = useMemo(
|
||||
() => ({
|
||||
sectionWidth: sectionSize.width,
|
||||
sectionHeight: sectionSize.height,
|
||||
}),
|
||||
[sectionSize.width, sectionSize.height],
|
||||
);
|
||||
|
||||
return (
|
||||
isSectionAvailable && (
|
||||
<Provider
|
||||
value={{
|
||||
sectionWidth: sectionSize.width,
|
||||
sectionHeight: sectionSize.height,
|
||||
}}
|
||||
>
|
||||
<Provider value={providerValue}>
|
||||
<SectionContainer
|
||||
viewAs={viewAs}
|
||||
ref={containerRef}
|
||||
|
@ -29,12 +29,7 @@ import React, { useEffect, useRef } from "react";
|
||||
import { DeviceType } from "../../../enums";
|
||||
import { Portal } from "../../portal";
|
||||
|
||||
import {
|
||||
StyledInfoPanelWrapper,
|
||||
StyledInfoPanel,
|
||||
StyledControlContainer,
|
||||
StyledCrossIcon,
|
||||
} from "../Section.styled";
|
||||
import { StyledInfoPanelWrapper, StyledInfoPanel } from "../Section.styled";
|
||||
import { InfoPanelProps } from "../Section.types";
|
||||
|
||||
const InfoPanel = ({
|
||||
@ -49,8 +44,6 @@ const InfoPanel = ({
|
||||
}: InfoPanelProps) => {
|
||||
const infoPanelRef = useRef<null | HTMLDivElement>(null);
|
||||
|
||||
const closeInfoPanel = () => setIsVisible?.(false);
|
||||
|
||||
useEffect(() => {
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
@ -74,13 +67,7 @@ const InfoPanel = ({
|
||||
id="InfoPanelWrapper"
|
||||
ref={infoPanelRef}
|
||||
>
|
||||
<StyledInfoPanel>
|
||||
<StyledControlContainer onClick={closeInfoPanel}>
|
||||
<StyledCrossIcon />
|
||||
</StyledControlContainer>
|
||||
|
||||
{children}
|
||||
</StyledInfoPanel>
|
||||
<StyledInfoPanel>{children}</StyledInfoPanel>
|
||||
</StyledInfoPanelWrapper>
|
||||
);
|
||||
|
||||
|
@ -63,8 +63,11 @@ const StyledSelector = styled.div`
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const StyledHeader = styled.div<{ withoutBorder?: boolean }>`
|
||||
width: calc(100% - 32px);
|
||||
const StyledHeader = styled.div<{
|
||||
withoutBorder?: boolean;
|
||||
withoutIcon: boolean;
|
||||
}>`
|
||||
width: calc(100% - 53px);
|
||||
min-height: 53px;
|
||||
height: 53px;
|
||||
max-height: 53px;
|
||||
@ -82,6 +85,7 @@ const StyledHeader = styled.div<{ withoutBorder?: boolean }>`
|
||||
.arrow-button {
|
||||
cursor: pointer;
|
||||
margin-right: 12px;
|
||||
min-width: 17px;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
|
@ -73,6 +73,8 @@ export type BreadCrumbsProps = {
|
||||
|
||||
export type HeaderProps = {
|
||||
headerLabel: string;
|
||||
onCloseClick: () => void;
|
||||
isCloseable?: boolean;
|
||||
} & THeaderBackButton;
|
||||
|
||||
export type TSelectorHeader =
|
||||
|
@ -26,34 +26,29 @@
|
||||
|
||||
import React from "react";
|
||||
|
||||
import ArrowPathReactSvgUrl from "PUBLIC_DIR/images/arrow.path.react.svg?url";
|
||||
|
||||
import { IconButton } from "../../icon-button";
|
||||
import { Heading } from "../../heading";
|
||||
|
||||
import { StyledHeader } from "../Selector.styled";
|
||||
import { HeaderProps } from "../Selector.types";
|
||||
import { AsideHeader } from "../../aside";
|
||||
|
||||
const Header = React.memo(
|
||||
({
|
||||
onBackClick,
|
||||
onCloseClick,
|
||||
withoutBackButton,
|
||||
headerLabel,
|
||||
withoutBorder,
|
||||
isCloseable,
|
||||
}: HeaderProps) => {
|
||||
return (
|
||||
<StyledHeader withoutBorder={withoutBorder}>
|
||||
{!withoutBackButton && typeof withoutBackButton === "boolean" && (
|
||||
<IconButton
|
||||
className="arrow-button"
|
||||
iconName={ArrowPathReactSvgUrl}
|
||||
size={17}
|
||||
onClick={onBackClick}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Heading className="heading-text">{headerLabel}</Heading>
|
||||
</StyledHeader>
|
||||
<AsideHeader
|
||||
header={headerLabel}
|
||||
isBackButton={
|
||||
!withoutBackButton && typeof withoutBackButton === "boolean"
|
||||
}
|
||||
onBackClick={onBackClick}
|
||||
onCloseClick={onCloseClick}
|
||||
withoutBorder={withoutBorder}
|
||||
isCloseable={isCloseable}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -28,6 +28,7 @@ import { TSelectorItem } from "../../components/selector";
|
||||
import {
|
||||
TBreadCrumb,
|
||||
TInfoBar,
|
||||
TSelectorHeader,
|
||||
} from "../../components/selector/Selector.types";
|
||||
import {
|
||||
TFileSecurity,
|
||||
@ -143,7 +144,8 @@ export type TSelectedFileInfo = {
|
||||
|
||||
export type TGetIcon = (size: number, fileExst: string) => string;
|
||||
|
||||
export type FilesSelectorProps = TInfoBar &
|
||||
export type FilesSelectorProps = TSelectorHeader &
|
||||
TInfoBar &
|
||||
(
|
||||
| {
|
||||
getIcon: TGetIcon;
|
||||
|
@ -114,6 +114,7 @@ const FilesSelectorComponent = ({
|
||||
createDefineRoomType,
|
||||
withInfoBar,
|
||||
infoBarData,
|
||||
headerProps,
|
||||
}: FilesSelectorProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(["Common"]);
|
||||
@ -475,8 +476,15 @@ const FilesSelectorComponent = ({
|
||||
openRoot,
|
||||
]);
|
||||
|
||||
const headerProps: TSelectorHeader = withHeader
|
||||
? { withHeader, headerProps: { headerLabel } }
|
||||
const headerSelectorProps: TSelectorHeader = withHeader
|
||||
? {
|
||||
withHeader,
|
||||
headerProps: {
|
||||
...headerProps,
|
||||
headerLabel,
|
||||
onCloseClick: onCancel,
|
||||
},
|
||||
}
|
||||
: {};
|
||||
|
||||
const withSearch = withSearchProp
|
||||
@ -553,7 +561,7 @@ const FilesSelectorComponent = ({
|
||||
|
||||
const SelectorBody = (
|
||||
<Selector
|
||||
{...headerProps}
|
||||
{...headerSelectorProps}
|
||||
{...searchProps}
|
||||
{...submitButtonProps}
|
||||
{...cancelButtonProps}
|
||||
@ -617,6 +625,7 @@ const FilesSelectorComponent = ({
|
||||
withoutBodyScroll
|
||||
zIndex={310}
|
||||
onClose={onCancel}
|
||||
withoutHeader
|
||||
>
|
||||
{SelectorBody}
|
||||
</Aside>
|
||||
|
@ -2580,6 +2580,7 @@ __metadata:
|
||||
"@babel/preset-typescript": "npm:^7.21.0"
|
||||
"@codemirror/lang-javascript": "npm:^6.2.2"
|
||||
"@svgr/webpack": "npm:^5.5.0"
|
||||
"@types/element-resize-detector": "npm:^1.1.6"
|
||||
"@types/eslint": "npm:^8.44.7"
|
||||
"@types/he": "npm:^1.2.3"
|
||||
"@typescript-eslint/eslint-plugin": "npm:^6.12.0"
|
||||
@ -7627,6 +7628,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/element-resize-detector@npm:^1.1.6":
|
||||
version: 1.1.6
|
||||
resolution: "@types/element-resize-detector@npm:1.1.6"
|
||||
checksum: 10/62967c4933ce6dc717608aa498bfbbf2567c3778958203621b1981f5804eb519cf16b8f677d3c92c9b2a9d791191b514dd60298e276fcbf6b1660542209dd299
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/emscripten@npm:^1.39.6":
|
||||
version: 1.39.10
|
||||
resolution: "@types/emscripten@npm:1.39.10"
|
||||
|
Loading…
Reference in New Issue
Block a user