Delete @docspace/editor
This commit is contained in:
parent
6d80c6f343
commit
271b4fb63e
@ -12,13 +12,9 @@
|
||||
"name": "🔑 @docspace/login",
|
||||
"path": "packages/login",
|
||||
},
|
||||
{
|
||||
"name": "📄 @docspace/editor",
|
||||
"path": "packages/editor",
|
||||
},
|
||||
{
|
||||
"name": "📄 @docspace/doceditor",
|
||||
"path": "packages/doceditor"
|
||||
"path": "packages/doceditor",
|
||||
},
|
||||
{
|
||||
"name": "🗂 @docspace/management",
|
||||
|
@ -12,12 +12,12 @@
|
||||
"yarn": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node ./common/scripts/before-build.js && yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/editor,@docspace/management}' run build",
|
||||
"build": "node ./common/scripts/before-build.js && yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/doceditor,@docspace/management}' run build",
|
||||
"bump": "yarn version apply --all",
|
||||
"clean": "yarn workspaces foreach -vptiR run clean",
|
||||
"deploy": "shx rm -rf ../publish/web && yarn workspaces foreach -ptR --from '{@docspace/client,@docspace/login,@docspace/editor,@docspace/management}' run deploy && shx cp -r public ../publish/web/ && node common/scripts/minify-common-locales.js",
|
||||
"deploy": "shx rm -rf ../publish/web && yarn workspaces foreach -ptR --from '{@docspace/client,@docspace/login,@docspace/doceditor,@docspace/management}' run deploy && shx cp -r public ../publish/web/ && node common/scripts/minify-common-locales.js",
|
||||
"start": "node ./common/scripts/before-build.js && yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/doceditor,@docspace/management}' run start",
|
||||
"start-prod": "yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/editor,@docspace/management}' run start-prod",
|
||||
"start-prod": "yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/doceditor,@docspace/management}' run start-prod",
|
||||
"storybook": "yarn workspace @docspace/shared storybook",
|
||||
"storybook-build": "yarn workspace @docspace/shared run storybook-build",
|
||||
"storybook-serve": "yarn workspace @docspace/shared run storybook-serve",
|
||||
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"bugfixes": true
|
||||
}
|
||||
],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"@loadable/babel-plugin",
|
||||
"babel-plugin-styled-components",
|
||||
["@babel/plugin-proposal-class-properties", { "loose": false }],
|
||||
"@babel/plugin-proposal-export-default-from"
|
||||
],
|
||||
"ignore": ["node_modules", "build"],
|
||||
"sourceType": "unambiguous"
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
module.exports = {
|
||||
extends: "../shared/.eslintrc.cjs",
|
||||
parserOptions: {
|
||||
project: "tsconfig.eslint.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
ignorePatterns: [
|
||||
"./tsconfig.json",
|
||||
"coverage/**",
|
||||
"storybook-static/**",
|
||||
"*.js",
|
||||
],
|
||||
};
|
1
packages/editor/.gitattributes
vendored
1
packages/editor/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
dist/* linguist-vendored=false
|
119
packages/editor/.gitignore
vendored
119
packages/editor/.gitignore
vendored
@ -1,119 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
|
||||
autoGeneratedTranslations.js
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "../shared/.prettierrc.json"
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
FROM node:12
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json ./
|
||||
COPY yarn.lock ./
|
||||
|
||||
RUN yarn install
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN yarn build
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD [ "yarn", "build:start" ]
|
@ -1,11 +0,0 @@
|
||||
module.exports = {
|
||||
presets: ["@babel/preset-env", "@babel/preset-react"],
|
||||
plugins: [
|
||||
"@loadable/babel-plugin",
|
||||
"babel-plugin-styled-components",
|
||||
["@babel/plugin-proposal-class-properties", { loose: false }],
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
],
|
||||
//ignore: ["node_modules", "build"],
|
||||
//sourceType: "unambiguous",
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"components": ["@docspace/shared/components"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
{
|
||||
"name": "@docspace/editor",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"homepage": "/doceditor",
|
||||
"scripts": {
|
||||
"build": "yarn clean && yarn build:translations && yarn build:client && yarn build:server",
|
||||
"build:server": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --config webpack/webpack.server.js",
|
||||
"build:client": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --config webpack/webpack.client.js",
|
||||
"build:dev-server": "NODE_OPTIONS=--openssl-legacy-provider webpack --config webpack/webpack.server.js",
|
||||
"build:dev-client": "NODE_OPTIONS=--openssl-legacy-provider webpack --config webpack/webpack.client.js",
|
||||
"build:translations": "node scripts/buildTranslations.js",
|
||||
"clean": "shx rm -rf dist",
|
||||
"start": "yarn clean && yarn build:translations && npm-run-all --parallel start:client start:server start:common",
|
||||
"start:client": "NODE_OPTIONS=--openssl-legacy-provider webpack --config webpack/webpack.client.js --watch --no-cache",
|
||||
"start:server": "NODE_OPTIONS=--openssl-legacy-provider webpack --config webpack/webpack.server.js --watch --no-cache",
|
||||
"start:common": "yarn build:dev-client && yarn build:dev-server && NODE_OPTIONS=--openssl-legacy-provider nodemon --watch dist/server.js dist/server.js",
|
||||
"start-prod": "NODE_OPTIONS=--openssl-legacy-provider node dist/server.js",
|
||||
"deploy": "shx --silent mkdir -p ../../../publish/web/editor && shx cp -r dist/* ../../../publish/web/editor && shx cp -f src/server/config/config-deploy.json ../../../publish/web/editor/config.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.18.10",
|
||||
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.0",
|
||||
"@babel/register": "^7.21.0",
|
||||
"@loadable/babel-plugin": "^5.15.3",
|
||||
"@loadable/component": "^5.15.3",
|
||||
"@loadable/server": "^5.15.3",
|
||||
"@loadable/webpack-plugin": "^5.15.2",
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"babel-loader": "^8.3.0",
|
||||
"babel-plugin-styled-components": "^1.13.3",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.3",
|
||||
"external-remotes-plugin": "^1.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "5.5.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"nodemon": "^2.0.22",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^13.2.1",
|
||||
"shx": "^0.3.4",
|
||||
"source-map-loader": "^4.0.1",
|
||||
"style-loader": "^3.3.2",
|
||||
"styled-components": "^5.3.9",
|
||||
"terser-webpack-plugin": "^5.3.7",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "5.76.3",
|
||||
"webpack-cli": "4.10.0",
|
||||
"webpack-dev-server": "4.13.1",
|
||||
"webpack-filter-warnings-plugin": "^1.2.1",
|
||||
"webpack-hot-middleware": "^2.25.3",
|
||||
"webpack-manifest-plugin": "^5.0.0",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"id": "e67be73d-f9ae-4ce1-8fec-1880cb518cb4",
|
||||
"title": "ONLYOFFICE",
|
||||
"socketPath": "/doceditor/ws",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.297.0",
|
||||
"@babel/eslint-parser": "^7.21.8",
|
||||
"@onlyoffice/document-editor-react": "1.3.0",
|
||||
"@types/eslint": "^8.44.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"aws-crt": "^1.15.13",
|
||||
"bufferutil": "^4.0.7",
|
||||
"compression": "^1.7.4",
|
||||
"date-and-time": "^2.4.3",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-storybook": "^0.6.15",
|
||||
"express": "^4.18.2",
|
||||
"express-xss-sanitizer": "^1.1.6",
|
||||
"i18next-express-middleware": "^2.0.0",
|
||||
"i18next-fs-backend": "^1.2.0",
|
||||
"morgan": "^1.10.0",
|
||||
"nconf": "^0.12.0",
|
||||
"prettier": "^3.1.0",
|
||||
"utf-8-validate": "^5.0.10",
|
||||
"winston": "^3.8.2",
|
||||
"winston-cloudwatch": "^6.1.1",
|
||||
"winston-daily-rotate-file": "^4.7.1"
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "يمكنك فتح المستند من خلال البوابة أو بواسطة تطبيق الهاتف",
|
||||
"OpenInApp": "فتح بواسطة التطبيق",
|
||||
"OpeningDocument": "فتح المستند",
|
||||
"StayInBrowser": "متابعة من خلال المتصفح"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "وثائق",
|
||||
"ErrorConnectionLost": "الاتصال مفقود",
|
||||
"FileLocation": "افتح موقع ملف",
|
||||
"FileName": "اسم الملف",
|
||||
"ImageFileType": "الصور",
|
||||
"MailMergeFileType": "حدد ملف XLSX",
|
||||
"OpenSavedDocument": "افتح المستند المحفوظ في علامة تبويب جديدة",
|
||||
"SelectFilesType": "حدد نوع الملفات : {{fileType}}",
|
||||
"UsersWithoutAccess": "بعض المستخدمين الذين تريد ذكرهم ليس لديهم حق الوصول إلى الغرفة: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Sənədi portalda və ya mobil proqramda aça bilərsiniz.",
|
||||
"OpenInApp": "Tətbiqdə açın",
|
||||
"OpeningDocument": "Sənədin açılması",
|
||||
"StayInBrowser": "Brauzerdə qalın"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "Sənədlər",
|
||||
"ErrorConnectionLost": "Bağlantı itdi",
|
||||
"FileLocation": "Faylın yerləşdiyi yeri açın",
|
||||
"FileName": "Fayl adı",
|
||||
"ImageFileType": "Şəkillər",
|
||||
"MailMergeFileType": "XLSX formatlı faylı seçin",
|
||||
"OpenSavedDocument": "Yadda saxlanmış sənədi yeni tabda açın",
|
||||
"SelectFilesType": "Bu növ faylları seçin: {{fileType}}",
|
||||
"UsersWithoutAccess": "Qeyd etmək istədiyiniz bəzi istifadəçilərin otağa girişi yoxdur: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Можете да отворите документа в портала или в мобилното приложение",
|
||||
"OpenInApp": "Отвори в приложението",
|
||||
"OpeningDocument": "Отваряне на документ",
|
||||
"StayInBrowser": "Остани в браузъра"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "документи",
|
||||
"ErrorConnectionLost": "Връзката е изгубена",
|
||||
"FileLocation": "Mестоположението на файла",
|
||||
"FileName": "Име на файла",
|
||||
"ImageFileType": "снимки",
|
||||
"MailMergeFileType": "Изберете файл във XLSX формат",
|
||||
"OpenSavedDocument": "Отворете записания документ в нов раздел",
|
||||
"SelectFilesType": "Изберете файлове от тип: {{fileType}}",
|
||||
"UsersWithoutAccess": "Някои потребители, които искате да споменете, нямат достъп до стаята: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Dokument můžete otevřít na portálu nebo v mobilní aplikaci",
|
||||
"OpenInApp": "Otevřít v aplikaci",
|
||||
"OpeningDocument": "Otevření dokumentu",
|
||||
"StayInBrowser": "Zůstat v prohlížeči"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dokumenty",
|
||||
"ErrorConnectionLost": "Spojení je ztraceno",
|
||||
"FileLocation": "Otevřít umístění souboru",
|
||||
"FileName": "Název souboru",
|
||||
"ImageFileType": "obrázky",
|
||||
"MailMergeFileType": "Vybrat soubor ve formátu XLSX",
|
||||
"OpenSavedDocument": "Otevřít uložený dokument na nové kartě",
|
||||
"SelectFilesType": "Vybrat soubory typu: {{fileType}}",
|
||||
"UsersWithoutAccess": "Někteří uživatelé, které chcete zmínit, nemají do místnosti přístup: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Sie können das Dokument im Portal oder in der mobilen App öffnen",
|
||||
"OpenInApp": "In der App öffnen",
|
||||
"OpeningDocument": "Dokument wird geöffnet",
|
||||
"StayInBrowser": "Im Browser bleiben"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "Dokumente",
|
||||
"ErrorConnectionLost": "Verbindung ist unterbrochen",
|
||||
"FileLocation": "Dateispeicherort öffnen",
|
||||
"FileName": "Dateiname",
|
||||
"ImageFileType": "Bilder",
|
||||
"MailMergeFileType": "Datei im XLSX-Format auswählen",
|
||||
"OpenSavedDocument": "Das gespeicherte Dokument im neuen Tab öffnen",
|
||||
"SelectFilesType": "Dateien dieses Typs auswählen: {{fileType}}",
|
||||
"UsersWithoutAccess": "Einige Benutzer, die Sie erwähnen möchten, haben keinen Zugang zum Raum: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Μπορείτε να ανοίξετε το έγγραφο στην πύλη ή στην εφαρμογή για κινητά",
|
||||
"OpenInApp": "Άνοιγμα στην εφαρμογή",
|
||||
"OpeningDocument": "Άνοιγμα εγγράφου",
|
||||
"StayInBrowser": "Παραμονή στο πρόγραμμα περιήγησης"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "Έγγραφα",
|
||||
"ErrorConnectionLost": "Η σύνδεση χάθηκε",
|
||||
"FileLocation": "Άνοιγμα τοποθεσίας αρχείου",
|
||||
"FileName": "Όνομα αρχείου",
|
||||
"ImageFileType": "Εικόνες",
|
||||
"MailMergeFileType": "Επιλέξτε το αρχείο σε μορφή XLSX",
|
||||
"OpenSavedDocument": "Άνοιγμα αποθηκευμένου εγγράφου σε νέα καρτέλα",
|
||||
"SelectFilesType": "Επιλέξτε αρχεία τύπου: {{fileType}}",
|
||||
"UsersWithoutAccess": "Ορισμένοι χρήστες τους οποίους θέλετε να αναφέρετε δεν έχουν πρόσβαση στο δωμάτιο: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "You can open the document on the portal or in the mobile application",
|
||||
"OpenInApp": "Open in the app",
|
||||
"OpeningDocument": "Opening a document",
|
||||
"StayInBrowser": "Stay in the browser"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documents",
|
||||
"ErrorConnectionLost": "Connection is lost",
|
||||
"FileLocation": "Open file location",
|
||||
"FileName": "File name",
|
||||
"ImageFileType": "images",
|
||||
"MailMergeFileType": "Select .XLSX file",
|
||||
"OpenSavedDocument": "Open saved document in new tab",
|
||||
"SelectFilesType": "Select files type: {{fileType}}",
|
||||
"UsersWithoutAccess": "Some users whom you want to mention don't have access to the room: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Usted puede abrir el documento en el portal o en la aplicación móvil",
|
||||
"OpenInApp": "Abrir en la aplicación",
|
||||
"OpeningDocument": "Abriendo el documento",
|
||||
"StayInBrowser": "Quedarse en el navegador"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documentos",
|
||||
"ErrorConnectionLost": "Se ha perdido la conexión",
|
||||
"FileLocation": "Abrir ubicación del archivo",
|
||||
"FileName": "Nombre de archivo",
|
||||
"ImageFileType": "imágenes",
|
||||
"MailMergeFileType": "Seleccionar archivo en formato XLSX",
|
||||
"OpenSavedDocument": "Abrir el documento guardado en una nueva pestaña",
|
||||
"SelectFilesType": "Seleccionar archivos de tipo: {{fileType}}",
|
||||
"UsersWithoutAccess": "Algunos usuarios a los que desea mencionar no tienen acceso a la sala: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Voit avata asiakirjan portaalissa tai mobiilisovelluksessa",
|
||||
"OpenInApp": "Avaa sovelluksessa",
|
||||
"OpeningDocument": "Avataan asiakirjaa",
|
||||
"StayInBrowser": "Pysy selaimessa"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "asiakirjat",
|
||||
"ErrorConnectionLost": "Yhteys on katkennut",
|
||||
"FileLocation": "Siirry asiakirjoihin",
|
||||
"FileName": "Tiedostonimi",
|
||||
"ImageFileType": "kuvat",
|
||||
"MailMergeFileType": "Valitse tiedosto XLSX-muodossa",
|
||||
"OpenSavedDocument": "Avaa tallennettu asiakirja uudessa välilehdessä",
|
||||
"SelectFilesType": "Valitse tiedostot tyyppiä: {{fileType}}",
|
||||
"UsersWithoutAccess": "Joillakin käyttäjillä, jotka haluat mainita, ei ole pääsyä huoneeseen: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Vous pouvez ouvrir le document sur le portail ou dans l'application mobile",
|
||||
"OpenInApp": "Ouvrir dans l'application",
|
||||
"OpeningDocument": "Ouverture du document",
|
||||
"StayInBrowser": "Rester dans le navigateur"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documents",
|
||||
"ErrorConnectionLost": "La connexion est perdue",
|
||||
"FileLocation": "Ouvrir l'emplacement du fichier",
|
||||
"FileName": "Nom du fichier",
|
||||
"ImageFileType": "images",
|
||||
"MailMergeFileType": "Sélectionner le fichier au format XLSX",
|
||||
"OpenSavedDocument": "Ouvrir le document enregistré dans un nouvel onglet",
|
||||
"SelectFilesType": "Sélectionner les fichiers de type: {{fileType}}",
|
||||
"UsersWithoutAccess": "Certains utilisateurs que vous souhaitez mentionner n'ont pas accès à la salle : {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Դուք կարող եք բացել փաստաթուղթը պորտալում կամ բջջային հավելվածում",
|
||||
"OpenInApp": "Բացեք հավելվածում",
|
||||
"OpeningDocument": "Փաստաթղթի բացում",
|
||||
"StayInBrowser": "Մնացեք բրաուզերո"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "Փաստաթղթեր",
|
||||
"ErrorConnectionLost": "Կապը ընդհատվեց",
|
||||
"FileLocation": "Բացել ֆայլի գտնվելու վայրը",
|
||||
"FileName": "ֆայլի անուն",
|
||||
"ImageFileType": "Պատկերներ",
|
||||
"MailMergeFileType": "Ընտրել ֆայլը XLSX ձևաչափով",
|
||||
"OpenSavedDocument": "Բացել պահպանված փաստաթուղթը նոր ներդիրում",
|
||||
"SelectFilesType": "Ընտրեք տեսակի ֆայլեր՝ {{fileType}}",
|
||||
"UsersWithoutAccess": "Որոշ օգտատերեր, որոնց ցանկանում եք նշել, մուտք չունեն սենյակ. {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "È possibile aprire il documento sul portale o nell'applicazione mobile",
|
||||
"OpenInApp": "Apri nell'app",
|
||||
"OpeningDocument": "Apertura di un documento",
|
||||
"StayInBrowser": "Rimani nel browser"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documenti",
|
||||
"ErrorConnectionLost": "La connessione è persa",
|
||||
"FileLocation": "Aprire la posizione del file",
|
||||
"FileName": "Nome di file",
|
||||
"ImageFileType": "immagine",
|
||||
"MailMergeFileType": "Selezionare il file nel formato XLSX",
|
||||
"OpenSavedDocument": "Aprire il documento salvato in una scheda nuova",
|
||||
"SelectFilesType": "Selezionare i file del tipo: {{fileType}}",
|
||||
"UsersWithoutAccess": "Alcuni utenti che vuoi menzionare non hanno accesso alla stanza: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "ポータルまたはモバイルアプリケーションでドキュメントを開くことができます",
|
||||
"OpenInApp": "アプリで開く",
|
||||
"OpeningDocument": "ドキュメントを開いています",
|
||||
"StayInBrowser": "ブラウザのまま"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "ドキュメント",
|
||||
"ErrorConnectionLost": "接続が切断されました",
|
||||
"FileLocation": "ファイルの場所を開く",
|
||||
"FileName": "ファイル名",
|
||||
"ImageFileType": "画像",
|
||||
"MailMergeFileType": "XLSX形式のファイルを選択する",
|
||||
"OpenSavedDocument": "保存されたファイルを新しいタブで開く",
|
||||
"SelectFilesType": " {{fileType}}タイプのファイルの選択",
|
||||
"UsersWithoutAccess": "言及したいユーザーの中には、ルームにアクセスできない人がいます:{{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "포털이나 모바일 애플리케이션에서 문서를 열 수 있습니다",
|
||||
"OpenInApp": "앱에서 열기",
|
||||
"OpeningDocument": "문서 여는 중",
|
||||
"StayInBrowser": "계속 브라우저 사용"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "문서",
|
||||
"ErrorConnectionLost": "연결이 끊어졌습니다",
|
||||
"FileLocation": "파일 위치 열기",
|
||||
"FileName": "파일명",
|
||||
"ImageFileType": "이미지",
|
||||
"MailMergeFileType": "XLSX 포맷 파일 선택",
|
||||
"OpenSavedDocument": "새로운 탭에서 저장 문서 열기",
|
||||
"SelectFilesType": "파일 유형 선택: {{fileType}}",
|
||||
"UsersWithoutAccess": "언급하려는 일부 사용자가 방에 액세스할 수 없습니다: {{users}}"
|
||||
}
|
@ -1 +0,0 @@
|
||||
{}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "ເອກະສານ",
|
||||
"ErrorConnectionLost": "ການເຊື່ອມຕໍ່ຫາຍໄປ",
|
||||
"FileLocation": "ເປີດບ່ອນຕຳແໜ່ງເອກະສານ",
|
||||
"FileName": "ຊື່ຟາຍ",
|
||||
"ImageFileType": "ຮູບພາບ",
|
||||
"MailMergeFileType": "ກະລຸນາເລືືອກໄຟລ໌ເປັນ .XLSX",
|
||||
"OpenSavedDocument": "ເປີດເອກະສານທີ່ບັນທືກໄວ້ໃນແຖບໃໝ່",
|
||||
"SelectFilesType": "ກະລຸນາເລືອກປະເພດໄຟລ໌ {{fileType}}",
|
||||
"UsersWithoutAccess": "ຜູ້ໃຊ້ບາງຄົນທີ່ທ່ານຕ້ອງການກ່າວເຖິງບໍ່ມີການເຂົ້າເຖິງຫ້ອງ: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Dokumentu var atvērt portālā un mobilajā lietotnē",
|
||||
"OpenInApp": "Atvērt lietotnē",
|
||||
"OpeningDocument": "Notiek dokumenta atvēršana",
|
||||
"StayInBrowser": "Palieciet pārlūkprogrammā"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dokumenti",
|
||||
"ErrorConnectionLost": "Zudis savienojums",
|
||||
"FileLocation": "Atvērt faila atrašanās vietu",
|
||||
"FileName": "Faila nosaukums",
|
||||
"ImageFileType": "attēli",
|
||||
"MailMergeFileType": "Atlasiet failu XLSX formātā",
|
||||
"OpenSavedDocument": "Atvērt saglabāto dokumentu jaunā cilnē",
|
||||
"SelectFilesType": "Atlasīt šāda veida failus: {{fileType}}",
|
||||
"UsersWithoutAccess": "Daži lietotāji, kurus vēlaties pieminēt, nevar piekļūt telpai: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "U kunt het document openen op het portaal of in de mobiele applicatie",
|
||||
"OpenInApp": "Openen in de app",
|
||||
"OpeningDocument": "Een document openen",
|
||||
"StayInBrowser": "Blijf in de browser"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documenten",
|
||||
"ErrorConnectionLost": "Verbinding is verbroken",
|
||||
"FileLocation": "Open bestandslocatie",
|
||||
"FileName": "Bestandsnaam",
|
||||
"ImageFileType": "afbeeldingen",
|
||||
"MailMergeFileType": "Selecteer het bestand in XLSX-formaat",
|
||||
"OpenSavedDocument": "Open bewaard document in nieuwe tab",
|
||||
"SelectFilesType": "Kies bestanden van het type: {{fileType}}",
|
||||
"UsersWithoutAccess": "Een aantal gebruikers die u wilt vermelden hebben geen toegang tot de kamer: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Możesz otworzyć dokument w portalu lub w aplikacji mobilnej",
|
||||
"OpenInApp": "Otwórz w aplikacji",
|
||||
"OpeningDocument": "Otwieranie dokumentu",
|
||||
"StayInBrowser": "Pozostań w przeglądarce"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dokumenty",
|
||||
"ErrorConnectionLost": "Połączenie zostało utracone",
|
||||
"FileLocation": "Otwórz lokalizację pliku",
|
||||
"FileName": "Nazwa pliku",
|
||||
"ImageFileType": "obrazy",
|
||||
"MailMergeFileType": "Wybierz plik w formacie XLSX",
|
||||
"OpenSavedDocument": "Otwórz zapisany dokument w nowej zakładce",
|
||||
"SelectFilesType": "Wybierz pliki z rodzaju: {{fileType}}",
|
||||
"UsersWithoutAccess": "Niektórzy użytkownicy, których chcesz oznaczyć, nie mają dostępu do pokoju: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Você pode abrir o documento no portal ou no aplicativo móvel",
|
||||
"OpenInApp": "Abra no aplicativo",
|
||||
"OpeningDocument": "Abrindo um documento",
|
||||
"StayInBrowser": "Fique no navegador"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documentos",
|
||||
"ErrorConnectionLost": "A conexão foi perdida",
|
||||
"FileLocation": "Local do arquivo aberto",
|
||||
"FileName": "Nome de Arquivo",
|
||||
"ImageFileType": "imagens",
|
||||
"MailMergeFileType": "Selecione o arquivo no formato XLSX",
|
||||
"OpenSavedDocument": "Abrir o documento salvo numa pasta nova",
|
||||
"SelectFilesType": "Selecionar arquivos do tipo: {{fileType}}",
|
||||
"UsersWithoutAccess": "Alguns usuários que você deseja mencionar não têm acesso à sala: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Pode abrir o documento no portal ou na aplicação",
|
||||
"OpenInApp": "Abrir na app",
|
||||
"OpeningDocument": "A abrir um documento",
|
||||
"StayInBrowser": "Permanecer no navegador"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "ficheiros",
|
||||
"ErrorConnectionLost": "A conexão foi perdida",
|
||||
"FileLocation": "Abrir localização",
|
||||
"FileName": "Nome do ficheiro",
|
||||
"ImageFileType": "imagens",
|
||||
"MailMergeFileType": "Selecione o ficheiro no formato XLSX",
|
||||
"OpenSavedDocument": "Abrir o documento guardado numa nova aba",
|
||||
"SelectFilesType": "Selecione ficheiros do tipo: {{fileType}}",
|
||||
"UsersWithoutAccess": "Alguns utilizadores que quer mencionar não têm acesso à sala: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Puteți să deschideți documentul pe portalul sau din aplicația mobilă",
|
||||
"OpenInApp": "Deschide din aplicația",
|
||||
"OpeningDocument": "Deschidere document",
|
||||
"StayInBrowser": "Rămâi în browser-ul"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "documente",
|
||||
"ErrorConnectionLost": "Conexiunea este pierdută",
|
||||
"FileLocation": "Deschidere locația fișierului",
|
||||
"FileName": "Numele fișierului",
|
||||
"ImageFileType": "imagini",
|
||||
"MailMergeFileType": "Selectare fișier format XLSX",
|
||||
"OpenSavedDocument": "Deschide documentul salvat într-o filă nouă",
|
||||
"SelectFilesType": "Selectare tip de fișier: {{fileType}}",
|
||||
"UsersWithoutAccess": "Unii utilizatori pe care doriţi să îi menţionaţi nu au acces la sala: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Вы можете открыть документ на портале или в мобильном приложении",
|
||||
"OpenInApp": "Открыть в приложении",
|
||||
"OpeningDocument": "Открытие документа",
|
||||
"StayInBrowser": "Остаться в браузере"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "документы",
|
||||
"ErrorConnectionLost": "Соединение потеряно",
|
||||
"FileLocation": "Открыть расположение файла",
|
||||
"FileName": "Имя файла",
|
||||
"ImageFileType": "изображения",
|
||||
"MailMergeFileType": "Выбрать файлы в формате XLSX",
|
||||
"OpenSavedDocument": "Открыть сохраненный документ в новой вкладке",
|
||||
"SelectFilesType": "Выбрать файлы типа: {{fileType}}",
|
||||
"UsersWithoutAccess": "Некоторые пользователи, которых вы хотите упомянуть, не имеют доступа к комнате: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Môžete otvoriť dokument na portáli alebo v mobilnej aplikácii",
|
||||
"OpenInApp": "Otvoriť v aplikácii",
|
||||
"OpeningDocument": "Otvorenie dokumentu",
|
||||
"StayInBrowser": "Zostať v prehliadači"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dokumenty",
|
||||
"ErrorConnectionLost": "Pripojenie sa stratilo",
|
||||
"FileLocation": "Otvoriť umiestnenie súboru",
|
||||
"FileName": "Názov súboru",
|
||||
"ImageFileType": "obrázky",
|
||||
"MailMergeFileType": "Vybrat soubor vo formátu XLSX",
|
||||
"OpenSavedDocument": "Otevřít uložený dokument na nové kartě",
|
||||
"SelectFilesType": "Vybrat soubory typu: {{fileType}}",
|
||||
"UsersWithoutAccess": "Niektorí používatelia, ktorých chcete označiť, nemajú prístup do miestnosti: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Dokument lahko odprete na portalu ali v mobilni aplikaciji",
|
||||
"OpenInApp": "Odprite v aplikaciji",
|
||||
"OpeningDocument": "Odprite dokument",
|
||||
"StayInBrowser": "Ostanite v brskalniku"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dokumenti",
|
||||
"ErrorConnectionLost": "Povezava je prekinjena",
|
||||
"FileLocation": "Pojdi v dokumente",
|
||||
"FileName": "Ime datoteke",
|
||||
"ImageFileType": "slike",
|
||||
"MailMergeFileType": "Izberi datoteko v XLSX formatu",
|
||||
"OpenSavedDocument": "Odpri shranjen dokument v novem zavihku",
|
||||
"SelectFilesType": "Izberi datoteke ali tip: {{fileType}}",
|
||||
"UsersWithoutAccess": "Nekateri uporabniki, ki jih želite omeniti, nimajo dostopa do sobe: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Belgeyi portalda veya mobil uygulamada açabilirsiniz",
|
||||
"OpenInApp": "Uygulamada aç",
|
||||
"OpeningDocument": "Belge açılıyor",
|
||||
"StayInBrowser": "Tarayıcıda kal"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "dökümanlar",
|
||||
"ErrorConnectionLost": "Bağlantı kesildi",
|
||||
"FileLocation": "Dosya konumunu aç",
|
||||
"FileName": "Dosya Adı",
|
||||
"ImageFileType": "görüntüler",
|
||||
"MailMergeFileType": "Dosyayı XLSX formatında seçin",
|
||||
"OpenSavedDocument": "Kaydedilen belgeyi yeni sekmede aç",
|
||||
"SelectFilesType": "Şu türdeki dosyaları seçin: {{fileType}}",
|
||||
"UsersWithoutAccess": "Bahsetmek istediğiniz bazı kullanıcıların odaya erişimi yok: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Ви можете відкрити документ на порталі або в мобільному застосунку",
|
||||
"OpenInApp": "Відкрити в застосунку",
|
||||
"OpeningDocument": "Відкриття документа",
|
||||
"StayInBrowser": "Залишитися у браузері"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "документи",
|
||||
"ErrorConnectionLost": "З'єднання втрачено",
|
||||
"FileLocation": "Перейти до документів",
|
||||
"FileName": "Ім'я файлу",
|
||||
"ImageFileType": "картинки",
|
||||
"MailMergeFileType": "Вибрати файл у форматі XLSX",
|
||||
"OpenSavedDocument": "Відкрити збережений документ на новій вкладці",
|
||||
"SelectFilesType": "Вибрати файли типу: {{fileType}}",
|
||||
"UsersWithoutAccess": "Деякі користувачі, яких ви хочете згадати, не мають доступу до кімнати: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "Bạn có thể mở tài liệu trên cổng thông tin hoặc trong ứng dụng di động",
|
||||
"OpenInApp": "Mở trong ứng dụng",
|
||||
"OpeningDocument": "Đang mở tài liệu",
|
||||
"StayInBrowser": "Ở lại trình duyệt"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "tài liệu",
|
||||
"ErrorConnectionLost": "Mất kết nối",
|
||||
"FileLocation": "Đi tới Tài liệu",
|
||||
"FileName": "Tên file",
|
||||
"ImageFileType": "hình ảnh",
|
||||
"MailMergeFileType": "Chọn tệp tin trong định dạng XLSX",
|
||||
"OpenSavedDocument": "Mở tài liệu đã lưu trong tab mới",
|
||||
"SelectFilesType": "Chọn tệp tin loại: {{fileType}}",
|
||||
"UsersWithoutAccess": "Một số người dùng mà bạn muốn đề cập đến không có quyền truy cập vào phòng: {{users}}"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"DeepLinkText": "您可以在门户或移动应用中打开文档",
|
||||
"OpenInApp": "在应用中打开",
|
||||
"OpeningDocument": "正在打开文档",
|
||||
"StayInBrowser": "始终在浏览器中"
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"DocumentsFileType": "文档",
|
||||
"ErrorConnectionLost": "已断开连接",
|
||||
"FileLocation": "打开文件的位置",
|
||||
"FileName": "文件名称",
|
||||
"ImageFileType": "图片",
|
||||
"MailMergeFileType": "选择XLSX格式的文件",
|
||||
"OpenSavedDocument": "在新标签中打开已保存的文件",
|
||||
"SelectFilesType": "选择类型的文件: {{fileType}}",
|
||||
"UsersWithoutAccess": "您想提及的部分用户没有房间访问权限:{{users}}"
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
const path = require("path");
|
||||
const beforeBuild = require("@docspace/shared/utils/beforeBuild");
|
||||
|
||||
beforeBuild(
|
||||
[
|
||||
path.join(__dirname, "../public/locales"),
|
||||
path.join(__dirname, "../../../public/locales"),
|
||||
],
|
||||
path.join(__dirname, "../src/autoGeneratedTranslations.js"),
|
||||
{
|
||||
path: path.join(__dirname, "../../client/public/locales"),
|
||||
files: [
|
||||
"ChangeOwnerPanel.json",
|
||||
"EmbeddingPanel.json",
|
||||
"Files.json",
|
||||
"PeopleSelector.json",
|
||||
"PeopleTranslations.json",
|
||||
"SharingPanel.json",
|
||||
"Translations.json",
|
||||
],
|
||||
alias: "CLIENT_PUBLIC_DIR",
|
||||
}
|
||||
);
|
@ -1,72 +0,0 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Editor from "./components/Editor.js";
|
||||
import { useSSR } from "react-i18next";
|
||||
import useMfScripts from "./helpers/useMfScripts";
|
||||
import { isRetina, frameCallCommand } from "@docspace/shared/utils/common";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { getCookie, setCookie } from "@docspace/shared/utils/cookie";
|
||||
|
||||
import initDesktop from "./helpers/initDesktop";
|
||||
import ErrorBoundary from "./components/ErrorBoundary";
|
||||
import store from "client/store";
|
||||
import i18n from "./i18n";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import GlobalStyle from "./components/GlobalStyle.js";
|
||||
import { inject, observer, Provider as MobxProvider } from "mobx-react";
|
||||
import { ThemeProvider } from "@docspace/shared/components/theme-provider";
|
||||
|
||||
const isDesktopEditor = window["AscDesktopEditor"] !== undefined;
|
||||
|
||||
const App = ({
|
||||
initialLanguage,
|
||||
initialI18nStoreASC,
|
||||
setTheme,
|
||||
getAppearanceTheme,
|
||||
currentColorScheme,
|
||||
...rest
|
||||
}) => {
|
||||
const [isInitialized, isErrorLoading] = useMfScripts();
|
||||
useSSR(initialI18nStoreASC, initialLanguage);
|
||||
|
||||
//console.log(rest);
|
||||
|
||||
return (
|
||||
<ErrorBoundary onError={onError}>
|
||||
<GlobalStyle />
|
||||
<Editor
|
||||
mfReady={isInitialized}
|
||||
mfFailed={isErrorLoading}
|
||||
isDesktopEditor={isDesktopEditor}
|
||||
initDesktop={initDesktop}
|
||||
currentColorScheme={currentColorScheme}
|
||||
{...rest}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
const AppWrapper = inject(({ settingsStore }) => {
|
||||
const { setTheme, getAppearanceTheme, currentColorScheme } = settingsStore;
|
||||
return {
|
||||
setTheme,
|
||||
getAppearanceTheme,
|
||||
currentColorScheme,
|
||||
};
|
||||
})(observer(App));
|
||||
|
||||
const ThemeProviderWrapper = inject(({ settingsStore }) => {
|
||||
let currentColorScheme = false;
|
||||
currentColorScheme = settingsStore.currentColorScheme || false;
|
||||
|
||||
return { theme: settingsStore.theme, currentColorScheme };
|
||||
})(observer(ThemeProvider));
|
||||
|
||||
export default (props) => (
|
||||
<MobxProvider {...store}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ThemeProviderWrapper>
|
||||
<AppWrapper {...props} />
|
||||
</ThemeProviderWrapper>
|
||||
</I18nextProvider>
|
||||
</MobxProvider>
|
||||
);
|
58
packages/editor/src/client/bootstrap.js
vendored
58
packages/editor/src/client/bootstrap.js
vendored
@ -1,58 +0,0 @@
|
||||
import React from "react";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
// import { registerSW } from "@docspace/shared/sw/helper";
|
||||
import App from "./App.js";
|
||||
import pkg from "../../package.json";
|
||||
import { initI18n } from "./helpers/utils.js";
|
||||
|
||||
const propsObj = window.__ASC_INITIAL_EDITOR_STATE__;
|
||||
const initialI18nStoreASC = window.initialI18nStoreASC;
|
||||
const initialLanguage = window.initialLanguage;
|
||||
|
||||
initI18n(initialI18nStoreASC);
|
||||
|
||||
const container = document.getElementById("root");
|
||||
if (container) {
|
||||
hydrateRoot(
|
||||
container,
|
||||
<React.Suspense fallback={<div></div>}>
|
||||
<App
|
||||
initialLanguage={initialLanguage}
|
||||
initialI18nStoreASC={initialI18nStoreASC}
|
||||
{...propsObj}
|
||||
/>
|
||||
</React.Suspense>
|
||||
);
|
||||
}
|
||||
if (IS_DEVELOPMENT) {
|
||||
const port = PORT || 5013;
|
||||
const socketPath = pkg.socketPath;
|
||||
|
||||
const ws = new WebSocket(`ws://localhost:${port}${socketPath}`);
|
||||
let isErrorConnection = false;
|
||||
|
||||
ws.onopen = (event) => {
|
||||
console.log("[editor-dev] Socket is connected. Live reload enabled");
|
||||
};
|
||||
|
||||
ws.onmessage = function (event) {
|
||||
if (event.data === "reload") {
|
||||
console.log("[editor-dev] App updated. Reloading...");
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = function (event) {
|
||||
console.log("[editor-dev] Socket is disconnected! Reloading...");
|
||||
setTimeout(() => {
|
||||
!isErrorConnection && location.reload();
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
ws.onerror = (event) => {
|
||||
isErrorConnection = true;
|
||||
console.log("[editor-dev] Socket connect error!");
|
||||
};
|
||||
}
|
||||
|
||||
// registerSW();
|
@ -1,102 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
import { mobile } from "@docspace/shared/utils";
|
||||
|
||||
export const StyledSimpleNav = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 12px 0;
|
||||
background-color: ${(props) => props.theme?.deepLink?.navBackground};
|
||||
margin-bottom: 32px;
|
||||
`;
|
||||
|
||||
export const StyledDeepLink = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
|
||||
@media ${mobile} {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledBodyWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
|
||||
@media ${mobile} {
|
||||
font-size: 23px;
|
||||
font-weight: 700;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledFileTile = styled.div`
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 8px 16px;
|
||||
background-color: ${(props) => props.theme?.deepLink?.fileTileBackground};
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const StyledActionsWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
|
||||
.stay-link {
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
|
||||
export const BgBlock = styled.div`
|
||||
background-image: ${(props) => props.bgPattern};
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
|
||||
@media ${mobile} {
|
||||
background-image: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 56px auto;
|
||||
max-width: 960px;
|
||||
width: 100vw;
|
||||
|
||||
@media ${mobile} {
|
||||
margin: 0 auto;
|
||||
}
|
||||
`;
|
||||
|
||||
export const LogoWrapper = styled.div`
|
||||
width: 386px;
|
||||
height: 44px;
|
||||
margin-top: auto;
|
||||
margin-bottom: 64px;
|
||||
|
||||
@media ${mobile} {
|
||||
display: none;
|
||||
}
|
||||
`;
|
@ -1,157 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { FormWrapper } from "@docspace/shared/components/form-wrapper";
|
||||
|
||||
import { getBgPattern } from "@docspace/shared/utils/common";
|
||||
import { getLogoFromPath } from "@docspace/shared/utils";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import { getDeepLink } from "../../helpers/deepLinkHelper";
|
||||
|
||||
import {
|
||||
StyledSimpleNav,
|
||||
StyledDeepLink,
|
||||
StyledBodyWrapper,
|
||||
StyledFileTile,
|
||||
StyledActionsWrapper,
|
||||
BgBlock,
|
||||
StyledWrapper,
|
||||
LogoWrapper,
|
||||
} from "./StyledDeepLink";
|
||||
|
||||
const DeepLink = ({
|
||||
fileInfo,
|
||||
logoUrls,
|
||||
userEmail,
|
||||
setIsShowDeepLink,
|
||||
currentColorScheme,
|
||||
theme,
|
||||
currentDeviceType,
|
||||
deepLinkConfig,
|
||||
}) => {
|
||||
const { t } = useTranslation(["DeepLink", "Common"]);
|
||||
|
||||
const [isRemember, setIsRemember] = useState(false);
|
||||
const onChangeCheckbox = () => {
|
||||
setIsRemember(!isRemember);
|
||||
};
|
||||
|
||||
const onOpenAppClick = () => {
|
||||
if (isRemember) localStorage.setItem("defaultOpenDocument", "app");
|
||||
getDeepLink(
|
||||
window.location.origin,
|
||||
userEmail,
|
||||
fileInfo,
|
||||
deepLinkConfig,
|
||||
window.location.href
|
||||
);
|
||||
};
|
||||
|
||||
const onStayBrowserClick = () => {
|
||||
if (isRemember) localStorage.setItem("defaultOpenDocument", "web");
|
||||
window.location.replace(window.location.search + "&without_redirect=true");
|
||||
setIsShowDeepLink(false);
|
||||
};
|
||||
|
||||
const getFileIcon = () => {
|
||||
const fileExst = fileInfo.fileExst.slice(1);
|
||||
const iconPath = "/static/images/icons/32/";
|
||||
return `${iconPath}${fileExst}.svg`;
|
||||
};
|
||||
|
||||
const getFileTitle = () => {
|
||||
return fileInfo.fileExst
|
||||
? fileInfo.title.split(".").slice(0, -1).join(".")
|
||||
: fileInfo.title;
|
||||
};
|
||||
|
||||
const logoPath = theme.isBase
|
||||
? logoUrls[1]?.path?.light
|
||||
: logoUrls[1]?.path?.dark;
|
||||
const logo = getLogoFromPath(logoPath);
|
||||
|
||||
const renderLogo = () => {
|
||||
if (currentDeviceType === DeviceType.mobile) {
|
||||
const logoPath = theme.isBase
|
||||
? logoUrls[0]?.path?.light
|
||||
: logoUrls[0]?.path?.dark;
|
||||
const logo = getLogoFromPath(logoPath);
|
||||
return (
|
||||
<StyledSimpleNav>
|
||||
<img src={logo} />
|
||||
</StyledSimpleNav>
|
||||
);
|
||||
} else {
|
||||
const logoPath = theme.isBase
|
||||
? logoUrls[1]?.path?.light
|
||||
: logoUrls[1]?.path?.dark;
|
||||
const logo = getLogoFromPath(logoPath);
|
||||
return (
|
||||
<LogoWrapper>
|
||||
<img src={logo} />
|
||||
</LogoWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const bgPattern = getBgPattern(currentColorScheme?.id);
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
{renderLogo()}
|
||||
<FormWrapper>
|
||||
<StyledDeepLink>
|
||||
<StyledBodyWrapper>
|
||||
<Text className="title">{t("OpeningDocument")}</Text>
|
||||
<StyledFileTile>
|
||||
<img src={getFileIcon()} />
|
||||
<Text fontSize="14px" fontWeight="600" truncate>
|
||||
{getFileTitle()}
|
||||
</Text>
|
||||
</StyledFileTile>
|
||||
<Text>{t("DeepLinkText")}</Text>
|
||||
</StyledBodyWrapper>
|
||||
<StyledActionsWrapper>
|
||||
<Checkbox
|
||||
label={t("Common:Remember")}
|
||||
isChecked={isRemember}
|
||||
onChange={onChangeCheckbox}
|
||||
/>
|
||||
<Button
|
||||
size="medium"
|
||||
primary
|
||||
label={t("OpenInApp")}
|
||||
onClick={onOpenAppClick}
|
||||
/>
|
||||
<Link
|
||||
className="stay-link"
|
||||
type="action"
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
isHovered
|
||||
color={currentColorScheme?.main?.accent}
|
||||
onClick={onStayBrowserClick}
|
||||
>
|
||||
{t("StayInBrowser")}
|
||||
</Link>
|
||||
</StyledActionsWrapper>
|
||||
</StyledDeepLink>
|
||||
</FormWrapper>
|
||||
<BgBlock bgPattern={bgPattern} />
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ settingsStore }) => {
|
||||
const { theme, currentDeviceType } = settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
currentDeviceType,
|
||||
};
|
||||
})(observer(DeepLink));
|
@ -1,112 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
export function loadComponent(scope, module) {
|
||||
return async () => {
|
||||
// Initializes the share scope. This fills it with known provided modules from this build and all remotes
|
||||
await __webpack_init_sharing__("default");
|
||||
const container = window[scope]; // or get the container somewhere else
|
||||
// Initialize the container, it may provide shared modules
|
||||
await container.init(__webpack_share_scopes__.default);
|
||||
const factory = await window[scope].get(module);
|
||||
const Module = factory();
|
||||
return Module;
|
||||
};
|
||||
}
|
||||
|
||||
export const useDynamicScript = (args) => {
|
||||
const [ready, setReady] = React.useState(false);
|
||||
const [failed, setFailed] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!args.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
const exists = document.getElementById(args.id);
|
||||
|
||||
if (exists || args?.isInit) {
|
||||
setReady(true);
|
||||
setFailed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const element = document.createElement("script");
|
||||
|
||||
element.id = args.id;
|
||||
element.src = args.url;
|
||||
element.type = "text/javascript";
|
||||
element.async = true;
|
||||
|
||||
setReady(false);
|
||||
setFailed(false);
|
||||
|
||||
element.onload = () => {
|
||||
console.log(`Dynamic Script Loaded: ${args.url}`);
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
element.onerror = () => {
|
||||
console.error(`Dynamic Script Error: ${args.url}`);
|
||||
setReady(false);
|
||||
setFailed(true);
|
||||
};
|
||||
|
||||
document.head.appendChild(element);
|
||||
|
||||
//TODO: Comment if you don't want to remove loaded remoteEntry
|
||||
// return () => {
|
||||
// console.log(`Dynamic Script Removed: ${args.url}`);
|
||||
// document.head.removeChild(element);
|
||||
// };
|
||||
}, [args.url]);
|
||||
|
||||
return {
|
||||
ready,
|
||||
failed,
|
||||
};
|
||||
};
|
||||
|
||||
const DynamicComponent = ({ system, needProxy, ...rest }) => {
|
||||
const [isInitialized, setIsInitialized] = React.useState(false);
|
||||
const [LoadedComponent, setLoadedComponent] = React.useState();
|
||||
|
||||
const { ready, failed } = useDynamicScript({
|
||||
url: system && system.url,
|
||||
id: system && system.scope,
|
||||
isInit: isInitialized,
|
||||
});
|
||||
|
||||
if (!system) {
|
||||
console.log(`Not system specified`);
|
||||
throw Error("Not system specified");
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
console.log(`Loading dynamic script: ${system.url}`);
|
||||
return <div className={rest.className} />;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
console.log(`Failed to load dynamic script: ${system.url}`);
|
||||
throw Error("failed");
|
||||
}
|
||||
|
||||
if (ready && !isInitialized) {
|
||||
setIsInitialized(true);
|
||||
const Component = React.lazy(loadComponent(system.scope, system.module));
|
||||
|
||||
setLoadedComponent(Component);
|
||||
}
|
||||
|
||||
const Component = React.lazy(loadComponent(system.scope, system.module));
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<div />}>
|
||||
{needProxy
|
||||
? LoadedComponent && <LoadedComponent {...rest} />
|
||||
: Component && <Component {...rest} />}
|
||||
</React.Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export default DynamicComponent;
|
@ -1,149 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { isMobile, isIOS, deviceType } from "react-device-detect";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { FolderType } from "@docspace/shared/enums";
|
||||
import { EDITOR_ID } from "@docspace/shared/constants";
|
||||
|
||||
import { Toast } from "@docspace/shared/components/toast";
|
||||
import { toast } from "react-toastify";
|
||||
import {
|
||||
restoreDocumentsVersion,
|
||||
getEditDiff,
|
||||
getEditHistory,
|
||||
createFile,
|
||||
updateFile,
|
||||
checkFillFormDraft,
|
||||
convertFile,
|
||||
getReferenceData,
|
||||
getSharedUsers,
|
||||
getProtectUsers,
|
||||
sendEditorNotify,
|
||||
} from "@docspace/shared/api/files";
|
||||
import { EditorWrapper } from "../components/StyledEditor";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import withDialogs from "../helpers/withDialogs";
|
||||
import {
|
||||
assign,
|
||||
frameCallEvent,
|
||||
frameCallCommand,
|
||||
} from "@docspace/shared/utils/common";
|
||||
import { getEditorTheme } from "@docspace/shared/utils";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { DocumentEditor } from "@onlyoffice/document-editor-react";
|
||||
import DeepLink from "./DeepLink";
|
||||
import { getDeepLink } from "../helpers/deepLinkHelper";
|
||||
|
||||
toast.configure();
|
||||
|
||||
let documentIsReady = false;
|
||||
let docSaved = null;
|
||||
let docTitle = null;
|
||||
let docEditor;
|
||||
let newConfig;
|
||||
let documentserverUrl =
|
||||
typeof window !== "undefined" && window?.location?.origin;
|
||||
let userAccessRights = {};
|
||||
let isArchiveFolderRoot = true;
|
||||
let usersInRoom = [];
|
||||
|
||||
const constructTitle = (firstPart, secondPart, reverse = false) => {
|
||||
return !reverse
|
||||
? `${firstPart} - ${secondPart}`
|
||||
: `${secondPart} - ${firstPart}`;
|
||||
};
|
||||
|
||||
const checkIfFirstSymbolInStringIsRtl = (str) => {
|
||||
if (!str) return;
|
||||
|
||||
const rtlRegexp = new RegExp(
|
||||
/[\u04c7-\u0591\u05D0-\u05EA\u05F0-\u05F4\u0600-\u06FF]/,
|
||||
);
|
||||
|
||||
return rtlRegexp.test(str[0]);
|
||||
};
|
||||
|
||||
function Editor({
|
||||
config,
|
||||
//personal,
|
||||
successAuth,
|
||||
isSharingAccess,
|
||||
user,
|
||||
|
||||
error,
|
||||
sharingDialog,
|
||||
onSDKRequestSharingSettings,
|
||||
|
||||
isVisible,
|
||||
selectFileDialog,
|
||||
|
||||
selectFolderDialog,
|
||||
|
||||
isDesktopEditor,
|
||||
initDesktop,
|
||||
view,
|
||||
mfReady,
|
||||
fileId,
|
||||
url,
|
||||
|
||||
logoUrls,
|
||||
currentColorScheme,
|
||||
portalSettings,
|
||||
}) {
|
||||
const [isShowDeepLink, setIsShowDeepLink] = useState(false);
|
||||
|
||||
const fileInfo = config?.file;
|
||||
|
||||
const { t } = useTranslation(["Editor", "Common"]);
|
||||
|
||||
const init = () => {
|
||||
try {
|
||||
let onRequestSharingSettings;
|
||||
|
||||
const events = {
|
||||
events: {
|
||||
onRequestSharingSettings,
|
||||
},
|
||||
};
|
||||
|
||||
newConfig = Object.assign(config, events);
|
||||
} catch (error) {
|
||||
toastr.error(error.message, null, 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
const additionalComponents =
|
||||
error && !error?.unAuthorized ? (
|
||||
<ErrorContainerBody
|
||||
headerText={t("Common:Error")}
|
||||
customizedBodyText={errorMessage()}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{sharingDialog}
|
||||
{selectFileDialog}
|
||||
{selectFolderDialog}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<EditorWrapper isVisibleSharingDialog={isVisible}>
|
||||
{newConfig && (
|
||||
<DocumentEditor
|
||||
id={EDITOR_ID}
|
||||
documentServerUrl={documentserverUrl}
|
||||
config={newConfig}
|
||||
height="100%"
|
||||
width="100%"
|
||||
events_onDocumentReady={onDocumentReady}
|
||||
></DocumentEditor>
|
||||
)}
|
||||
|
||||
{additionalComponents}
|
||||
|
||||
<Toast />
|
||||
</EditorWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withDialogs(Editor);
|
@ -1,49 +0,0 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ErrorContainer from "@docspace/shared/components/error-container/ErrorContainer";
|
||||
|
||||
const Error520 = ({ match }) => {
|
||||
const { t } = useTranslation(["Common"]);
|
||||
const params = useParams();
|
||||
const { error } = (params && params) || {};
|
||||
|
||||
return (
|
||||
<ErrorContainer headerText={t("SomethingWentWrong")} bodyText={error} />
|
||||
);
|
||||
};
|
||||
|
||||
class ErrorBoundary extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
static getDerivedStateFromError(error) {
|
||||
// Update state so the next render will show the fallback UI.
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error, errorInfo) {
|
||||
// You can also log the error to an error reporting service
|
||||
console.error(error, errorInfo);
|
||||
this.props.onError && this.props.onError();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
// You can render any custom fallback UI
|
||||
return <Error520 />;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBoundary.propTypes = {
|
||||
children: PropTypes.any,
|
||||
onError: PropTypes.func,
|
||||
};
|
||||
|
||||
export default ErrorBoundary;
|
@ -1,31 +0,0 @@
|
||||
import { createGlobalStyle } from "styled-components";
|
||||
|
||||
const GlobalStyle = createGlobalStyle`
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
|
||||
font-family: 'Open Sans', sans-serif, Arial;
|
||||
font-size: 13px;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
#root {
|
||||
min-height: 100%;
|
||||
|
||||
.pageLoader {
|
||||
position: fixed;
|
||||
left: calc(50% - 20px);
|
||||
top: 35%;
|
||||
}
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body.loading * {
|
||||
cursor: wait !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export default GlobalStyle;
|
@ -1,35 +0,0 @@
|
||||
import React from "react";
|
||||
import DynamicComponent from "./DynamicComponent";
|
||||
import { CLIENT_REMOTE_ENTRY_URL, CLIENT_SCOPE } from "../helpers/constants";
|
||||
|
||||
const SelectFileDialog = ({
|
||||
isVisible,
|
||||
mfReady,
|
||||
onCloseFileDialog,
|
||||
onSelectFile,
|
||||
filesListTitle,
|
||||
settings,
|
||||
successAuth,
|
||||
...rest
|
||||
}) => {
|
||||
return (
|
||||
(mfReady && isVisible && successAuth && (
|
||||
<DynamicComponent
|
||||
{...rest}
|
||||
system={{
|
||||
scope: CLIENT_SCOPE,
|
||||
url: CLIENT_REMOTE_ENTRY_URL,
|
||||
module: "./SelectFileDialog",
|
||||
}}
|
||||
isPanelVisible={isVisible}
|
||||
onClose={onCloseFileDialog}
|
||||
onSelectFile={onSelectFile}
|
||||
descriptionText={filesListTitle}
|
||||
settings={settings}
|
||||
/>
|
||||
)) ||
|
||||
null
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectFileDialog;
|
@ -1,47 +0,0 @@
|
||||
import React from "react";
|
||||
import DynamicComponent from "./DynamicComponent";
|
||||
import { CLIENT_REMOTE_ENTRY_URL, CLIENT_SCOPE } from "../helpers/constants";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
const SelectFolderDialog = ({
|
||||
successAuth,
|
||||
folderId,
|
||||
isVisible,
|
||||
onCloseFolderDialog,
|
||||
onClickSaveSelectFolder,
|
||||
titleSelectorFolder,
|
||||
|
||||
extension,
|
||||
settings,
|
||||
mfReady,
|
||||
}) => {
|
||||
const { t } = useTranslation(["Editor", "Common"]);
|
||||
|
||||
return (
|
||||
(mfReady && isVisible && successAuth && (
|
||||
<DynamicComponent
|
||||
system={{
|
||||
scope: CLIENT_SCOPE,
|
||||
url: CLIENT_REMOTE_ENTRY_URL,
|
||||
module: "./SelectFolderDialog",
|
||||
}}
|
||||
needProxy
|
||||
id={folderId}
|
||||
isPanelVisible={isVisible}
|
||||
onClose={onCloseFolderDialog}
|
||||
onSave={onClickSaveSelectFolder}
|
||||
isCopy={true}
|
||||
isEditorDialog={true}
|
||||
withFooterInput={true}
|
||||
withFooterCheckbox={extension !== "fb2"}
|
||||
footerInputHeader={t("FileName")}
|
||||
currentFooterInputValue={titleSelectorFolder}
|
||||
footerCheckboxLabel={t("OpenSavedDocument")}
|
||||
settings={settings}
|
||||
/>
|
||||
)) ||
|
||||
null
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectFolderDialog;
|
@ -1,34 +0,0 @@
|
||||
import React from "react";
|
||||
import DynamicComponent from "./DynamicComponent";
|
||||
import { CLIENT_REMOTE_ENTRY_URL, CLIENT_SCOPE } from "../helpers/constants";
|
||||
|
||||
const SharingDialog = ({
|
||||
isVisible,
|
||||
fileInfo,
|
||||
onCancel,
|
||||
loadUsersRightsList,
|
||||
filesSettings,
|
||||
mfReady,
|
||||
}) => {
|
||||
return (
|
||||
(mfReady && isVisible && (
|
||||
<DynamicComponent
|
||||
className="dynamic-sharing-dialog"
|
||||
system={{
|
||||
scope: CLIENT_SCOPE,
|
||||
url: CLIENT_REMOTE_ENTRY_URL,
|
||||
module: "./SharingDialog",
|
||||
name: "SharingDialog",
|
||||
}}
|
||||
isVisible={isVisible}
|
||||
sharingObject={fileInfo}
|
||||
onCancel={onCancel}
|
||||
onSuccess={loadUsersRightsList}
|
||||
settings={filesSettings}
|
||||
/>
|
||||
)) ||
|
||||
null
|
||||
);
|
||||
};
|
||||
|
||||
export default SharingDialog;
|
@ -1,32 +0,0 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
|
||||
const StyledSelectFolder = styled.div`
|
||||
.editor-select-folder_text-input {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.editor-select-folder_checkbox {
|
||||
background-color: ${(props) => props.theme.editor.background};
|
||||
word-break: break-word;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledSelectFolder.defaultProps = { theme: Base };
|
||||
|
||||
const StyledSelectFile = styled.div`
|
||||
.editor-select-file_text {
|
||||
word-break: break-word;
|
||||
}
|
||||
`;
|
||||
|
||||
const EditorWrapper = styled.div`
|
||||
height: 100vh;
|
||||
|
||||
.dynamic-sharing-dialog {
|
||||
${(props) => !props.isVisibleSharingDialog && "display: none"}
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledSelectFolder, StyledSelectFile, EditorWrapper };
|
@ -1,2 +0,0 @@
|
||||
export const CLIENT_SCOPE = "client";
|
||||
export const CLIENT_REMOTE_ENTRY_URL = "/remoteEntry.js";
|
@ -1,119 +0,0 @@
|
||||
function DeepLinker(options) {
|
||||
if (!options) {
|
||||
throw new Error("no options");
|
||||
}
|
||||
|
||||
let hasFocus = true;
|
||||
let didHide = false;
|
||||
|
||||
function onBlur() {
|
||||
hasFocus = false;
|
||||
}
|
||||
|
||||
function onVisibilityChange(e) {
|
||||
if (e.target.visibilityState === "hidden") {
|
||||
didHide = true;
|
||||
}
|
||||
}
|
||||
|
||||
function onFocus() {
|
||||
if (didHide) {
|
||||
if (options.onReturn) {
|
||||
options.onReturn();
|
||||
}
|
||||
|
||||
didHide = false;
|
||||
} else {
|
||||
if (!hasFocus && options.onFallback) {
|
||||
setTimeout(function () {
|
||||
if (!didHide) {
|
||||
options.onFallback();
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
hasFocus = true;
|
||||
}
|
||||
|
||||
function bindEvents(mode) {
|
||||
[
|
||||
[window, "blur", onBlur],
|
||||
[document, "visibilitychange", onVisibilityChange],
|
||||
[window, "focus", onFocus],
|
||||
].forEach(function (conf) {
|
||||
conf[0][mode + "EventListener"](conf[1], conf[2]);
|
||||
});
|
||||
}
|
||||
|
||||
bindEvents("add");
|
||||
|
||||
this.destroy = bindEvents.bind(null, "remove");
|
||||
this.openURL = function (url) {
|
||||
var dialogTimeout = 500;
|
||||
|
||||
setTimeout(function () {
|
||||
if (hasFocus && options.onIgnored) {
|
||||
options.onIgnored();
|
||||
}
|
||||
}, dialogTimeout);
|
||||
|
||||
window.location = url;
|
||||
};
|
||||
}
|
||||
|
||||
function bytesToBase64(bytes) {
|
||||
const binString = String.fromCodePoint(...bytes);
|
||||
return btoa(binString);
|
||||
}
|
||||
|
||||
export const getDeepLink = (
|
||||
location,
|
||||
email,
|
||||
file,
|
||||
deepLinkConfig,
|
||||
originalUrl
|
||||
) => {
|
||||
const jsonData = {
|
||||
portal: location,
|
||||
email: email,
|
||||
file: {
|
||||
id: file.id,
|
||||
title: file.title,
|
||||
extension: file.fileExst,
|
||||
},
|
||||
folder: {
|
||||
id: file.folderId,
|
||||
parentId: file.rootFolderId,
|
||||
rootFolderType: file.rootFolderType,
|
||||
},
|
||||
originalUrl: originalUrl,
|
||||
};
|
||||
const stringifyData = JSON.stringify(jsonData);
|
||||
const deepLinkData = bytesToBase64(new TextEncoder().encode(stringifyData));
|
||||
|
||||
const linker = new DeepLinker({
|
||||
onIgnored: function () {
|
||||
redirectToStore(deepLinkConfig);
|
||||
},
|
||||
onFallback: function () {
|
||||
redirectToStore(deepLinkConfig);
|
||||
},
|
||||
onReturn: function () {
|
||||
//redirectToStore(deepLinkConfig);
|
||||
},
|
||||
});
|
||||
|
||||
linker.openURL(`${deepLinkConfig?.url}?data=${deepLinkData}`);
|
||||
};
|
||||
|
||||
const redirectToStore = (deepLinkConfig) => {
|
||||
const nav = navigator.userAgent;
|
||||
const isIOS = nav.includes("iPhone;") || nav.includes("iPad;");
|
||||
|
||||
const storeUrl = isIOS
|
||||
? `https://apps.apple.com/app/id${deepLinkConfig?.iosPackageId}`
|
||||
: `https://play.google.com/store/apps/details?id=${deepLinkConfig?.androidPackageName}`;
|
||||
|
||||
window.location.replace(storeUrl);
|
||||
};
|
@ -1,39 +0,0 @@
|
||||
import {
|
||||
setEncryptionKeys,
|
||||
getEncryptionAccess,
|
||||
} from "@docspace/shared/api/files";
|
||||
import { regDesktop } from "@docspace/shared/utils/desktop";
|
||||
|
||||
const initDesktop = (cfg, user, fileId, t) => {
|
||||
const encryptionKeys = cfg?.editorConfig?.encryptionKeys;
|
||||
regDesktop(
|
||||
user,
|
||||
!!encryptionKeys,
|
||||
encryptionKeys,
|
||||
(keys) => {
|
||||
setEncryptionKeys(keys);
|
||||
},
|
||||
true,
|
||||
(callback) => {
|
||||
getEncryptionAccess(fileId)
|
||||
.then((keys) => {
|
||||
var data = {
|
||||
keys,
|
||||
};
|
||||
|
||||
callback(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
window?.toastr.error(
|
||||
typeof error === "string" ? error : error.message,
|
||||
null,
|
||||
0,
|
||||
true
|
||||
);
|
||||
});
|
||||
},
|
||||
t
|
||||
);
|
||||
};
|
||||
|
||||
export default initDesktop;
|
@ -1,47 +0,0 @@
|
||||
import React from "react";
|
||||
import {
|
||||
loadComponent,
|
||||
useDynamicScript,
|
||||
} from "../components/DynamicComponent";
|
||||
import { CLIENT_SCOPE, CLIENT_REMOTE_ENTRY_URL } from "../helpers/constants";
|
||||
|
||||
function useMfScripts() {
|
||||
const [isInitialized, setIsInitialized] = React.useState(false);
|
||||
const [isError, setIsError] = React.useState(false);
|
||||
|
||||
const { ready: studioReady, failed: studioFailed } = useDynamicScript({
|
||||
id: CLIENT_SCOPE,
|
||||
url: CLIENT_REMOTE_ENTRY_URL,
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (studioReady) {
|
||||
initMfScripts();
|
||||
}
|
||||
|
||||
if (studioFailed) {
|
||||
setIsError(true);
|
||||
setIsInitialized(false);
|
||||
}
|
||||
}, [studioReady]);
|
||||
|
||||
const initMfScripts = async () => {
|
||||
const SharingDialog = await loadComponent(
|
||||
CLIENT_SCOPE,
|
||||
"./SharingDialog"
|
||||
)();
|
||||
const filesUtils = await loadComponent(CLIENT_SCOPE, "./utils")();
|
||||
const authStore = await loadComponent(CLIENT_SCOPE, "./store")();
|
||||
|
||||
window.filesUtils = filesUtils;
|
||||
window.SharingDialog = SharingDialog.default;
|
||||
window.authStore = authStore.default;
|
||||
|
||||
setIsInitialized(true);
|
||||
setIsError(false);
|
||||
};
|
||||
|
||||
return [isInitialized, isError];
|
||||
}
|
||||
|
||||
export default useMfScripts;
|
@ -1,85 +0,0 @@
|
||||
import pkg from "../../../package.json";
|
||||
import { translations } from "SRC_DIR/autoGeneratedTranslations";
|
||||
|
||||
export function getLanguage(lng) {
|
||||
try {
|
||||
let language = lng == "en-US" || lng == "en-GB" ? "en" : lng;
|
||||
|
||||
const splitted = lng.split("-");
|
||||
|
||||
if (splitted.length == 2 && splitted[0] == splitted[1].toLowerCase()) {
|
||||
language = splitted[0];
|
||||
}
|
||||
|
||||
return language;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return lng;
|
||||
}
|
||||
|
||||
export function loadLanguagePath(homepage, fixedNS = null) {
|
||||
return (lng, ns) => {
|
||||
const language = getLanguage(lng instanceof Array ? lng[0] : lng);
|
||||
|
||||
const lngCollection = translations.get(language);
|
||||
|
||||
const path = lngCollection?.get(`${fixedNS || ns}`);
|
||||
|
||||
if (!path) return `/doceditor/locales/${language}/${fixedNS || ns}.json`;
|
||||
|
||||
const isCommonPath = path?.indexOf("Common") > -1;
|
||||
const isClientPath = !isCommonPath && path?.indexOf("Editor") === -1;
|
||||
|
||||
if (ns.length > 0 && ns[0] === "Common" && isCommonPath) {
|
||||
return path.replace("/doceditor/", "/static/");
|
||||
}
|
||||
|
||||
if (ns.length > 0 && ns[0] != "Editor" && isClientPath) {
|
||||
return path.replace("/doceditor/", "/");
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
}
|
||||
|
||||
export const initI18n = (initialI18nStoreASC) => {
|
||||
if (!initialI18nStoreASC || window.i18n) return;
|
||||
|
||||
window.i18n = {};
|
||||
window.i18n.inLoad = [];
|
||||
window.i18n.loaded = {};
|
||||
|
||||
for (let lng in initialI18nStoreASC) {
|
||||
const collection = translations.get(lng);
|
||||
|
||||
for (let ns in initialI18nStoreASC[lng]) {
|
||||
const path = collection?.get(ns);
|
||||
|
||||
if (!path) {
|
||||
window.i18n.loaded[`/doceditor/locales/${lng}/${ns}.json`] = {
|
||||
namespaces: ns,
|
||||
data: initialI18nStoreASC[lng][ns],
|
||||
};
|
||||
} else {
|
||||
if (ns === "Common") {
|
||||
window.i18n.loaded[`${path?.replace("/doceditor/", "/static/")}`] = {
|
||||
namespaces: ns,
|
||||
data: initialI18nStoreASC[lng][ns],
|
||||
};
|
||||
} else if (ns != "Editor") {
|
||||
window.i18n.loaded[`${path?.replace("/doceditor/", "/")}`] = {
|
||||
namespaces: ns,
|
||||
data: initialI18nStoreASC[lng][ns],
|
||||
};
|
||||
} else {
|
||||
window.i18n.loaded[`${path}`] = {
|
||||
namespaces: ns,
|
||||
data: initialI18nStoreASC[lng][ns],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -1,120 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { getPresignedUri, getReferenceData } from "@docspace/shared/api/files";
|
||||
import { getRestoreProgress } from "@docspace/shared/api/portal";
|
||||
import { FilesSelectorFilterTypes, FilterType } from "@docspace/shared/enums";
|
||||
import { EDITOR_ID } from "@docspace/shared/constants";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SharingDialog from "../components/SharingDialog";
|
||||
import SelectFileDialog from "../components/SelectFileDialog";
|
||||
import SelectFolderDialog from "../components/SelectFolderDialog";
|
||||
|
||||
const insertImageAction = "imageFileType";
|
||||
const mailMergeAction = "mailMergeFileType";
|
||||
const compareFilesAction = "documentsFileType";
|
||||
const setReferenceSourceAction = "referenceSourceType";
|
||||
|
||||
const withDialogs = (WrappedComponent) => {
|
||||
return (props) => {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [filesType, setFilesType] = useState("");
|
||||
const [isFileDialogVisible, setIsFileDialogVisible] = useState(false);
|
||||
|
||||
const { t } = useTranslation(["Editor", "Common"]);
|
||||
|
||||
const { config, fileId, mfReady, sharingSettings } = props;
|
||||
const fileInfo = config?.file;
|
||||
|
||||
useEffect(() => {
|
||||
if (window.authStore) {
|
||||
initSocketHelper();
|
||||
}
|
||||
}, [mfReady]);
|
||||
|
||||
const initSocketHelper = async () => {
|
||||
await window.authStore.authStore.init(true);
|
||||
|
||||
const { socketHelper } = window.authStore.settingsStore;
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: { roomParts: "backup-restore" },
|
||||
});
|
||||
socketHelper.on("restore-backup", () => {
|
||||
getRestoreProgress()
|
||||
.then((response) => {
|
||||
if (!response) {
|
||||
console.log("Skip denyEditingRights - empty progress response");
|
||||
return;
|
||||
}
|
||||
const message = t("Common:PreparationPortalTitle");
|
||||
const docEditor =
|
||||
typeof window !== "undefined" &&
|
||||
window.DocEditor?.instances[EDITOR_ID];
|
||||
|
||||
docEditor?.denyEditingRights(message);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("getRestoreProgress", e);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
setIsVisible(false);
|
||||
};
|
||||
|
||||
const loadUsersRightsList = (docEditor) => {
|
||||
window.SharingDialog.convertSharingUsers(sharingSettings).then(
|
||||
(sharingSettings) => {
|
||||
docEditor.setSharingSettings({
|
||||
sharingSettings,
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const sharingDialog = (
|
||||
<SharingDialog
|
||||
mfReady={mfReady}
|
||||
isVisible={isVisible}
|
||||
fileInfo={fileInfo}
|
||||
onCancel={onCancel}
|
||||
loadUsersRightsList={loadUsersRightsList}
|
||||
filesSettings={props.filesSettings}
|
||||
/>
|
||||
);
|
||||
|
||||
// const selectFileDialog = (
|
||||
// <SelectFileDialog
|
||||
// isVisible={isFileDialogVisible}
|
||||
// onSelectFile={onSelectFile}
|
||||
// onCloseFileDialog={onCloseFileDialog}
|
||||
// {...fileTypeDetection()}
|
||||
// filesListTitle={selectFilesListTitle()}
|
||||
// settings={props.filesSettings}
|
||||
// mfReady={mfReady}
|
||||
// successAuth={props.successAuth}
|
||||
// />
|
||||
// );
|
||||
|
||||
return (
|
||||
<WrappedComponent
|
||||
{...props}
|
||||
sharingDialog={sharingDialog}
|
||||
onSDKRequestSharingSettings={onSDKRequestSharingSettings}
|
||||
loadUsersRightsList={loadUsersRightsList}
|
||||
isVisible={isVisible}
|
||||
selectFileDialog={selectFileDialog}
|
||||
onSDKRequestInsertImage={onSDKRequestInsertImage}
|
||||
onSDKRequestSelectSpreadsheet={onSDKRequestSelectSpreadsheet}
|
||||
onSDKRequestSelectDocument={onSDKRequestSelectDocument}
|
||||
onSDKRequestReferenceSource={onSDKRequestReferenceSource}
|
||||
isFileDialogVisible={isFileDialogVisible}
|
||||
selectFolderDialog={selectFolderDialog}
|
||||
onSDKRequestSaveAs={onSDKRequestSaveAs}
|
||||
isFolderDialogVisible={isFolderDialogVisible}
|
||||
/>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
export default withDialogs;
|
@ -1,46 +0,0 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import Backend from "@docspace/shared/utils/i18next-http-backend";
|
||||
import config from "../../package.json";
|
||||
import { LANGUAGE } from "@docspace/shared/constants";
|
||||
import { getLtrLanguageForEditor } from "@docspace/shared/utils/common";
|
||||
import { getCookie } from "@docspace/shared/utils";
|
||||
import { loadLanguagePath } from "./helpers/utils";
|
||||
|
||||
const newInstance = i18n.createInstance();
|
||||
|
||||
const userLng = getCookie(LANGUAGE) || "en";
|
||||
const portalLng = window?.__ASC_INITIAL_EDITOR_STATE__?.portalSettings?.culture;
|
||||
|
||||
newInstance
|
||||
.use(Backend)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: getLtrLanguageForEditor(userLng, portalLng, true),
|
||||
fallbackLng: "en",
|
||||
load: "currentOnly",
|
||||
//debug: true,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
backend: {
|
||||
loadPath: loadLanguagePath(config.homepage),
|
||||
allowMultiLoading: true,
|
||||
crossDomain: false,
|
||||
},
|
||||
|
||||
ns: ["Editor", "Common", "DeepLink"],
|
||||
defaultNS: "Editor",
|
||||
|
||||
react: {
|
||||
useSuspense: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default newInstance;
|
@ -1 +0,0 @@
|
||||
import("./bootstrap");
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"PORT": "5013",
|
||||
"app": {
|
||||
"appsettings": "../../../buildtools/config"
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"PORT": "5013",
|
||||
"app": {
|
||||
"appsettings": "../../../../buildtools/config"
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import nconf from "nconf";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
nconf.argv().env().file("config", path.join(__dirname, "config.json"));
|
||||
|
||||
getAndSaveAppsettings();
|
||||
|
||||
function getAndSaveAppsettings() {
|
||||
let appsettings = nconf.get("app").appsettings;
|
||||
|
||||
if (!path.isAbsolute(appsettings)) {
|
||||
appsettings = path.join(__dirname, appsettings);
|
||||
}
|
||||
|
||||
const env = nconf.get("app").environment;
|
||||
|
||||
console.log('environment: ' + env);
|
||||
nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json'));
|
||||
nconf.file("appsettings", path.join(appsettings, 'appsettings.json'));
|
||||
|
||||
nconf.file(
|
||||
"appsettingsServices",
|
||||
path.join(appsettings, "appsettings.services.json")
|
||||
);
|
||||
}
|
||||
|
||||
export default nconf;
|
@ -1,226 +0,0 @@
|
||||
import express from "express";
|
||||
import template from "./lib/template";
|
||||
import devMiddleware from "./lib/middleware/devMiddleware";
|
||||
import i18nextMiddleware from "i18next-express-middleware";
|
||||
import i18next from "i18next";
|
||||
import path from "path";
|
||||
import compression from "compression";
|
||||
import ws from "./lib/websocket";
|
||||
import fs from "fs";
|
||||
import logger from "morgan";
|
||||
import winston from "./lib/logger.js";
|
||||
import { getAssets, initDocEditor } from "./lib/helpers";
|
||||
import renderApp from "./lib/helpers/render-app";
|
||||
import dns from "dns";
|
||||
import { translations } from "SRC_DIR/autoGeneratedTranslations";
|
||||
import { getLtrLanguageForEditor } from "@docspace/shared/utils/common";
|
||||
import { getLanguage } from "@docspace/shared/utils";
|
||||
import { xss } from "express-xss-sanitizer";
|
||||
|
||||
dns.setDefaultResultOrder("ipv4first");
|
||||
|
||||
const fallbackLng = "en";
|
||||
|
||||
let port = PORT;
|
||||
|
||||
const config = fs.readFileSync(path.join(__dirname, "config.json"), "utf-8");
|
||||
const parsedCOnfig = JSON.parse(config);
|
||||
|
||||
if (parsedCOnfig?.PORT) {
|
||||
port = parsedCOnfig.PORT;
|
||||
}
|
||||
|
||||
winston.stream = {
|
||||
write: (message) => winston.info(message),
|
||||
};
|
||||
|
||||
const app = express();
|
||||
|
||||
const resources = {};
|
||||
|
||||
translations.forEach((lngCol, key) => {
|
||||
resources[key] = {};
|
||||
lngCol.forEach((data, ns) => {
|
||||
if (resources[key]) {
|
||||
resources[key][ns] = data;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
i18next.init({
|
||||
fallbackLng: fallbackLng,
|
||||
load: "currentOnly",
|
||||
|
||||
saveMissing: true,
|
||||
ns: ["Editor", "Common", "DeepLink"],
|
||||
defaultNS: "Editor",
|
||||
|
||||
resources,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
format: function (value, format) {
|
||||
if (format === "lowercase") return value.toLowerCase();
|
||||
return value;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
app.use(i18nextMiddleware.handle(i18next));
|
||||
app.use(compression());
|
||||
app.use(xss());
|
||||
app.use(
|
||||
"/doceditor/",
|
||||
express.static(path.resolve(path.join(__dirname, "client")), {
|
||||
// don`t delete
|
||||
// https://github.com/pillarjs/send/issues/110
|
||||
cacheControl: false,
|
||||
})
|
||||
);
|
||||
|
||||
app.use(
|
||||
logger("dev", {
|
||||
stream: winston.stream,
|
||||
skip: function (req, res) {
|
||||
if (req.url == "/health") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
if (IS_DEVELOPMENT) {
|
||||
app.use(devMiddleware);
|
||||
|
||||
app.get("/health", (req, res) => {
|
||||
res.send({ status: "Healthy" });
|
||||
});
|
||||
|
||||
app.get("/doceditor", async (req, res) => {
|
||||
const { i18n, initialEditorState, assets } = req;
|
||||
const portalLng =
|
||||
getLanguage(initialEditorState?.portalSettings?.culture) || "en";
|
||||
const userLng = getLanguage(initialEditorState?.user?.cultureName);
|
||||
const finalLng = getLtrLanguageForEditor(userLng, portalLng, true);
|
||||
|
||||
await i18next.changeLanguage(finalLng);
|
||||
|
||||
let initialI18nStoreASC = {};
|
||||
|
||||
if (i18n && i18n?.services?.resourceStore?.data) {
|
||||
for (let key in i18n?.services?.resourceStore?.data) {
|
||||
if (key === "en" || key === finalLng) {
|
||||
initialI18nStoreASC[key] = i18n.services.resourceStore.data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialEditorState?.error) {
|
||||
winston.error(initialEditorState.error.errorMessage);
|
||||
}
|
||||
|
||||
const { component, styleTags } = renderApp(i18n, initialEditorState);
|
||||
|
||||
const htmlString = template(
|
||||
initialEditorState,
|
||||
component,
|
||||
styleTags,
|
||||
initialI18nStoreASC,
|
||||
finalLng,
|
||||
assets
|
||||
);
|
||||
|
||||
res.send(htmlString);
|
||||
});
|
||||
|
||||
const server = app.listen(port, () => {
|
||||
winston.info(`Server is listening on port ${port}`);
|
||||
});
|
||||
|
||||
const wss = ws(server);
|
||||
|
||||
const manifestFile = path.resolve(
|
||||
path.join(__dirname, "client/manifest.json")
|
||||
);
|
||||
|
||||
let fsWait = false;
|
||||
let waitTimeout = null;
|
||||
fs.watch(manifestFile, (event, filename) => {
|
||||
if (filename && event === "change") {
|
||||
if (fsWait) return;
|
||||
fsWait = true;
|
||||
waitTimeout = setTimeout(() => {
|
||||
fsWait = false;
|
||||
clearTimeout(waitTimeout);
|
||||
wss.broadcast("reload");
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let assets;
|
||||
|
||||
try {
|
||||
assets = getAssets();
|
||||
} catch (e) {
|
||||
winston.error(e.message);
|
||||
}
|
||||
|
||||
app.get("/health", (req, res) => {
|
||||
res.send({ status: "Healthy" });
|
||||
});
|
||||
|
||||
app.get("/doceditor", async (req, res) => {
|
||||
const { i18n } = req;
|
||||
let initialEditorState;
|
||||
|
||||
try {
|
||||
initialEditorState = await initDocEditor(req);
|
||||
} catch (e) {
|
||||
winston.error(e.message);
|
||||
}
|
||||
|
||||
const portalLng =
|
||||
getLanguage(initialEditorState?.portalSettings?.culture) || "en";
|
||||
const userLng = getLanguage(initialEditorState?.user?.cultureName);
|
||||
const finalLng = getLtrLanguageForEditor(userLng, portalLng, true);
|
||||
|
||||
await i18next.changeLanguage(finalLng);
|
||||
|
||||
let initialI18nStoreASC = {};
|
||||
|
||||
if (i18n && i18n?.services?.resourceStore?.data) {
|
||||
for (let key in i18n?.services?.resourceStore?.data) {
|
||||
if (key === "en" || key === finalLng) {
|
||||
initialI18nStoreASC[key] = i18n.services.resourceStore.data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (initialEditorState?.error) {
|
||||
winston.error(initialEditorState.error.errorMessage);
|
||||
}
|
||||
|
||||
const { component, styleTags } = renderApp(i18n, initialEditorState);
|
||||
|
||||
const htmlString = template(
|
||||
initialEditorState,
|
||||
component,
|
||||
styleTags,
|
||||
initialI18nStoreASC,
|
||||
finalLng,
|
||||
assets
|
||||
);
|
||||
|
||||
if (initialEditorState.isSettingsError) {
|
||||
res.redirect("/access-restricted");
|
||||
}
|
||||
|
||||
res.send(htmlString);
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
winston.info(`Server is listening on port ${port}`);
|
||||
});
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { initSSR } from "@docspace/shared/api/client";
|
||||
import { getUser } from "@docspace/shared/api/people";
|
||||
import {
|
||||
getSettings,
|
||||
getBuildVersion,
|
||||
getAppearanceTheme,
|
||||
getLogoUrls,
|
||||
} from "@docspace/shared/api/settings";
|
||||
import {
|
||||
openEdit,
|
||||
getSettingsFiles,
|
||||
// getShareFiles,
|
||||
} from "@docspace/shared/api/files";
|
||||
import { TenantStatus } from "@docspace/shared/enums";
|
||||
|
||||
import { getLtrLanguageForEditor } from "@docspace/shared/utils/common";
|
||||
import { getLogoFromPath } from "@docspace/shared/utils";
|
||||
|
||||
export const getFavicon = (logoUrls) => {
|
||||
if (!logoUrls) return null;
|
||||
|
||||
return getLogoFromPath(logoUrls[2]?.path?.light);
|
||||
};
|
||||
|
||||
export const initDocEditor = async (req) => {
|
||||
if (!req) return false;
|
||||
let personal = IS_PERSONAL || null;
|
||||
const { headers, url, query, type } = req;
|
||||
const { version, desktop: isDesktop } = query;
|
||||
let error = null,
|
||||
user,
|
||||
settings,
|
||||
filesSettings,
|
||||
versionInfo,
|
||||
appearanceTheme,
|
||||
logoUrls;
|
||||
initSSR(headers);
|
||||
|
||||
try {
|
||||
const decodedId = query.fileId || query.fileid || null;
|
||||
const fileId =
|
||||
typeof decodedId === "string" ? encodeURIComponent(decodedId) : decodedId;
|
||||
|
||||
if (!fileId) {
|
||||
return {
|
||||
props: {
|
||||
needLoader: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const doc = query?.doc || null;
|
||||
const shareKey = query?.share ?? null;
|
||||
const view = url.indexOf("action=view") !== -1;
|
||||
const fileVersion = version || null;
|
||||
|
||||
const baseSettings = [
|
||||
getUser(null, headers),
|
||||
getAppearanceTheme(headers),
|
||||
getLogoUrls(headers),
|
||||
];
|
||||
let settings;
|
||||
|
||||
try {
|
||||
settings = await getSettings(false, headers);
|
||||
} catch (err) {
|
||||
console.error("initDocEditor settings failed", err);
|
||||
|
||||
return { isSettingsError: true };
|
||||
}
|
||||
|
||||
[user, appearanceTheme, logoUrls] = await Promise.all(baseSettings);
|
||||
|
||||
if (settings.tenantStatus === TenantStatus.PortalRestore) {
|
||||
error = "restore-backup";
|
||||
return { error, logoUrls };
|
||||
}
|
||||
|
||||
[filesSettings, versionInfo] = await Promise.all([
|
||||
getSettingsFiles(headers),
|
||||
getBuildVersion(headers),
|
||||
]);
|
||||
|
||||
const successAuth = !!user;
|
||||
|
||||
personal = settings?.personal;
|
||||
|
||||
if (!successAuth && !doc && !shareKey) {
|
||||
error = {
|
||||
unAuthorized: true,
|
||||
};
|
||||
return { error };
|
||||
}
|
||||
|
||||
const config = await openEdit(
|
||||
fileId,
|
||||
fileVersion,
|
||||
doc,
|
||||
view,
|
||||
headers,
|
||||
shareKey
|
||||
);
|
||||
|
||||
//const sharingSettings = await getShareFiles([+fileId], []);
|
||||
|
||||
const isSharingAccess = config?.file?.canShare;
|
||||
|
||||
if (view) {
|
||||
config.editorConfig.mode = "view";
|
||||
}
|
||||
|
||||
if (type) {
|
||||
config.type = type;
|
||||
}
|
||||
|
||||
// logoUrls.forEach((logo, index) => {
|
||||
// logoUrls[index].path.dark = getLogoFromPath(logo.path.dark);
|
||||
// logoUrls[index].path.light = getLogoFromPath(logo.path.dark);
|
||||
// });
|
||||
|
||||
// change only for default logo
|
||||
if (
|
||||
config?.editorConfig?.customization?.logo?.image.indexOf("images/logo/") >
|
||||
-1
|
||||
) {
|
||||
config.editorConfig.customization.logo.image =
|
||||
config.editorConfig.customization.logo.url +
|
||||
getLogoFromPath(config.editorConfig.customization.logo.image);
|
||||
}
|
||||
|
||||
// change only for default logo
|
||||
if (
|
||||
config?.editorConfig?.customization?.logo?.imageDark.indexOf(
|
||||
"images/logo/"
|
||||
) > -1
|
||||
) {
|
||||
config.editorConfig.customization.logo.imageDark =
|
||||
config.editorConfig.customization.logo.url +
|
||||
getLogoFromPath(config.editorConfig.customization.logo.imageDark);
|
||||
}
|
||||
|
||||
if (
|
||||
config.editorConfig.customization.customer &&
|
||||
config.editorConfig.customization.customer.logo.indexOf("images/logo/") >
|
||||
-1
|
||||
) {
|
||||
config.editorConfig.customization.customer.logo =
|
||||
config.editorConfig.customization.logo.url +
|
||||
getLogoFromPath(config.editorConfig.customization.customer.logo);
|
||||
}
|
||||
// needed to reset rtl language in Editor
|
||||
config.editorConfig.lang = getLtrLanguageForEditor(
|
||||
user?.cultureName,
|
||||
settings.culture,
|
||||
true
|
||||
);
|
||||
|
||||
return {
|
||||
config,
|
||||
personal,
|
||||
successAuth,
|
||||
user,
|
||||
error,
|
||||
isSharingAccess,
|
||||
url,
|
||||
doc,
|
||||
fileId,
|
||||
view,
|
||||
filesSettings,
|
||||
//sharingSettings,
|
||||
portalSettings: settings,
|
||||
versionInfo,
|
||||
appearanceTheme,
|
||||
logoUrls,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("initDocEditor failed", err);
|
||||
let message = "";
|
||||
if (typeof err === "string") message = err;
|
||||
else message = err.response?.data?.error?.message || err.message;
|
||||
|
||||
const errorStatus =
|
||||
typeof err !== "string"
|
||||
? err?.response?.data?.statusCode || err?.response?.data?.status
|
||||
: null;
|
||||
|
||||
error = {
|
||||
errorMessage: message,
|
||||
errorStatus,
|
||||
};
|
||||
return { error, user, logoUrls };
|
||||
}
|
||||
};
|
||||
|
||||
export const getAssets = () => {
|
||||
const manifest = fs.readFileSync(
|
||||
path.join(__dirname, "client/manifest.json"),
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
const assets = JSON.parse(manifest);
|
||||
|
||||
return assets;
|
||||
};
|
||||
|
||||
export const getScripts = (assets) => {
|
||||
const regTest = /static\/js\/.*/;
|
||||
const keys = [];
|
||||
|
||||
for (let key in assets) {
|
||||
if (assets.hasOwnProperty(key) && regTest.test(key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
@ -1,26 +0,0 @@
|
||||
import React from "react";
|
||||
import { ServerStyleSheet } from "styled-components";
|
||||
import GlobalStyle from "../../../client/components/GlobalStyle";
|
||||
import Editor from "../../../client/components/Editor";
|
||||
import { renderToString } from "react-dom/server";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
|
||||
const renderApp = (i18n, initialState) => {
|
||||
const sheet = new ServerStyleSheet();
|
||||
const component = renderToString(
|
||||
sheet.collectStyles(
|
||||
<React.Suspense fallback={<div></div>}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<GlobalStyle />
|
||||
<Editor {...initialState} />
|
||||
</I18nextProvider>
|
||||
</React.Suspense>,
|
||||
),
|
||||
);
|
||||
|
||||
const styleTags = sheet.getStyleTags();
|
||||
|
||||
return { component, styleTags };
|
||||
};
|
||||
|
||||
export default renderApp;
|
@ -1,106 +0,0 @@
|
||||
import winston from "winston";
|
||||
import WinstonCloudWatch from "winston-cloudwatch";
|
||||
import date from "date-and-time";
|
||||
import os from "os";
|
||||
import { randomUUID } from "crypto";
|
||||
import "winston-daily-rotate-file";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import config from "../config";
|
||||
|
||||
let logPath = config.get("logPath");
|
||||
let logLevel = config.get("logLevel") || "debug";
|
||||
|
||||
if (logPath != null) {
|
||||
if (!path.isAbsolute(logPath)) {
|
||||
logPath = path.join(__dirname, "..", logPath);
|
||||
}
|
||||
}
|
||||
|
||||
const fileName = logPath
|
||||
? path.join(logPath, "editor.%DATE%.log")
|
||||
: path.join(__dirname, "..", "..", "..", "Logs", "editor.%DATE%.log");
|
||||
const dirName = path.dirname(fileName);
|
||||
|
||||
const aws = config.get("aws").cloudWatch;
|
||||
|
||||
const accessKeyId = aws.accessKeyId;
|
||||
const secretAccessKey = aws.secretAccessKey;
|
||||
const awsRegion = aws.region;
|
||||
const logGroupName = aws.logGroupName;
|
||||
const logStreamName = aws.logStreamName.replace("${hostname}", os.hostname())
|
||||
.replace("${applicationContext}", "Editor")
|
||||
.replace("${guid}", randomUUID())
|
||||
.replace("${date}", date.format(new Date(), 'YYYY/MM/DDTHH.mm.ss'));
|
||||
|
||||
|
||||
if (!fs.existsSync(dirName)) {
|
||||
fs.mkdirSync(dirName);
|
||||
}
|
||||
|
||||
const options = {
|
||||
file: {
|
||||
filename: fileName,
|
||||
level: logLevel,
|
||||
datePattern: "MM-DD",
|
||||
handleExceptions: true,
|
||||
humanReadableUnhandledException: true,
|
||||
zippedArchive: true,
|
||||
maxSize: "50m",
|
||||
maxFiles: "30d",
|
||||
json: true,
|
||||
},
|
||||
console: {
|
||||
level: logLevel,
|
||||
handleExceptions: true,
|
||||
json: false,
|
||||
colorize: true,
|
||||
},
|
||||
cloudWatch: {
|
||||
name: 'aws',
|
||||
level: logLevel,
|
||||
logStreamName: logStreamName,
|
||||
logGroupName: logGroupName,
|
||||
awsRegion: awsRegion,
|
||||
jsonMessage: true,
|
||||
awsOptions: {
|
||||
credentials: {
|
||||
accessKeyId: accessKeyId,
|
||||
secretAccessKey: secretAccessKey
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let transports = [
|
||||
new winston.transports.Console(options.console),
|
||||
new winston.transports.DailyRotateFile(options.file)
|
||||
];
|
||||
|
||||
if (aws != null && aws.accessKeyId !== '')
|
||||
{
|
||||
transports.push(new WinstonCloudWatch(options.cloudWatch));
|
||||
}
|
||||
|
||||
const customFormat = winston.format(info => {
|
||||
const now = new Date();
|
||||
|
||||
info.date = date.format(now, 'YYYY-MM-DD HH:mm:ss');
|
||||
info.applicationContext = "Editor";
|
||||
info.level = info.level.toUpperCase();
|
||||
|
||||
const hostname = os.hostname();
|
||||
|
||||
info["instance-id"] = hostname;
|
||||
|
||||
return info;
|
||||
})();
|
||||
|
||||
export default new winston.createLogger({
|
||||
format: winston.format.combine(
|
||||
customFormat,
|
||||
winston.format.json()
|
||||
),
|
||||
transports: transports,
|
||||
exitOnError: false,
|
||||
});
|
@ -1,22 +0,0 @@
|
||||
import winston from "../logger.js";
|
||||
import { getAssets, initDocEditor } from "../helpers";
|
||||
|
||||
winston.stream = {
|
||||
write: (message) => winston.info(message),
|
||||
};
|
||||
|
||||
export default async (req, res, next) => {
|
||||
try {
|
||||
const assets = await getAssets();
|
||||
req.initialEditorState = await initDocEditor(req);
|
||||
|
||||
if (req.initialEditorState.isSettingsError) {
|
||||
res.redirect("/access-restricted");
|
||||
}
|
||||
|
||||
req.assets = assets;
|
||||
} catch (e) {
|
||||
winston.error(e.message);
|
||||
}
|
||||
next();
|
||||
};
|
@ -1,425 +0,0 @@
|
||||
import { getFavicon, getScripts } from "./helpers";
|
||||
import pkg from "../../../package.json";
|
||||
import fontsCssUrl from "PUBLIC_DIR/css/fonts.css?url";
|
||||
|
||||
export default function template(
|
||||
initialEditorState = {},
|
||||
appComponent = "",
|
||||
styleTags,
|
||||
initialI18nStoreASC,
|
||||
initialLanguage,
|
||||
assets
|
||||
) {
|
||||
const { title } = pkg;
|
||||
const { error } = initialEditorState;
|
||||
const editorUrl = initialEditorState?.config?.editorUrl;
|
||||
const faviconHref = getFavicon(initialEditorState?.logoUrls);
|
||||
|
||||
let clientScripts =
|
||||
assets && assets.hasOwnProperty("client.js")
|
||||
? `<script defer="defer" src="${assets["client.js"]}"></script>`
|
||||
: "";
|
||||
|
||||
const editorApiScript =
|
||||
error || !editorUrl
|
||||
? ""
|
||||
: `<script type="text/javascript" id="onlyoffice-api-script" src="${editorUrl}" async></script>`;
|
||||
|
||||
if (!IS_DEVELOPMENT) {
|
||||
const productionBundleKeys = getScripts(assets);
|
||||
productionBundleKeys.map((key) => {
|
||||
clientScripts =
|
||||
clientScripts + `<script defer="defer" src="${assets[key]}"></script>`;
|
||||
});
|
||||
}
|
||||
|
||||
const initialEditorStateStringify = JSON.stringify(initialEditorState);
|
||||
|
||||
const lt = /</g,
|
||||
gt = />/g;
|
||||
|
||||
const initialEditorStateString = initialEditorStateStringify
|
||||
.replace(lt, "<")
|
||||
.replace(gt, ">");
|
||||
|
||||
const scripts = `
|
||||
<script id="__ASC_INITIAL_EDITOR_STATE__">
|
||||
window.__ASC_INITIAL_EDITOR_STATE__ = ${initialEditorStateString}
|
||||
</script>
|
||||
<script id="__ASC_INITIAL_EDITOR_I18N__">
|
||||
window.initialI18nStoreASC = ${JSON.stringify(initialI18nStoreASC)}
|
||||
window.initialLanguage = "${initialLanguage}"
|
||||
</script>
|
||||
${clientScripts}
|
||||
<script>
|
||||
const tempElm = document.getElementById("loader");
|
||||
tempElm.style.backgroundColor =
|
||||
localStorage.theme === "Dark" ? "#333333" : "#f4f4f4";
|
||||
console.log("It's Editor INIT");
|
||||
fetch("${CONFIG_URL}")
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("HTTP error " + response.status);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((config) => {
|
||||
window.DocSpaceConfig = {
|
||||
...config,
|
||||
};
|
||||
|
||||
if (window.navigator.userAgent.includes("ZoomWebKit") || window.navigator.userAgent.includes("ZoomApps")) {
|
||||
window.DocSpaceConfig.editor = {
|
||||
openOnNewPage: false,
|
||||
requestClose: true
|
||||
};
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
</script>
|
||||
${editorApiScript}
|
||||
|
||||
`;
|
||||
// <script defer="defer" src="${assets["runtime.js"]}"></script>
|
||||
// <script defer="defer" src="${assets["vendor.js"]}"></script>
|
||||
const page = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title> ${title} </title>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="stylesheet" type="text/css" href="${fontsCssUrl}" />
|
||||
|
||||
<link id="favicon" rel="shortcut icon" href="${faviconHref}" type="image/x-icon"/>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link rel="apple-touch-icon" href="${faviconHref}" />
|
||||
<link rel="android-touch-icon" href="${faviconHref}" />
|
||||
${styleTags}
|
||||
<style type="text/css">
|
||||
.loadmask {
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
background-color: #f4f4f4;
|
||||
z-index: 1001;
|
||||
}
|
||||
.loader-page {
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
bottom: 42%;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
line-height: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.loader-page-romb {
|
||||
width: 40px;
|
||||
display: inline-block;
|
||||
}
|
||||
.romb {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
background: red;
|
||||
border-radius: 6px;
|
||||
-webkit-transform: rotate(135deg) skew(20deg, 20deg);
|
||||
-moz-transform: rotate(135deg) skew(20deg, 20deg);
|
||||
-ms-transform: rotate(135deg) skew(20deg, 20deg);
|
||||
-o-transform: rotate(135deg) skew(20deg, 20deg);
|
||||
-webkit-animation: movedown 3s infinite ease;
|
||||
-moz-animation: movedown 3s infinite ease;
|
||||
-ms-animation: movedown 3s infinite ease;
|
||||
-o-animation: movedown 3s infinite ease;
|
||||
animation: movedown 3s infinite ease;
|
||||
}
|
||||
#blue {
|
||||
z-index: 3;
|
||||
background: #55bce6;
|
||||
-webkit-animation-name: blue;
|
||||
-moz-animation-name: blue;
|
||||
-ms-animation-name: blue;
|
||||
-o-animation-name: blue;
|
||||
animation-name: blue;
|
||||
}
|
||||
#red {
|
||||
z-index: 1;
|
||||
background: #de7a59;
|
||||
-webkit-animation-name: red;
|
||||
-moz-animation-name: red;
|
||||
-ms-animation-name: red;
|
||||
-o-animation-name: red;
|
||||
animation-name: red;
|
||||
}
|
||||
#green {
|
||||
z-index: 2;
|
||||
background: #a1cb5c;
|
||||
-webkit-animation-name: green;
|
||||
-moz-animation-name: green;
|
||||
-ms-animation-name: green;
|
||||
-o-animation-name: green;
|
||||
animation-name: green;
|
||||
}
|
||||
@-webkit-keyframes red {
|
||||
0% {
|
||||
top: 120px;
|
||||
background: #de7a59;
|
||||
}
|
||||
10% {
|
||||
top: 120px;
|
||||
background: #f2cbbf;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 120px;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
}
|
||||
20% {
|
||||
background: #e6e4e4;
|
||||
}
|
||||
30% {
|
||||
background: #d2d2d2;
|
||||
}
|
||||
40% {
|
||||
top: 120px;
|
||||
}
|
||||
100% {
|
||||
top: 120px;
|
||||
background: #de7a59;
|
||||
}
|
||||
}
|
||||
@keyframesred {
|
||||
0% {
|
||||
top: 120px;
|
||||
background: #de7a59;
|
||||
}
|
||||
10% {
|
||||
top: 120px;
|
||||
background: #f2cbbf;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 120px;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
}
|
||||
20% {
|
||||
background: #e6e4e4;
|
||||
}
|
||||
30% {
|
||||
background: #d2d2d2;
|
||||
}
|
||||
40% {
|
||||
top: 120px;
|
||||
}
|
||||
100% {
|
||||
top: 120px;
|
||||
background: #de7a59;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes green {
|
||||
0% {
|
||||
top: 110px;
|
||||
background: #a1cb5c;
|
||||
opacity: 1;
|
||||
}
|
||||
10% {
|
||||
top: 110px;
|
||||
background: #cbe0ac;
|
||||
opacity: 1;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 110px;
|
||||
opacity: 1;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
background: #efefef;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
30% {
|
||||
background: #e6e4e4;
|
||||
}
|
||||
70% {
|
||||
top: 110px;
|
||||
}
|
||||
100% {
|
||||
top: 110px;
|
||||
background: #a1cb5c;
|
||||
}
|
||||
}
|
||||
@keyframes green {
|
||||
0% {
|
||||
top: 110px;
|
||||
background: #a1cb5c;
|
||||
opacity: 1;
|
||||
}
|
||||
10% {
|
||||
top: 110px;
|
||||
background: #cbe0ac;
|
||||
opacity: 1;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 110px;
|
||||
opacity: 1;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
background: #efefef;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
30% {
|
||||
background: #e6e4e4;
|
||||
}
|
||||
70% {
|
||||
top: 110px;
|
||||
}
|
||||
100% {
|
||||
top: 110px;
|
||||
background: #a1cb5c;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes blue {
|
||||
0% {
|
||||
top: 100px;
|
||||
background: #55bce6;
|
||||
opacity: 1;
|
||||
}
|
||||
10% {
|
||||
top: 100px;
|
||||
background: #bfe8f8;
|
||||
opacity: 1;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 100px;
|
||||
opacity: 1;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
45% {
|
||||
background: #efefef;
|
||||
top: 0;
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
top: 100px;
|
||||
background: #55bce6;
|
||||
}
|
||||
}
|
||||
@keyframes blue {
|
||||
0% {
|
||||
top: 100px;
|
||||
background: #55bce6;
|
||||
opacity: 1;
|
||||
}
|
||||
10% {
|
||||
top: 100px;
|
||||
background: #bfe8f8;
|
||||
opacity: 1;
|
||||
}
|
||||
14% {
|
||||
background: #f4f4f4;
|
||||
top: 100px;
|
||||
opacity: 1;
|
||||
}
|
||||
15% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
background: #f4f4f4;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
background: #fff;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
45% {
|
||||
background: #efefef;
|
||||
top: 0;
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
top: 100px;
|
||||
background: #55bce6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="loader" class="loadmask">
|
||||
<div class="loader-page">
|
||||
<div class="loader-page-romb">
|
||||
<div class="romb" id="blue"></div>
|
||||
<div class="romb" id="green"></div>
|
||||
<div class="romb" id="red"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="root">${appComponent}</div>
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
<script src="${BROWSER_DETECTOR_URL}"></script>
|
||||
${scripts}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
return page;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
const WebSocket = require("ws");
|
||||
const pkg = require("../../../package.json");
|
||||
const { socketPath } = pkg;
|
||||
|
||||
module.exports = (expressServer) => {
|
||||
const wss = new WebSocket.Server({
|
||||
noServer: true,
|
||||
path: socketPath,
|
||||
});
|
||||
|
||||
expressServer.on("upgrade", (request, socket, head) => {
|
||||
wss.handleUpgrade(request, socket, head, (websocket) => {
|
||||
wss.emit("connection", websocket, request);
|
||||
});
|
||||
});
|
||||
|
||||
wss.on("connection", function connection(ws) {
|
||||
ws.on("message", function (message) {
|
||||
wss.broadcast(message);
|
||||
});
|
||||
});
|
||||
|
||||
wss.broadcast = function broadcast(msg) {
|
||||
wss.clients.forEach(function each(client) {
|
||||
client.send(msg);
|
||||
});
|
||||
};
|
||||
|
||||
return wss;
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
// 👇️ add all the directories and files
|
||||
// that you want to lint here
|
||||
"src",
|
||||
// add all files in which you see
|
||||
// the "parserOptions.project" error
|
||||
".eslintrc.cjs",
|
||||
"__mocks__",
|
||||
"jest.config.ts",
|
||||
".storybook",
|
||||
"babel.config.ts",
|
||||
"index.d.ts",
|
||||
"tsconfig.eslint.json"
|
||||
]
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"extends": "../shared/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"PUBLIC_DIR/*": ["../../public/*"],
|
||||
"SRC_DIR/*": ["./src/*"],
|
||||
},
|
||||
},
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user