diff --git a/packages/client/public/locales/en/EmptyView.json b/packages/client/public/locales/en/EmptyView.json
index c45227d261..e40265d495 100644
--- a/packages/client/public/locales/en/EmptyView.json
+++ b/packages/client/public/locales/en/EmptyView.json
@@ -35,5 +35,10 @@
"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."
+ "UserEmptyDescription": "Files and folders uploaded by admins will appeared here.",
+ "InviteRootRoomDescription": "Send an invitation to add new members to your {{productName}}",
+ "MigrationDataTitle": "Migration Data",
+ "MigrationDataDescription": "Import data to your {{productName}} from ONLYOFFICE Workspace, Google Workspace, or Nextcloud.",
+ "EmptyRootRoomUserTitle": "There are no rooms here yet",
+ "EmptyRootRoomUserDescription": "The shared room will appear here."
}
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 e9c5472b12..4299ec8638 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
@@ -2,6 +2,7 @@ import React from "react";
import { P, match } from "ts-pattern";
import {
+ EmployeeType,
FilesSelectorFilterTypes,
FilterType,
FolderType,
@@ -13,6 +14,7 @@ import CreateNewFormIcon from "PUBLIC_DIR/images/emptyview/create.new.form.svg";
import CreateNewSpreadsheetIcon from "PUBLIC_DIR/images/emptyview/create.new.spreadsheet.svg";
import CreateNewPresentation from "PUBLIC_DIR/images/emptyview/create.new.presentation.svg";
import CreateRoom from "PUBLIC_DIR/images/emptyview/create.room.svg";
+import InviteUserFormIcon from "PUBLIC_DIR/images/emptyview/invite.user.svg";
import SharedIcon from "PUBLIC_DIR/images/emptyview/share.svg";
@@ -57,7 +59,7 @@ export const getDescription = (
): string => {
const isNotAdmin = isUser(access);
- if (isRootEmptyPage) return getRootDesctiption(t, rootFolderType);
+ if (isRootEmptyPage) return getRootDesctiption(t, access, rootFolderType);
if (isFolder)
return getFolderDescription(
@@ -85,7 +87,7 @@ export const getTitle = (
): string => {
const isNotAdmin = isUser(access);
- if (isRootEmptyPage) return getRootTitle(t, rootFolderType);
+ if (isRootEmptyPage) return getRootTitle(t, access, rootFolderType);
if (isFolder)
return getFolderTitle(
@@ -232,6 +234,28 @@ export const getOptions = (
disabled: false,
};
+ const inviteRootRoom = {
+ title: t("EmptyView:InviteNewUsers"),
+ description: t("EmptyView:InviteRootRoomDescription", {
+ productName: t("Common:ProductName"),
+ }),
+ icon: ,
+ key: "invite-root-room",
+ onClick: () => actions.inviteRootUser(EmployeeType.Guest),
+ disabled: false,
+ };
+
+ const migrationData = {
+ title: t("EmptyView:MigrationDataTitle"),
+ description: t("EmptyView:MigrationDataDescription", {
+ productName: t("Common:ProductName"),
+ }),
+ icon: ,
+ key: "migration-data",
+ onClick: () => actions.navigate("/portal-settings/data-import"),
+ disabled: false,
+ };
+
const createFile: EmptyViewItemType = {
title: t("EmptyView:CreateNewFileTitle"),
description: t("EmptyView:CreateNewFileDescription"),
@@ -276,13 +300,13 @@ export const getOptions = (
if (isArchiveFolderRoot) return [];
if (isRootEmptyPage) {
- switch (rootFolderType) {
- case FolderType.Rooms:
- return [createRoom];
-
- default:
- return [];
- }
+ return match([rootFolderType, access])
+ .with([FolderType.Rooms, ShareAccessRights.None], () => [
+ createRoom,
+ inviteRootRoom,
+ migrationData,
+ ])
+ .otherwise(() => []);
}
if (isFolder) {
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 cbd340c6cb..0014a5a2f0 100644
--- a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx
+++ b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.tsx
@@ -2,6 +2,7 @@ import { useTheme } from "styled-components";
import { inject, observer } from "mobx-react";
import { useTranslation } from "react-i18next";
import React, { useMemo, useCallback } from "react";
+import { useNavigate } from "react-router-dom";
import {
Events,
@@ -47,7 +48,10 @@ const EmptyViewContainer = observer(
onCreateAndCopySharedLink,
setSelectFileFormRoomDialogVisible,
setInviteUsersWarningDialogVisible,
+ inviteUser: inviteRootUser,
}: EmptyViewContainerProps) => {
+ const navigate = useNavigate();
+
const { t } = useTranslation([
"EmptyView",
"Files",
@@ -189,6 +193,8 @@ const EmptyViewContainer = observer(
createAndCopySharedLink,
openInfoPanel,
onCreateRoom,
+ inviteRootUser,
+ navigate,
},
),
[
@@ -209,6 +215,8 @@ const EmptyViewContainer = observer(
onCreate,
openInfoPanel,
onCreateRoom,
+ inviteRootUser,
+ navigate,
],
);
@@ -237,7 +245,7 @@ const InjectedEmptyViewContainer = inject<
infoPanelStore,
currentTariffStatusStore,
}): InjectedEmptyViewContainerProps => {
- const { onClickInviteUsers, onCreateAndCopySharedLink } =
+ const { onClickInviteUsers, onCreateAndCopySharedLink, inviteUser } =
contextOptionsStore;
const { isGracePeriod } = currentTariffStatusStore;
@@ -270,6 +278,7 @@ const InjectedEmptyViewContainer = inject<
setInviteUsersWarningDialogVisible,
setVisibleInfoPanel,
setViewInfoPanel,
+ inviteUser,
};
},
)(EmptyViewContainer as React.FC);
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 ce91603022..fc06c07dc6 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
@@ -1,5 +1,5 @@
-import type { TFolderSecurity } from "@docspace/shared/api/files/types";
-import type { TRoomSecurity } from "@docspace/shared/api/rooms/types";
+import type { NavigateFunction } from "react-router-dom";
+
import type {
FilesSelectorFilterTypes,
FilterType,
@@ -41,27 +41,34 @@ export interface OutEmptyViewContainerProps {
isRootEmptyPage: boolean;
}
-export interface InjectedEmptyViewContainerProps {
- access: Nullable;
- security: Nullable;
- selectedFolder?: ReturnType<
+export interface InjectedEmptyViewContainerProps
+ extends Pick<
+ TStore["contextOptionsStore"],
+ "inviteUser" | "onCreateAndCopySharedLink" | "onClickInviteUsers"
+ >,
+ Pick<
+ TStore["dialogsStore"],
+ | "setSelectFileFormRoomDialogVisible"
+ | "setInviteUsersWarningDialogVisible"
+ >,
+ Pick<
+ TStore["selectedFolderStore"],
+ "access" | "security" | "rootFolderType"
+ > {
+ selectedFolder: ReturnType<
TStore["selectedFolderStore"]["getSelectedFolder"]
>;
isGracePeriod: boolean;
isVisibleInfoPanel: boolean;
- rootFolderType: Nullable;
- onClickInviteUsers: (folderId: string | number, roomType: RoomsType) => void;
- onCreateAndCopySharedLink: TStore["contextOptionsStore"]["onCreateAndCopySharedLink"];
- setSelectFileFormRoomDialogVisible: TStore["dialogsStore"]["setSelectFileFormRoomDialogVisible"];
setVisibleInfoPanel: (arg: boolean) => void;
setViewInfoPanel: TStore["infoPanelStore"]["setView"];
- setInviteUsersWarningDialogVisible: TStore["dialogsStore"]["setInviteUsersWarningDialogVisible"];
}
export type EmptyViewContainerProps = OutEmptyViewContainerProps &
InjectedEmptyViewContainerProps;
export type OptionActions = {
+ navigate: NavigateFunction;
inviteUser: VoidFunction;
onCreate: (extension: ExtensiontionType, withoutDialog?: boolean) => void;
uploadFromDocspace: (
@@ -72,4 +79,5 @@ export type OptionActions = {
createAndCopySharedLink: VoidFunction;
openInfoPanel: VoidFunction;
onCreateRoom: VoidFunction;
+ inviteRootUser: TStore["contextOptionsStore"]["inviteUser"];
};
diff --git a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.utils.tsx b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.utils.tsx
index 90f64e798d..a5e41978ff 100644
--- a/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.utils.tsx
+++ b/packages/client/src/components/EmptyContainer/sub-components/EmptyViewContainer/EmptyViewContainer.utils.tsx
@@ -34,6 +34,9 @@ import CreateNewFormIcon from "PUBLIC_DIR/images/emptyview/create.new.form.svg";
import EmptyRoomsRootDarkIcon from "PUBLIC_DIR/images/emptyview/empty.rooms.root.dark.svg";
import EmptyRoomsRootLightIcon from "PUBLIC_DIR/images/emptyview/empty.rooms.root.light.svg";
+import EmptyRoomsRootUserDarkIcon from "PUBLIC_DIR/images/emptyview/empty.rooms.root.user.dark.svg";
+import EmptyRoomsRootUserLightIcon from "PUBLIC_DIR/images/emptyview/empty.rooms.root.user.light.svg";
+
import EmptyFormRoomDarkIcon from "PUBLIC_DIR/images/emptyview/empty.form.room.dark.svg";
import EmptyFormRoomLightIcon from "PUBLIC_DIR/images/emptyview/empty.form.room.light.svg";
@@ -88,6 +91,8 @@ import type {
} from "./EmptyViewContainer.types";
export const isUser = (access: AccessType) => {
+ console.log({ access });
+
return (
access !== ShareAccessRights.None &&
access !== ShareAccessRights.RoomManager &&
@@ -155,14 +160,20 @@ export const getRoomDescription = (
export const getRootDesctiption = (
t: TTranslation,
+ access: AccessType,
rootFolderType: Nullable,
) => {
- return match([rootFolderType])
- .with([FolderType.Rooms], () => t("Files:RoomEmptyContainerDescription"))
- .with([FolderType.USER], () => t("Test"))
- .with([FolderType.Recent], () => t("Test"))
- .with([FolderType.Archive], () => t("Test"))
- .with([FolderType.TRASH], () => t("Test"))
+ return match([rootFolderType, access])
+ .with([FolderType.Rooms, ShareAccessRights.None], () =>
+ t("Files:RoomEmptyContainerDescription"),
+ )
+ .with([FolderType.Rooms, ShareAccessRights.DenyAccess], () =>
+ t("EmptyView:EmptyRootRoomUserDescription"),
+ )
+ .with([FolderType.USER, P._], () => t("Test"))
+ .with([FolderType.Recent, P._], () => t("Test"))
+ .with([FolderType.Archive, P._], () => t("Test"))
+ .with([FolderType.TRASH, P._], () => t("Test"))
.otherwise(() => "");
};
@@ -234,18 +245,22 @@ export const getRoomTitle = (
export const getRootTitle = (
t: TTranslation,
+ access: AccessType,
rootFolderType: Nullable,
) => {
- return match([rootFolderType])
- .with([FolderType.Rooms], () =>
+ return match([rootFolderType, access])
+ .with([FolderType.Rooms, ShareAccessRights.None], () =>
t("Files:EmptyRootRoomHeader", {
productName: t("Common:ProductName"),
}),
)
- .with([FolderType.USER], () => t("Test"))
- .with([FolderType.Recent], () => t("Test"))
- .with([FolderType.Archive], () => t("Test"))
- .with([FolderType.TRASH], () => t("Test"))
+ .with([FolderType.Rooms, ShareAccessRights.DenyAccess], () =>
+ t("EmptyView:EmptyRootRoomUserTitle"),
+ )
+ .with([FolderType.USER, P._], () => t("Test"))
+ .with([FolderType.Recent, P._], () => t("Test"))
+ .with([FolderType.Archive, P._], () => t("Test"))
+ .with([FolderType.TRASH, P._], () => t("Test"))
.otherwise(() => "");
};
@@ -363,9 +378,16 @@ export const getRootIcom = (
isBaseTheme: boolean,
) => {
return match([rootFolderType, access])
- .with([FolderType.Rooms, P._], () =>
+ .with([FolderType.Rooms, ShareAccessRights.None], () =>
isBaseTheme ? : ,
)
+ .with([FolderType.Rooms, ShareAccessRights.DenyAccess], () =>
+ isBaseTheme ? (
+
+ ) : (
+
+ ),
+ )
.with([FolderType.USER, P._], () => )
.with([FolderType.Recent, P._], () => )
.with([FolderType.Archive, P._], () => )
diff --git a/packages/client/src/store/ContextOptionsStore.js b/packages/client/src/store/ContextOptionsStore.js
index 9d0ddf6fd1..506fa444ff 100644
--- a/packages/client/src/store/ContextOptionsStore.js
+++ b/packages/client/src/store/ContextOptionsStore.js
@@ -2098,12 +2098,14 @@ class ContextOptionsStore {
return newOptions;
};
- onInvite = (e) => {
+ /**
+ * @param {EmployeeType} userType
+ * @returns {void}
+ */
+ inviteUser = (userType) => {
const { setInviteUsersWarningDialogVisible, setInvitePanelOptions } =
this.dialogsStore;
- const type = e.item["data-type"];
-
if (this.currentTariffStatusStore.isGracePeriod) {
setInviteUsersWarningDialogVisible(true);
return;
@@ -2113,10 +2115,15 @@ class ContextOptionsStore {
visible: true,
roomId: -1,
hideSelector: true,
- defaultAccess: type,
+ defaultAccess: userType,
});
};
+ onInvite = (e) => {
+ const type = e.item["data-type"];
+ this.inviteUser(type);
+ };
+
onInviteAgain = (t) => {
resendInvitesAgain()
.then(() =>
diff --git a/public/images/emptyview/create.room.svg b/public/images/emptyview/create.room.svg
index b3cce21756..c1af7175d7 100644
--- a/public/images/emptyview/create.room.svg
+++ b/public/images/emptyview/create.room.svg
@@ -1,4 +1,4 @@
diff --git a/public/images/emptyview/empty.migration.svg b/public/images/emptyview/empty.migration.svg
new file mode 100644
index 0000000000..f9ab05f0ea
--- /dev/null
+++ b/public/images/emptyview/empty.migration.svg
@@ -0,0 +1,4 @@
+
diff --git a/public/images/emptyview/empty.rooms.root.user.dark.svg b/public/images/emptyview/empty.rooms.root.user.dark.svg
new file mode 100644
index 0000000000..6e73101b5d
--- /dev/null
+++ b/public/images/emptyview/empty.rooms.root.user.dark.svg
@@ -0,0 +1,14 @@
+
diff --git a/public/images/emptyview/empty.rooms.root.user.light.svg b/public/images/emptyview/empty.rooms.root.user.light.svg
new file mode 100644
index 0000000000..50e314c93d
--- /dev/null
+++ b/public/images/emptyview/empty.rooms.root.user.light.svg
@@ -0,0 +1,14 @@
+