Merge pull request #529 from ONLYOFFICE/feature/room-embedding

Web: Files: added embedding settings to the room context menu
This commit is contained in:
Ilya Oleshko 2024-06-27 11:19:22 +03:00 committed by GitHub
commit 24e12cd8e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 85 additions and 78 deletions

View File

@ -6,7 +6,6 @@
"Width": "Width", "Width": "Width",
"Link": "Link", "Link": "Link",
"DisplaySettings": "Display settings", "DisplaySettings": "Display settings",
"EmbeddingDescription": "Embed Public room into your website or blog. Apply additional display settings for customizing the embedded content.",
"CodeSuccessfullyCopied": "Code to insert successfully copied to clipboard", "CodeSuccessfullyCopied": "Code to insert successfully copied to clipboard",
"LinkProtectedWithPassword": "The link is protected with a password.", "LinkProtectedWithPassword": "The link is protected with a password.",
"ContentRestricted": "Content copying, file downloading and printing are restricted.", "ContentRestricted": "Content copying, file downloading and printing are restricted.",

View File

@ -57,11 +57,6 @@ const StyledBody = styled.div`
} }
.embedding-panel_body { .embedding-panel_body {
.embedding-panel_description {
color: ${({ theme }) => theme.embeddingPanel.descriptionTextColor};
margin: 18px 0;
}
.embedding-panel_bar { .embedding-panel_bar {
.embedding-panel_bar-header { .embedding-panel_bar-header {
display: flex; display: flex;

View File

@ -26,11 +26,12 @@
import { useState, useEffect, useCallback, useRef } from "react"; import { useState, useEffect, useCallback, useRef } from "react";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import { useNavigate } from "react-router-dom";
import { withTranslation, Trans } from "react-i18next"; import { withTranslation, Trans } from "react-i18next";
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import isEqual from "lodash/isEqual"; import isEqual from "lodash/isEqual";
import { objectToGetParams } from "@docspace/shared/utils/common"; import { objectToGetParams } from "@docspace/shared/utils/common";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import config from "PACKAGE_FILE";
import { Text } from "@docspace/shared/components/text"; import { Text } from "@docspace/shared/components/text";
import { toastr } from "@docspace/shared/components/toast"; import { toastr } from "@docspace/shared/components/toast";
@ -103,7 +104,7 @@ type EmbeddingPanelProps = {
visible: boolean; visible: boolean;
setEmbeddingPanelData: (value: { setEmbeddingPanelData: (value: {
visible: boolean; visible: boolean;
fileId?: string | number; itemId?: string | number;
}) => void; }) => void;
setEditLinkPanelIsVisible: (value: boolean) => void; setEditLinkPanelIsVisible: (value: boolean) => void;
currentColorScheme: TColorScheme; currentColorScheme: TColorScheme;
@ -111,7 +112,8 @@ type EmbeddingPanelProps = {
setLinkParams: (linkParams: LinkParamsType) => void; setLinkParams: (linkParams: LinkParamsType) => void;
fetchExternalLinks: (roomId: string | number) => LinkParamsLinkType[]; fetchExternalLinks: (roomId: string | number) => LinkParamsLinkType[];
isAdmin: boolean; isAdmin: boolean;
fileId?: string | number; itemId?: string | number;
isRoom: boolean;
}; };
type TOptionType = TOption & { type TOptionType = TOption & {
@ -130,18 +132,17 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
setLinkParams, setLinkParams,
fetchExternalLinks, fetchExternalLinks,
isAdmin, isAdmin,
fileId, itemId,
isRoom,
} = props; } = props;
const { roomId, link } = linkParams; const { roomId, link } = linkParams;
const navigate = useNavigate();
const [sharedLinksOptions, setSharedLinksOptions] = useState<TOptionType[]>( const [sharedLinksOptions, setSharedLinksOptions] = useState<TOptionType[]>(
[], [],
); );
const [selectedLink, setSelectedLink] = useState<TOptionType>(); const [selectedLink, setSelectedLink] = useState<TOptionType>();
const [barIsVisible, setBarIsVisible] = useState(!!fileId); const [barIsVisible, setBarIsVisible] = useState(true);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const dataDimensions = [ const dataDimensions = [
@ -164,7 +165,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
height: `${heightValue}${dataDimensions[1].label}`, height: `${heightValue}${dataDimensions[1].label}`,
frameId: "ds-frame", frameId: "ds-frame",
init: true, init: true,
id: fileId, id: itemId,
}; };
const roomConfig = { const roomConfig = {
@ -190,10 +191,14 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
}, },
}; };
const [config, setConfig] = useState(fileId ? fileConfig : roomConfig); const isFile = itemId && !isRoom;
const params = objectToGetParams(config); const [embeddingConfig, setEmbeddingConfig] = useState(
const codeBlock = `<div id="${config.frameId}">Fallback text</div>\n<script src="${SDK_SCRIPT_URL}${params}"></script>`; isFile ? fileConfig : roomConfig,
);
const params = objectToGetParams(embeddingConfig);
const codeBlock = `<div id="${embeddingConfig.frameId}">Fallback text</div>\n<script src="${SDK_SCRIPT_URL}${params}"></script>`;
const currentLink = selectedLink ?? link; const currentLink = selectedLink ?? link;
@ -217,7 +222,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
} }
const showLinkBar = const showLinkBar =
selectedLink?.sharedTo?.password || selectedLink?.sharedTo?.denyDownload; currentLink?.sharedTo?.password || currentLink?.sharedTo?.denyDownload;
const onClose = () => { const onClose = () => {
setEmbeddingPanelData({ visible: false }); setEmbeddingPanelData({ visible: false });
@ -225,28 +230,28 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
const onChangeWidth = (e: React.ChangeEvent<HTMLInputElement>) => { const onChangeWidth = (e: React.ChangeEvent<HTMLInputElement>) => {
setWidthValue(e.target.value); setWidthValue(e.target.value);
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, width: `${e.target.value}${widthDimension.label}` }; return { ...config, width: `${e.target.value}${widthDimension.label}` };
}); });
}; };
const onChangeHeight = (e: React.ChangeEvent<HTMLInputElement>) => { const onChangeHeight = (e: React.ChangeEvent<HTMLInputElement>) => {
setHeightValue(e.target.value); setHeightValue(e.target.value);
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, height: `${e.target.value}${heightDimension.label}` }; return { ...config, height: `${e.target.value}${heightDimension.label}` };
}); });
}; };
const onChangeWidthDimension = (item: TOption) => { const onChangeWidthDimension = (item: TOption) => {
setWidthDimension(item); setWidthDimension(item);
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, width: `${widthValue}${item.label}` }; return { ...config, width: `${widthValue}${item.label}` };
}); });
}; };
const onChangeHeightDimension = (item: TOption) => { const onChangeHeightDimension = (item: TOption) => {
setHeightDimension(item); setHeightDimension(item);
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, height: `${heightValue}${item.label}` }; return { ...config, height: `${heightValue}${item.label}` };
}); });
}; };
@ -257,13 +262,13 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
}; };
const onHeaderChange = () => { const onHeaderChange = () => {
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, showTitle: !config.showTitle }; return { ...config, showTitle: !config.showTitle };
}); });
}; };
const onTitleChange = () => { const onTitleChange = () => {
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, showFilter: !config.showFilter }; return { ...config, showFilter: !config.showFilter };
}); });
}; };
@ -280,7 +285,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
const onChangeSharedLink = (item: TOptionType) => { const onChangeSharedLink = (item: TOptionType) => {
setSelectedLink(item); setSelectedLink(item);
setConfig((config) => { setEmbeddingConfig((config) => {
return { ...config, requestToken: item?.sharedTo?.requestToken }; return { ...config, requestToken: item?.sharedTo?.requestToken };
}); });
}; };
@ -290,8 +295,14 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
}; };
const onOpenDevTools = () => { const onOpenDevTools = () => {
navigate("/portal-settings/developer-tools"); const url = combineUrl(
onClose(); window.location.origin,
window.ClientConfig?.proxy?.url,
config.homepage,
"/portal-settings/developer-tools",
);
window.open(url, "_blank");
}; };
const onKeyPress = (e: KeyboardEvent) => { const onKeyPress = (e: KeyboardEvent) => {
@ -332,10 +343,10 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
}, [roomId, fetchExternalLinks]); }, [roomId, fetchExternalLinks]);
useEffect(() => { useEffect(() => {
if (fileId) { if (itemId) {
getLinks(); getLinks();
} }
}, [fileId, getLinks]); }, [itemId, getLinks]);
const usePrevious = (value: LinkParamsLinkType | null) => { const usePrevious = (value: LinkParamsLinkType | null) => {
const ref = useRef<LinkParamsLinkType | null>(); const ref = useRef<LinkParamsLinkType | null>();
@ -431,12 +442,6 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
</div> </div>
)} )}
<div className="embedding-panel_body"> <div className="embedding-panel_body">
{!fileId && (
<Text fontSize="12px" className="embedding-panel_description">
{t("EmbeddingPanel:EmbeddingDescription")}
</Text>
)}
{sharedLinksOptions && sharedLinksOptions.length > 1 && ( {sharedLinksOptions && sharedLinksOptions.length > 1 && (
<> <>
<Text <Text
@ -492,7 +497,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
/> />
</div> </div>
{!fileId && ( {!isFile && (
<> <>
<Text <Text
className="embedding-panel_header-text" className="embedding-panel_header-text"
@ -506,7 +511,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
<CheckboxElement <CheckboxElement
label={t("Common:Title")} label={t("Common:Title")}
onChange={onHeaderChange} onChange={onHeaderChange}
isChecked={config.showTitle} isChecked={embeddingConfig.showTitle}
img={theme.isBase ? HeaderUrl : HeaderDarkUrl} img={theme.isBase ? HeaderUrl : HeaderDarkUrl}
title={t("JavascriptSdk:Header")} title={t("JavascriptSdk:Header")}
description={t("JavascriptSdk:HeaderDescription")} description={t("JavascriptSdk:HeaderDescription")}
@ -514,7 +519,7 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
<CheckboxElement <CheckboxElement
label={t("JavascriptSdk:SearchFilterAndSort")} label={t("JavascriptSdk:SearchFilterAndSort")}
onChange={onTitleChange} onChange={onTitleChange}
isChecked={config.showFilter} isChecked={embeddingConfig.showFilter}
img={theme.isBase ? SearchUrl : SearchDarkUrl} img={theme.isBase ? SearchUrl : SearchDarkUrl}
title={t("JavascriptSdk:SearchBlock")} title={t("JavascriptSdk:SearchBlock")}
description={t( description={t(
@ -567,18 +572,8 @@ const EmbeddingPanelComponent = (props: EmbeddingPanelProps) => {
); );
}; };
export default inject( export default inject<TStore>(
({ ({ dialogsStore, settingsStore, userStore, publicRoomStore }) => {
dialogsStore,
settingsStore,
userStore,
publicRoomStore,
}: {
dialogsStore: DialogsStore;
settingsStore: SettingsStore;
userStore: UserStore;
publicRoomStore: PublicRoomStore;
}) => {
const { const {
embeddingPanelData, embeddingPanelData,
setEmbeddingPanelData, setEmbeddingPanelData,
@ -594,7 +589,8 @@ export default inject(
theme, theme,
currentColorScheme, currentColorScheme,
visible: embeddingPanelData.visible, visible: embeddingPanelData.visible,
fileId: embeddingPanelData.fileId, itemId: embeddingPanelData.item?.id,
isRoom: embeddingPanelData.item?.isRoom,
setEmbeddingPanelData, setEmbeddingPanelData,
setEditLinkPanelIsVisible, setEditLinkPanelIsVisible,
linkParams, linkParams,

View File

@ -27,7 +27,6 @@
import ClearTrashReactSvgUrl from "PUBLIC_DIR/images/clear.trash.react.svg?url"; import ClearTrashReactSvgUrl from "PUBLIC_DIR/images/clear.trash.react.svg?url";
import ReconnectSvgUrl from "PUBLIC_DIR/images/reconnect.svg?url"; import ReconnectSvgUrl from "PUBLIC_DIR/images/reconnect.svg?url";
import SettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url"; import SettingsReactSvgUrl from "PUBLIC_DIR/images/catalog.settings.react.svg?url";
import CopyToReactSvgUrl from "PUBLIC_DIR/images/copyTo.react.svg?url";
import DownloadReactSvgUrl from "PUBLIC_DIR/images/download.react.svg?url"; import DownloadReactSvgUrl from "PUBLIC_DIR/images/download.react.svg?url";
import MoveReactSvgUrl from "PUBLIC_DIR/images/move.react.svg?url"; import MoveReactSvgUrl from "PUBLIC_DIR/images/move.react.svg?url";
import RenameReactSvgUrl from "PUBLIC_DIR/images/rename.react.svg?url"; import RenameReactSvgUrl from "PUBLIC_DIR/images/rename.react.svg?url";
@ -45,6 +44,7 @@ import PublicRoomIconUrl from "PUBLIC_DIR/images/public-room.react.svg?url";
import LeaveRoomSvgUrl from "PUBLIC_DIR/images/logout.react.svg?url"; import LeaveRoomSvgUrl from "PUBLIC_DIR/images/logout.react.svg?url";
import CatalogRoomsReactSvgUrl from "PUBLIC_DIR/images/catalog.rooms.react.svg?url"; import CatalogRoomsReactSvgUrl from "PUBLIC_DIR/images/catalog.rooms.react.svg?url";
import TabletLinkReactSvgUrl from "PUBLIC_DIR/images/tablet-link.react.svg?url"; import TabletLinkReactSvgUrl from "PUBLIC_DIR/images/tablet-link.react.svg?url";
import CodeReactSvgUrl from "PUBLIC_DIR/images/code.react.svg?url";
import React from "react"; import React from "react";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
@ -290,6 +290,7 @@ const SectionHeaderContent = (props) => {
startUpload, startUpload,
getFolderModel, getFolderModel,
onCreateRoom, onCreateRoom,
onOpenEmbeddingSettings,
} = props; } = props;
const navigate = useNavigate(); const navigate = useNavigate();
@ -589,11 +590,20 @@ const SectionHeaderContent = (props) => {
onClick: () => onClickEditRoom(selectedFolder), onClick: () => onClickEditRoom(selectedFolder),
disabled: !isRoom || !security?.EditRoom, disabled: !isRoom || !security?.EditRoom,
}, },
{
id: "header_option_invite-users-to-room",
key: "invite-users-to-room",
label: t("Common:InviteUsers"),
icon: PersonReactSvgUrl,
onClick: () =>
onClickInviteUsers(selectedFolder.id, selectedFolder.roomType),
disabled: !isRoom || !security?.EditAccess,
},
{ {
id: "header_option_copy-external-link", id: "header_option_copy-external-link",
key: "copy-external-link", key: "copy-external-link",
label: t("Files:CopySharedLink"), label: t("Files:CopySharedLink"),
icon: CopyToReactSvgUrl, icon: TabletLinkReactSvgUrl,
onClick: async () => { onClick: async () => {
if (primaryLink) { if (primaryLink) {
copyShareLink(primaryLink.sharedTo.shareLink); copyShareLink(primaryLink.sharedTo.shareLink);
@ -613,13 +623,12 @@ const SectionHeaderContent = (props) => {
isArchive, isArchive,
}, },
{ {
id: "header_option_invite-users-to-room", id: "header_option_room-embed",
key: "invite-users-to-room", key: "room-embed",
label: t("Common:InviteUsers"), label: t("Files:Embed"),
icon: PersonReactSvgUrl, icon: CodeReactSvgUrl,
onClick: () => onClick: () => onOpenEmbeddingSettings(selectedFolder),
onClickInviteUsers(selectedFolder.id, selectedFolder.roomType), disabled: !security?.Embed,
disabled: !isRoom || !security?.EditAccess,
}, },
{ {
id: "header_option_room-info", id: "header_option_room-info",
@ -635,6 +644,14 @@ const SectionHeaderContent = (props) => {
isSeparator: true, isSeparator: true,
disabled: isRecycleBinFolder, disabled: isRecycleBinFolder,
}, },
{
id: "header_option_download",
key: "download",
label: t("Common:Download"),
onClick: onDownloadAction,
disabled: !security?.Download,
icon: DownloadReactSvgUrl,
},
{ {
id: "header_option_archive-room", id: "header_option_archive-room",
key: "archive-room", key: "archive-room",
@ -663,14 +680,6 @@ const SectionHeaderContent = (props) => {
onClick: onLeaveRoom, onClick: onLeaveRoom,
disabled: isArchive || !inRoom || isPublicRoom, disabled: isArchive || !inRoom || isPublicRoom,
}, },
{
id: "header_option_download",
key: "download",
label: t("Common:Download"),
onClick: onDownloadAction,
disabled: !security?.Download,
icon: DownloadReactSvgUrl,
},
{ {
id: "header_option_unarchive-room", id: "header_option_unarchive-room",
key: "unarchive-room", key: "unarchive-room",
@ -1178,6 +1187,7 @@ export default inject(
onCreateAndCopySharedLink, onCreateAndCopySharedLink,
getFolderModel, getFolderModel,
onCreateRoom, onCreateRoom,
onOpenEmbeddingSettings,
} = contextOptionsStore; } = contextOptionsStore;
const canRestoreAll = isArchiveFolder && roomsForRestore.length > 0; const canRestoreAll = isArchiveFolder && roomsForRestore.length > 0;
@ -1361,6 +1371,7 @@ export default inject(
onClickReconnectStorage, onClickReconnectStorage,
getFolderModel, getFolderModel,
onCreateRoom, onCreateRoom,
onOpenEmbeddingSettings,
}; };
}, },
)( )(

View File

@ -449,9 +449,11 @@ class ContextOptionsStore {
this.selectedFolderStore; this.selectedFolderStore;
const { setLinkParams, setEmbeddingPanelData } = this.dialogsStore; const { setLinkParams, setEmbeddingPanelData } = this.dialogsStore;
const sharedItem = shared const sharedItem = item.isRoom
? getSelectedFolder() ? item
: navigationPath.find((r) => r.shared); : shared
? getSelectedFolder()
: navigationPath.find((r) => r.shared);
if (!sharedItem) return; if (!sharedItem) return;
@ -464,7 +466,7 @@ class ContextOptionsStore {
isFormRoom, isFormRoom,
}); });
setEmbeddingPanelData({ visible: true, fileId: item.id }); setEmbeddingPanelData({ visible: true, item });
}; };
onCreateAndCopySharedLink = async (item, t) => { onCreateAndCopySharedLink = async (item, t) => {

View File

@ -103,7 +103,7 @@ class DialogsStore {
createRoomConfirmDialogVisible = false; createRoomConfirmDialogVisible = false;
changeUserTypeDialogVisible = false; changeUserTypeDialogVisible = false;
editLinkPanelIsVisible = false; editLinkPanelIsVisible = false;
embeddingPanelData = { visible: false, fileId: null }; embeddingPanelData = { visible: false, item: null };
submitToGalleryDialogVisible = false; submitToGalleryDialogVisible = false;
linkParams = null; linkParams = null;
leaveRoomDialogVisible = false; leaveRoomDialogVisible = false;

View File

@ -1606,6 +1606,7 @@ class FilesStore {
folders: data.folders, folders: data.folders,
...data.current, ...data.current,
inRoom: !!data.current.inRoom, inRoom: !!data.current.inRoom,
isRoom: !!data.current.roomType,
pathParts: data.pathParts, pathParts: data.pathParts,
navigationPath, navigationPath,
...{ new: data.new }, ...{ new: data.new },
@ -2029,6 +2030,7 @@ class FilesStore {
const canCopy = item.security?.Copy; const canCopy = item.security?.Copy;
const canDuplicate = item.security?.Duplicate; const canDuplicate = item.security?.Duplicate;
const canDownload = item.security?.Download; const canDownload = item.security?.Download;
const canEmbed = item.security?.Embed;
if (isFile) { if (isFile) {
const shouldFillForm = item.viewAccessibility.WebRestrictedEditing; const shouldFillForm = item.viewAccessibility.WebRestrictedEditing;
@ -2193,10 +2195,7 @@ class FilesStore {
} }
if (!canViewFile || isRecycleBinFolder) { if (!canViewFile || isRecycleBinFolder) {
fileOptions = this.removeOptions(fileOptions, [ fileOptions = this.removeOptions(fileOptions, ["preview"]);
"preview",
"embedding-settings",
]);
} }
if (!canOpenPlayer || isRecycleBinFolder) { if (!canOpenPlayer || isRecycleBinFolder) {
@ -2328,7 +2327,7 @@ class FilesStore {
]); ]);
} }
if (this.publicRoomStore.isPublicRoom) { if (this.publicRoomStore.isPublicRoom || !canEmbed) {
fileOptions = this.removeOptions(fileOptions, ["embedding-settings"]); fileOptions = this.removeOptions(fileOptions, ["embedding-settings"]);
} }
@ -2375,6 +2374,7 @@ class FilesStore {
"edit-room", "edit-room",
"invite-users-to-room", "invite-users-to-room",
"external-link", "external-link",
"embedding-settings",
"room-info", "room-info",
"pin-room", "pin-room",
"unpin-room", "unpin-room",
@ -2443,6 +2443,10 @@ class FilesStore {
: (roomOptions = this.removeOptions(roomOptions, ["unmute-room"])); : (roomOptions = this.removeOptions(roomOptions, ["unmute-room"]));
} }
if (this.publicRoomStore.isPublicRoom || !canEmbed) {
roomOptions = this.removeOptions(roomOptions, ["embedding-settings"]);
}
if (!canViewRoomInfo) { if (!canViewRoomInfo) {
roomOptions = this.removeOptions(roomOptions, ["room-info"]); roomOptions = this.removeOptions(roomOptions, ["room-info"]);
} }