Delete @docspace/editor

This commit is contained in:
Timofey Boyko 2024-02-26 11:28:45 +03:00
parent 6d80c6f343
commit 271b4fb63e
103 changed files with 4 additions and 3611 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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"
}

View File

@ -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",
],
};

View File

@ -1 +0,0 @@
dist/* linguist-vendored=false

View File

@ -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

View File

@ -1,3 +0,0 @@
{
"extends": "../shared/.prettierrc.json"
}

View File

@ -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" ]

View File

@ -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",
};

View File

@ -1,9 +0,0 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"components": ["@docspace/shared/components"]
}
},
"exclude": ["node_modules"]
}

View File

@ -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"
}
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "يمكنك فتح المستند من خلال البوابة أو بواسطة تطبيق الهاتف",
"OpenInApp": "فتح بواسطة التطبيق",
"OpeningDocument": "فتح المستند",
"StayInBrowser": "متابعة من خلال المتصفح"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "وثائق",
"ErrorConnectionLost": "الاتصال مفقود",
"FileLocation": "افتح موقع ملف",
"FileName": "اسم الملف",
"ImageFileType": "الصور",
"MailMergeFileType": "حدد ملف XLSX",
"OpenSavedDocument": "افتح المستند المحفوظ في علامة تبويب جديدة",
"SelectFilesType": "حدد نوع الملفات : {{fileType}}",
"UsersWithoutAccess": "بعض المستخدمين الذين تريد ذكرهم ليس لديهم حق الوصول إلى الغرفة: {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Можете да отворите документа в портала или в мобилното приложение",
"OpenInApp": "Отвори в приложението",
"OpeningDocument": "Отваряне на документ",
"StayInBrowser": "Остани в браузъра"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "документи",
"ErrorConnectionLost": "Връзката е изгубена",
"FileLocation": "Mестоположението на файла",
"FileName": "Име на файла",
"ImageFileType": "снимки",
"MailMergeFileType": "Изберете файл във XLSX формат",
"OpenSavedDocument": "Отворете записания документ в нов раздел",
"SelectFilesType": "Изберете файлове от тип: {{fileType}}",
"UsersWithoutAccess": "Някои потребители, които искате да споменете, нямат достъп до стаята: {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Μπορείτε να ανοίξετε το έγγραφο στην πύλη ή στην εφαρμογή για κινητά",
"OpenInApp": "Άνοιγμα στην εφαρμογή",
"OpeningDocument": "Άνοιγμα εγγράφου",
"StayInBrowser": "Παραμονή στο πρόγραμμα περιήγησης"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "Έγγραφα",
"ErrorConnectionLost": "Η σύνδεση χάθηκε",
"FileLocation": "Άνοιγμα τοποθεσίας αρχείου",
"FileName": "Όνομα αρχείου",
"ImageFileType": "Εικόνες",
"MailMergeFileType": "Επιλέξτε το αρχείο σε μορφή XLSX",
"OpenSavedDocument": "Άνοιγμα αποθηκευμένου εγγράφου σε νέα καρτέλα",
"SelectFilesType": "Επιλέξτε αρχεία τύπου: {{fileType}}",
"UsersWithoutAccess": "Ορισμένοι χρήστες τους οποίους θέλετε να αναφέρετε δεν έχουν πρόσβαση στο δωμάτιο: {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Voit avata asiakirjan portaalissa tai mobiilisovelluksessa",
"OpenInApp": "Avaa sovelluksessa",
"OpeningDocument": "Avataan asiakirjaa",
"StayInBrowser": "Pysy selaimessa"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Դուք կարող եք բացել փաստաթուղթը պորտալում կամ բջջային հավելվածում",
"OpenInApp": "Բացեք հավելվածում",
"OpeningDocument": "Փաստաթղթի բացում",
"StayInBrowser": "Մնացեք բրաուզերո"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "Փաստաթղթեր",
"ErrorConnectionLost": "Կապը ընդհատվեց",
"FileLocation": "Բացել ֆայլի գտնվելու վայրը",
"FileName": "ֆայլի անուն",
"ImageFileType": "Պատկերներ",
"MailMergeFileType": "Ընտրել ֆայլը XLSX ձևաչափով",
"OpenSavedDocument": "Բացել պահպանված փաստաթուղթը նոր ներդիրում",
"SelectFilesType": "Ընտրեք տեսակի ֆայլեր՝ {{fileType}}",
"UsersWithoutAccess": "Որոշ օգտատերեր, որոնց ցանկանում եք նշել, մուտք չունեն սենյակ. {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "ポータルまたはモバイルアプリケーションでドキュメントを開くことができます",
"OpenInApp": "アプリで開く",
"OpeningDocument": "ドキュメントを開いています",
"StayInBrowser": "ブラウザのまま"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "ドキュメント",
"ErrorConnectionLost": "接続が切断されました",
"FileLocation": "ファイルの場所を開く",
"FileName": "ファイル名",
"ImageFileType": "画像",
"MailMergeFileType": "XLSX形式のファイルを選択する",
"OpenSavedDocument": "保存されたファイルを新しいタブで開く",
"SelectFilesType": " {{fileType}}タイプのファイルの選択",
"UsersWithoutAccess": "言及したいユーザーの中には、ルームにアクセスできない人がいます:{{users}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "포털이나 모바일 애플리케이션에서 문서를 열 수 있습니다",
"OpenInApp": "앱에서 열기",
"OpeningDocument": "문서 여는 중",
"StayInBrowser": "계속 브라우저 사용"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "문서",
"ErrorConnectionLost": "연결이 끊어졌습니다",
"FileLocation": "파일 위치 열기",
"FileName": "파일명",
"ImageFileType": "이미지",
"MailMergeFileType": "XLSX 포맷 파일 선택",
"OpenSavedDocument": "새로운 탭에서 저장 문서 열기",
"SelectFilesType": "파일 유형 선택: {{fileType}}",
"UsersWithoutAccess": "언급하려는 일부 사용자가 방에 액세스할 수 없습니다: {{users}}"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "ເອກະສານ",
"ErrorConnectionLost": "ການເຊື່ອມຕໍ່ຫາຍໄປ",
"FileLocation": "ເປີດບ່ອນຕຳແໜ່ງເອກະສານ",
"FileName": "ຊື່ຟາຍ",
"ImageFileType": "ຮູບພາບ",
"MailMergeFileType": "ກະລຸນາເລືືອກໄຟລ໌ເປັນ .XLSX",
"OpenSavedDocument": "ເປີດເອກະສານທີ່ບັນທືກໄວ້ໃນແຖບໃໝ່",
"SelectFilesType": "ກະລຸນາເລືອກປະເພດໄຟລ໌ {{fileType}}",
"UsersWithoutAccess": "ຜູ້​ໃຊ້​ບາງ​ຄົນ​ທີ່​ທ່ານ​ຕ້ອງ​ການ​ກ່າວ​ເຖິງ​ບໍ່​ມີ​ການ​ເຂົ້າ​ເຖິງ​ຫ້ອງ: {{users}}"
}

View File

@ -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ā"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Вы можете открыть документ на портале или в мобильном приложении",
"OpenInApp": "Открыть в приложении",
"OpeningDocument": "Открытие документа",
"StayInBrowser": "Остаться в браузере"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "документы",
"ErrorConnectionLost": "Соединение потеряно",
"FileLocation": "Открыть расположение файла",
"FileName": "Имя файла",
"ImageFileType": "изображения",
"MailMergeFileType": "Выбрать файлы в формате XLSX",
"OpenSavedDocument": "Открыть сохраненный документ в новой вкладке",
"SelectFilesType": "Выбрать файлы типа: {{fileType}}",
"UsersWithoutAccess": "Некоторые пользователи, которых вы хотите упомянуть, не имеют доступа к комнате: {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "Ви можете відкрити документ на порталі або в мобільному застосунку",
"OpenInApp": "Відкрити в застосунку",
"OpeningDocument": "Відкриття документа",
"StayInBrowser": "Залишитися у браузері"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "документи",
"ErrorConnectionLost": "З'єднання втрачено",
"FileLocation": "Перейти до документів",
"FileName": "Ім'я файлу",
"ImageFileType": "картинки",
"MailMergeFileType": "Вибрати файл у форматі XLSX",
"OpenSavedDocument": "Відкрити збережений документ на новій вкладці",
"SelectFilesType": "Вибрати файли типу: {{fileType}}",
"UsersWithoutAccess": "Деякі користувачі, яких ви хочете згадати, не мають доступу до кімнати: {{users}}"
}

View File

@ -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"
}

View File

@ -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}}"
}

View File

@ -1,6 +0,0 @@
{
"DeepLinkText": "您可以在门户或移动应用中打开文档",
"OpenInApp": "在应用中打开",
"OpeningDocument": "正在打开文档",
"StayInBrowser": "始终在浏览器中"
}

View File

@ -1,11 +0,0 @@
{
"DocumentsFileType": "文档",
"ErrorConnectionLost": "已断开连接",
"FileLocation": "打开文件的位置",
"FileName": "文件名称",
"ImageFileType": "图片",
"MailMergeFileType": "选择XLSX格式的文件",
"OpenSavedDocument": "在新标签中打开已保存的文件",
"SelectFilesType": "选择类型的文件: {{fileType}}",
"UsersWithoutAccess": "您想提及的部分用户没有房间访问权限:{{users}}"
}

View File

@ -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",
}
);

View File

@ -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>
);

View File

@ -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();

View File

@ -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;
}
`;

View File

@ -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));

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 };

View File

@ -1,2 +0,0 @@
export const CLIENT_SCOPE = "client";
export const CLIENT_REMOTE_ENTRY_URL = "/remoteEntry.js";

View File

@ -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);
};

View File

@ -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;

View File

@ -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;

View File

@ -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],
};
}
}
}
}
};

View File

@ -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;

View File

@ -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;

View File

@ -1 +0,0 @@
import("./bootstrap");

View File

@ -1,6 +0,0 @@
{
"PORT": "5013",
"app": {
"appsettings": "../../../buildtools/config"
}
}

View File

@ -1,6 +0,0 @@
{
"PORT": "5013",
"app": {
"appsettings": "../../../../buildtools/config"
}
}

View File

@ -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;

View File

@ -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}`);
});
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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,
});

View File

@ -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();
};

View File

@ -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, "&lt;")
.replace(gt, "&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;
}

View File

@ -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;
};

View File

@ -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"
]
}

View File

@ -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