DocSpace-client/web/ASC.Web.Editor/src/Editor.jsx

427 lines
11 KiB
React
Raw Normal View History

2021-03-06 15:50:06 +00:00
import React, { useEffect, useState } from "react";
2021-03-05 18:15:48 +00:00
import Toast from "@appserver/components/toast";
import toastr from "@appserver/components/toast/toastr";
import Box from "@appserver/components/box";
import { regDesktop } from "@appserver/common/desktop";
import Loaders from "@appserver/common/components/Loaders";
import {
2021-03-22 09:12:34 +00:00
combineUrl,
2021-03-05 18:15:48 +00:00
getObjectByLocation,
//showLoader,
//hideLoader,
tryRedirectTo,
} from "@appserver/common/utils";
import {
getDocServiceUrl,
openEdit,
setEncryptionKeys,
getEncryptionAccess,
} from "@appserver/common/api/files";
import { checkIsAuthenticated } from "@appserver/common/api/user";
import { getUser } from "@appserver/common/api/people";
import throttle from "lodash/throttle";
2021-03-06 15:50:06 +00:00
import { isIOS, deviceType } from "react-device-detect";
import { homepage } from "../package.json";
2021-03-05 18:15:48 +00:00
import "./custom.scss";
2021-03-22 09:12:34 +00:00
import { AppServerConfig } from "@appserver/common/constants";
2021-03-26 12:05:41 +00:00
import SharingPanel from "files/SharingPanel";
import { inject, observer } from "mobx-react";
import { Provider as MobxProvider } from "mobx-react";
import store from "studio/store";
import initFilesStore from "files/InitFilesStore";
import filesStore from "files/FilesStore";
import uploadDataStore from "files/UploadDataStore";
import dialogsStore from "files/DialogsStore";
import treeFoldersStore from "files/TreeFoldersStore";
import i18n from "./i18n";
2021-03-05 18:15:48 +00:00
let documentIsReady = false;
let docTitle = null;
let fileType = null;
2021-03-26 12:05:41 +00:00
let config;
2021-03-05 18:15:48 +00:00
let docSaved = null;
2021-03-26 12:05:41 +00:00
let docEditor;
const url = window.location.href;
const filesUrl = url.substring(0, url.indexOf("/doceditor"));
2021-03-26 12:05:41 +00:00
const Editor = ({
uploadPanelVisible,
sharingPanelVisible,
setSharingPanelVisible,
getShareUsers,
2021-03-26 12:05:41 +00:00
}) => {
2021-03-06 15:50:06 +00:00
const urlParams = getObjectByLocation(window.location);
const fileId = urlParams
? urlParams.fileId || urlParams.fileid || null
: null;
const doc = urlParams ? urlParams.doc || null : null;
const isDesktop = window["AscDesktopEditor"] !== undefined;
const [isLoading, setIsLoading] = useState(true);
const [isAuthenticated, setIsAuthenticated] = useState(true);
2021-03-05 18:15:48 +00:00
2021-03-06 15:50:06 +00:00
const throttledChangeTitle = throttle(
() => changeTitle(docSaved, docTitle),
500
);
2021-03-26 12:05:41 +00:00
useEffect(() => {
init();
2021-03-26 12:05:41 +00:00
}, []);
const getShareUsersList = (isInit) => {
let sharingSettings = [];
const folderId = [];
getShareUsers(folderId, [+fileId]).then((result) => {
for (let i = 1; i < result.length; i++) {
let resultAccess =
result[i].access === 1
? i18n.t("FullAccess")
: result[i].access === 2
? i18n.t("ReadOnly")
: result[i].access === 3
? i18n.t("DenyAccess")
: result[i].access === 4
? i18n.t("CustomFilter")
: result[i].access === 5
? i18n.t("Review")
: result[i].access === 6
? i18n.t("Comment")
: result[i].access === 7
? i18n.t("FormFilling")
: "";
let obj = {
user: result[i].sharedTo.displayName || result[i].sharedTo.name,
permissions: resultAccess,
};
sharingSettings.push(obj);
}
isInit
? (config.document.info = {
...config.document.info,
sharingSettings,
})
: docEditor.setSharingSettings({
sharingSettings,
});
});
};
2021-03-28 16:21:08 +00:00
const updateUsersRightsList = () => {
if (docEditor) getShareUsersList(false);
};
2021-03-06 15:50:06 +00:00
const init = async () => {
try {
2021-03-05 18:15:48 +00:00
if (!fileId) return;
console.log("PureEditor componentDidMount", fileId, doc);
if (isIPad()) {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty("--vh", `${vh}px`);
}
//showLoader();
const docApiUrl = await getDocServiceUrl();
if (!doc) {
2021-03-06 15:50:06 +00:00
const success = await checkIsAuthenticated();
2021-03-05 18:15:48 +00:00
2021-03-06 15:50:06 +00:00
if (!success) {
2021-03-22 09:12:34 +00:00
return tryRedirectTo(combineUrl(AppServerConfig.proxyURL, "/login"));
2021-03-06 15:50:06 +00:00
} else {
setIsAuthenticated(success);
}
2021-03-05 18:15:48 +00:00
}
2021-03-26 12:05:41 +00:00
config = await openEdit(fileId, doc);
2021-03-05 18:15:48 +00:00
if (isDesktop) {
const isEncryption =
config.editorConfig["encryptionKeys"] !== undefined;
const user = await getUser();
regDesktop(
user,
isEncryption,
config.editorConfig.encryptionKeys,
(keys) => {
setEncryptionKeys(keys);
},
true,
(callback) => {
getEncryptionAccess(fileId)
.then((keys) => {
var data = {
keys,
};
callback(data);
})
.catch((error) => {
console.log(error);
toastr.error(
typeof error === "string" ? error : error.message,
null,
0,
true
);
});
}
);
}
if (config) {
getShareUsersList(true);
}
2021-03-06 15:50:06 +00:00
setIsLoading(false);
loadDocApi(docApiUrl, () => onLoad(config));
2021-03-05 18:15:48 +00:00
} catch (error) {
console.log(error);
toastr.error(
typeof error === "string" ? error : error.message,
null,
0,
true
);
}
2021-03-06 15:50:06 +00:00
};
const isIPad = () => {
return isIOS && deviceType === "tablet";
};
const setFavicon = (fileType) => {
const favicon = document.getElementById("favicon");
if (!favicon) return;
let icon = null;
switch (fileType) {
case "docx":
icon = "text.ico";
break;
case "pptx":
icon = "presentation.ico";
break;
case "xlsx":
icon = "spreadsheet.ico";
break;
default:
break;
}
if (icon) favicon.href = `${homepage}/images/${icon}`;
};
const changeTitle = (docSaved, docTitle) => {
docSaved ? setDocumentTitle(docTitle) : setDocumentTitle(`*${docTitle}`);
};
const setDocumentTitle = (subTitle = null) => {
//const { isAuthenticated, settingsStore, product: currentModule } = auth;
//const { organizationName } = settingsStore;
const organizationName = "ONLYOFFICE"; //TODO: Replace to API variant
const moduleTitle = "Documents"; //TODO: Replace to API variant
let title;
if (subTitle) {
if (isAuthenticated && moduleTitle) {
title = subTitle + " - " + moduleTitle;
} else {
title = subTitle + " - " + organizationName;
}
} else if (moduleTitle && organizationName) {
title = moduleTitle + " - " + organizationName;
} else {
title = organizationName;
}
document.title = title;
};
const loadDocApi = (docApiUrl, onLoadCallback) => {
2021-03-05 18:15:48 +00:00
const script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("id", "scripDocServiceAddress");
script.onload = onLoadCallback;
script.src = docApiUrl;
script.async = true;
console.log("PureEditor componentDidMount: added script");
document.body.appendChild(script);
};
2021-03-06 15:50:06 +00:00
const onLoad = (config) => {
2021-03-05 18:15:48 +00:00
console.log("Editor config: ", config);
2021-03-26 12:05:41 +00:00
2021-03-05 18:15:48 +00:00
try {
console.log(config);
docTitle = config.document.title;
fileType = config.document.fileType;
setFavicon(fileType);
setDocumentTitle(docTitle);
if (window.innerWidth < 720) {
config.type = "mobile";
}
config.editorConfig.customization = {
...config.editorConfig.customization,
goback: {
blank: true,
requestClose: false,
text: i18n.t("FileLocation"),
url: `${filesUrl}`,
},
};
2021-03-05 18:15:48 +00:00
const events = {
events: {
2021-03-06 15:50:06 +00:00
onAppReady: onSDKAppReady,
onDocumentStateChange: onDocumentStateChange,
onMetaChange: onMetaChange,
onDocumentReady: onDocumentReady,
onInfo: onSDKInfo,
onWarning: onSDKWarning,
onError: onSDKError,
...(config.document.permissions.edit && {
onRequestSharingSettings: onSDKRequestSharingSettings,
}),
2021-03-05 18:15:48 +00:00
},
};
const newConfig = Object.assign(config, events);
if (!window.DocsAPI) throw new Error("DocsAPI is not defined");
2021-03-26 12:05:41 +00:00
docEditor = window.DocsAPI.DocEditor("editor", newConfig);
2021-03-05 18:15:48 +00:00
} catch (error) {
console.log(error);
toastr.error(error.message, null, 0, true);
}
};
2021-03-06 15:50:06 +00:00
const onSDKAppReady = () => {
2021-03-26 14:35:44 +00:00
console.log("ONLYOFFICE Document Editor is ready");
2021-03-05 18:15:48 +00:00
};
2021-03-06 15:50:06 +00:00
const onSDKInfo = (event) => {
2021-03-05 18:15:48 +00:00
console.log(
"ONLYOFFICE Document Editor is opened in mode " + event.data.mode
);
};
2021-03-26 12:05:41 +00:00
const onSDKRequestSharingSettings = () => {
setSharingPanelVisible(true);
};
2021-03-06 15:50:06 +00:00
const onSDKWarning = (event) => {
2021-03-05 18:15:48 +00:00
console.log(
"ONLYOFFICE Document Editor reports a warning: code " +
event.data.warningCode +
", description " +
event.data.warningDescription
);
};
2021-03-06 15:50:06 +00:00
const onSDKError = (event) => {
2021-03-05 18:15:48 +00:00
console.log(
"ONLYOFFICE Document Editor reports an error: code " +
event.data.errorCode +
", description " +
event.data.errorDescription
);
};
2021-03-06 15:50:06 +00:00
const onDocumentStateChange = (event) => {
2021-03-05 18:15:48 +00:00
if (!documentIsReady) return;
docSaved = !event.data;
throttledChangeTitle();
};
2021-03-06 15:50:06 +00:00
const onDocumentReady = () => {
2021-03-05 18:15:48 +00:00
documentIsReady = true;
};
2021-03-06 15:50:06 +00:00
const onMetaChange = (event) => {
2021-03-05 18:15:48 +00:00
const newTitle = event.data.title;
if (newTitle && newTitle !== docTitle) {
setDocumentTitle(newTitle);
docTitle = newTitle;
}
};
//debugger;
2021-03-06 15:50:06 +00:00
return (
<Box
widthProp="100vw"
heightProp={isIPad() ? "calc(var(--vh, 1vh) * 100)" : "100vh"}
>
<Toast />
{!isLoading ? (
<>
<div id="editor"></div>
{sharingPanelVisible && (
<SharingPanel
key="sharing-panel"
uploadPanelVisible={uploadPanelVisible}
isSharingPanelVisible={sharingPanelVisible}
openFileId={fileId}
2021-03-28 16:21:08 +00:00
updateUsersRightsList={updateUsersRightsList}
editorAccessRights={config && config.document.permissions}
documentTitle={config && config.document.title}
/>
)}
</>
2021-03-06 15:50:06 +00:00
) : (
<Box paddingProp="16px">
<Loaders.Rectangle height="96vh" />
</Box>
)}
</Box>
);
};
2021-03-05 18:15:48 +00:00
const EditorWrapper = inject(
({ uploadDataStore, dialogsStore, filesStore }) => {
const { uploadPanelVisible } = uploadDataStore;
const { getShareUsers } = filesStore;
const { sharingPanelVisible, setSharingPanelVisible } = dialogsStore;
return {
uploadPanelVisible,
sharingPanelVisible,
setSharingPanelVisible,
getShareUsers,
};
}
)(observer(Editor));
2021-03-26 12:05:41 +00:00
export default () => (
<MobxProvider
{...store}
initFilesStore={initFilesStore}
filesStore={filesStore}
uploadDataStore={uploadDataStore}
dialogsStore={dialogsStore}
treeFoldersStore={treeFoldersStore}
>
<EditorWrapper />
</MobxProvider>
);