diff --git a/packages/client/package.json b/packages/client/package.json index 3e06cca4b6..dfd93519cb 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -74,6 +74,7 @@ "@babel/preset-typescript": "^7.21.0", "@svgr/webpack": "^5.5.0", "@types/eslint": "^8.44.7", + "@types/he": "^1.2.3", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "babel-loader": "^8.3.0", diff --git a/packages/client/public/locales/en/EmptyView.json b/packages/client/public/locales/en/EmptyView.json index 09c1992b16..f206d5a321 100644 --- a/packages/client/public/locales/en/EmptyView.json +++ b/packages/client/public/locales/en/EmptyView.json @@ -21,6 +21,5 @@ "UploadFromPortalDescription": "Upload any type files from Documents or Rooms", "UploadFromPortalTitle": "Upload from {{productName}}", "UploadPDFFormOptionDescription": "Select a ready PDF form available in {{productName}} and upload it to the room.", - "UserEmptyDescription": "Files and folders uploaded by admins will appeared here.", - "UserEmptyTitle": "No docs here yet" + "UserEmptyDescription": "Files and folders uploaded by admins will appeared here." } diff --git a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js index 8782db9ac9..35f0108100 100644 --- a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js +++ b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js @@ -90,6 +90,7 @@ const EmptyFolderContainer = ({ isFolder={!isRoom} folderId={folderId} parentRoomType={parentRoomType} + isArchiveFolderRoot={isArchiveFolderRoot} /> ); } diff --git a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.helpers.tsx b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.helpers.tsx index e56c9db6b8..a7054f3ff3 100644 --- a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.helpers.tsx +++ b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.helpers.tsx @@ -63,6 +63,7 @@ export const getDescription = ( isFolder: boolean, folderType: Nullable, parentRoomType: Nullable, + isArchiveFolderRoot: boolean, ): string => { const isCollaborator = access === ShareAccessRights.Collaborator; @@ -88,8 +89,13 @@ export const getDescription = ( ], () => t("Files:EmptyFormSubFolderHeaderText"), ) - .with([FolderType.FormRoom, null, P.when(() => isNotAdmin)], () => - t("EmptyView:FormFolderDefaultUserDescription"), + .with( + [ + FolderType.FormRoom, + null, + P.when(() => isNotAdmin || isArchiveFolderRoot), + ], + () => t("EmptyView:FormFolderDefaultUserDescription"), ) .with([FolderType.FormRoom, null, P._], () => t("EmptyView:FormFolderDefaultDescription", { @@ -99,7 +105,8 @@ export const getDescription = ( .otherwise(() => ""); } - if (isNotAdmin) return t("EmptyView:UserEmptyDescription"); + if (isNotAdmin || isArchiveFolderRoot) + return t("EmptyView:UserEmptyDescription"); if (isCollaborator) return t("EmptyView:CollaboratorEmptyDesciprtion"); @@ -113,6 +120,7 @@ export const getTitle = ( isFolder: boolean, folderType: Nullable, parentRoomType: Nullable, + isArchiveFolderRoot: boolean, ): string => { const isCollaborator = access === ShareAccessRights.Collaborator; @@ -135,8 +143,13 @@ export const getTitle = ( .with([P._, FolderType.SubFolderInProgress, P._], () => t("Files:EmptyFormSubFolderProgressDescriptionText"), ) - .with([FolderType.FormRoom, null, P.when(() => isNotAdmin)], () => - t("EmptyView:FormFolderDefaultUserTitle"), + .with( + [ + FolderType.FormRoom, + null, + P.when(() => isNotAdmin || isArchiveFolderRoot), + ], + () => t("EmptyView:FormFolderDefaultUserTitle"), ) .with([FolderType.FormRoom, null, P._], () => t("EmptyView:FormFolderDefaultTitle"), @@ -146,7 +159,7 @@ export const getTitle = ( if (isCollaborator) return t("EmptyView:CollaboratorEmptyTitle"); - if (isNotAdmin) return t("EmptyView:UserEmptyTitle"); + if (isNotAdmin || isArchiveFolderRoot) return t("Files:EmptyScreenFolder"); switch (type) { case RoomsType.FormRoom: @@ -317,6 +330,7 @@ export const getOptions = ( isFolder: boolean, folderType: Nullable, parentRoomType: Nullable, + isArchiveFolderRoot: boolean, actions: OptionActions, ): EmptyViewItemType[] => { const isFormFiller = access === ShareAccessRights.FormFilling; @@ -417,6 +431,8 @@ export const getOptions = ( ], }; + if (isArchiveFolderRoot) return []; + if (isFolder) { return match([parentRoomType, folderType, access]) .with( diff --git a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx index 17caa36187..45024510c6 100644 --- a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx +++ b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx @@ -30,6 +30,7 @@ const EmptyViewContainer = observer( folderType, selectedFolder, parentRoomType, + isArchiveFolderRoot, onClickInviteUsers, onCreateAndCopySharedLink, setSelectFileFormRoomDialogVisible, @@ -95,6 +96,7 @@ const EmptyViewContainer = observer( isFolder, folderType, parentRoomType, + isArchiveFolderRoot, ); const title = getTitle( type, @@ -103,6 +105,7 @@ const EmptyViewContainer = observer( isFolder, folderType, parentRoomType, + isArchiveFolderRoot, ); const icon = getIcon( type, @@ -114,7 +117,16 @@ const EmptyViewContainer = observer( ); return { description, title, icon }; - }, [type, t, theme.isBase, access, isFolder, folderType, parentRoomType]); + }, [ + type, + t, + theme.isBase, + access, + isFolder, + folderType, + parentRoomType, + isArchiveFolderRoot, + ]); const options = useMemo( () => @@ -126,6 +138,7 @@ const EmptyViewContainer = observer( isFolder, folderType, parentRoomType, + isArchiveFolderRoot, { inviteUser, onCreate, @@ -141,6 +154,7 @@ const EmptyViewContainer = observer( isFolder, folderType, parentRoomType, + isArchiveFolderRoot, t, inviteUser, uploadFromDocspace, diff --git a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.types.ts b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.types.ts index 28f6c5fdc0..46590bfb3b 100644 --- a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.types.ts +++ b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.types.ts @@ -28,6 +28,7 @@ export interface EmptyViewContainerProps { parentRoomType: Nullable; folderType: Nullable; isFolder: boolean; + isArchiveFolderRoot: boolean; onClickInviteUsers?: (folderId: string | number, roomType: RoomsType) => void; setSelectFileFormRoomDialogVisible?: TStore["dialogsStore"]["setSelectFileFormRoomDialogVisible"]; onCreateAndCopySharedLink?: TStore["contextOptionsStore"]["onCreateAndCopySharedLink"]; diff --git a/packages/client/src/helpers/confirmRoute.js b/packages/client/src/helpers/confirmRoute.js index d0f2b4fd08..4a9344d9be 100644 --- a/packages/client/src/helpers/confirmRoute.js +++ b/packages/client/src/helpers/confirmRoute.js @@ -109,6 +109,7 @@ const ConfirmRoute = ({ switch (validationResult) { case ValidationResult.Ok: + case ValidationResult.UserExisted: const confirmHeader = search.slice(1); const linkData = { ...confirmLinkData, @@ -129,7 +130,10 @@ const ConfirmRoute = ({ setState((val) => ({ ...val, isLoaded: true, linkData, roomData })); break; case ValidationResult.Invalid: - console.error("invlid link", { confirmLinkData, validationResult }); + console.error("invalid link", { + confirmLinkData, + validationResult, + }); window.location.href = combineUrl( window.ClientConfig?.proxy?.url, path, @@ -159,6 +163,24 @@ const ConfirmRoute = ({ "/error?messageKey=20", ); break; + case ValidationResult.QuotaFailed: + console.error("access below quota", { + confirmLinkData, + validationResult, + }); + window.location.href = combineUrl( + window.ClientConfig?.proxy?.url, + path, + "/error", + ); + break; + case ValidationResult.UserExcluded: + console.error("user excluded", { + confirmLinkData, + validationResult, + }); + window.location.replace(defaultPage); + break; default: console.error("unknown link", { confirmLinkData, diff --git a/packages/client/src/helpers/enums.ts b/packages/client/src/helpers/enums.ts index d0de9800d7..4df9492951 100644 --- a/packages/client/src/helpers/enums.ts +++ b/packages/client/src/helpers/enums.ts @@ -39,4 +39,7 @@ export const enum ValidationResult { Invalid = 1, Expired = 2, TariffLimit = 3, + UserExisted = 4, + UserExcluded = 5, + QuotaFailed = 6, } diff --git a/packages/client/src/pages/Confirm/sub-components/createUser.js b/packages/client/src/pages/Confirm/sub-components/createUser.js index 8cf725283e..497e7f0828 100644 --- a/packages/client/src/pages/Confirm/sub-components/createUser.js +++ b/packages/client/src/pages/Confirm/sub-components/createUser.js @@ -122,6 +122,7 @@ const CreateUserForm = (props) => { const emailFromLink = linkData?.email ? linkData.email : ""; const roomName = roomData?.title; + const roomId = roomData?.roomId; const [email, setEmail] = useState(emailFromLink); const [emailValid, setEmailValid] = useState(true); @@ -199,6 +200,7 @@ const CreateUserForm = (props) => { roomName, firstName: user.firstName, lastName: user.lastName, + linkData: linkData, }), ), ); @@ -209,6 +211,14 @@ const CreateUserForm = (props) => { "max-age": COOKIE_EXPIRATION_YEAR, }); + const finalUrl = roomId + ? `/rooms/shared/filter?folder=${roomId}` + : defaultPage; + + if (roomId) { + sessionStorage.setItem("referenceUrl", finalUrl); + } + window.location.href = combineUrl( window.ClientConfig?.proxy?.url, "/login", diff --git a/packages/client/src/pages/Home/InfoPanel/Body/views/History/HistoryBlockContent/RoomExternalLink.tsx b/packages/client/src/pages/Home/InfoPanel/Body/views/History/HistoryBlockContent/RoomExternalLink.tsx index 23b705cf35..bf561b6b06 100644 --- a/packages/client/src/pages/Home/InfoPanel/Body/views/History/HistoryBlockContent/RoomExternalLink.tsx +++ b/packages/client/src/pages/Home/InfoPanel/Body/views/History/HistoryBlockContent/RoomExternalLink.tsx @@ -24,13 +24,14 @@ // 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 { inject, observer } from "mobx-react"; import { decode } from "he"; +import { withTranslation } from "react-i18next"; +import { inject, observer } from "mobx-react"; import { Link } from "@docspace/shared/components/link"; import { toastr } from "@docspace/shared/components/toast"; -import { withTranslation } from "react-i18next"; import { Text } from "@docspace/shared/components/text"; +import { RoomsType } from "@docspace/shared/enums"; import { TTranslation } from "@docspace/shared/types"; import { StyledHistoryLink } from "../../../styles/history"; @@ -65,7 +66,9 @@ interface HistoryRoomExternalLinkProps { isEdit: boolean; link: TFeedData; roomId: number | string; + isFormRoom?: boolean; }) => void; + isFormRoom?: boolean; } const HistoryRoomExternalLink = ({ @@ -75,6 +78,7 @@ const HistoryRoomExternalLink = ({ setEditLinkPanelIsVisible, setLinkParams, roomId, + isFormRoom, }: HistoryRoomExternalLinkProps) => { const onEditLink = () => { if (!feedData.sharedTo) { @@ -82,7 +86,12 @@ const HistoryRoomExternalLink = ({ return; } - setLinkParams({ isEdit: true, link: feedData, roomId }); + setLinkParams({ + isEdit: true, + link: feedData, + roomId, + isFormRoom, + }); setEditLinkPanelIsVisible(true); }; @@ -90,29 +99,31 @@ const HistoryRoomExternalLink = ({ {canEditLink ? ( - {decode(feedData.title || feedData.sharedTo?.title)} + {decode((feedData.title || feedData.sharedTo?.title) ?? "")} ) : ( - {decode(feedData.title || feedData.sharedTo?.title)} + {decode((feedData.title || feedData.sharedTo?.title) ?? "")} )} ); }; -export default inject(({ userStore, dialogsStore, infoPanelStore }) => { +export default inject(({ userStore, dialogsStore, infoPanelStore }) => { const { infoPanelSelection } = infoPanelStore; const { setLinkParams, setEditLinkPanelIsVisible } = dialogsStore; const { user } = userStore; - const { id } = infoPanelSelection; + const { id, roomType } = infoPanelSelection!; - const cannotEdit = user.isVisitor || user.isCollaborator; + const isFormRoom = roomType === RoomsType.FormRoom; + const cannotEdit = user?.isVisitor || user?.isCollaborator; return { canEditLink: !cannotEdit, setEditLinkPanelIsVisible, setLinkParams, roomId: id, + isFormRoom, }; })(withTranslation(["InfoPanel"])(observer(HistoryRoomExternalLink))); diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/sub-components/PresetTile.js b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/sub-components/PresetTile.js index 4b6fffe202..c05c7a6645 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/sub-components/PresetTile.js +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/sub-components/PresetTile.js @@ -26,6 +26,7 @@ import React from "react"; import styled, { css } from "styled-components"; +import { ReactSVG } from "react-svg"; import { Base } from "@docspace/shared/themes"; @@ -90,9 +91,10 @@ const PresetTile = (props) => { {title} - {title} + {description} +