Merge branch 'develop' of github.com:ONLYOFFICE/DocSpace into feature/new-profile

# Conflicts:
#	packages/client/src/pages/My/i18n.js
#	packages/client/src/pages/Profile/Section/Body/index.js
This commit is contained in:
Viktor Fomin 2022-09-05 16:47:09 +03:00
commit bcdc2993c6
174 changed files with 3814 additions and 2589 deletions

View File

@ -36,7 +36,6 @@ powershell -Command "(gc build\deploy\nginx\onlyoffice.conf) -replace '#', '' |
xcopy config\nginx\sites-enabled\* build\deploy\nginx\sites-enabled\ /E /R /Y
REM fix paths
powershell -Command "(gc build\deploy\nginx\sites-enabled\onlyoffice-login.conf) -replace 'ROOTPATH', '%~dp0deploy\login' -replace '\\', '/' | Out-File -encoding ASCII build\deploy\nginx\sites-enabled\onlyoffice-login.conf"
powershell -Command "(gc build\deploy\nginx\sites-enabled\onlyoffice-client.conf) -replace 'ROOTPATH', '%~dp0deploy\client' -replace '\\', '/' | Out-File -encoding ASCII build\deploy\nginx\sites-enabled\onlyoffice-client.conf"
REM restart nginx

10
build/run/Login.xml Normal file
View File

@ -0,0 +1,10 @@
<service>
<id>OnlyofficeLogin</id>
<name>ONLYOFFICE Login SSR</name>
<startmode>manual</startmode>
<executable>node</executable>
<arguments>../../build/deploy/login/server.js</arguments>
<log mode="none"/>
<delayedAutoStart>true</delayedAutoStart>
<onfailure action="none" />
</service>

View File

@ -143,8 +143,17 @@ server {
}
location /login {
#rewrite login/(.*) /$1 break;
proxy_pass http://localhost:5011;
proxy_redirect off;
proxy_set_header Host $this_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /sockjs-node {

View File

@ -1,9 +0,0 @@
server {
listen 5011;
root "ROOTPATH";
index index.html;
location / {
try_files $uri /index.html =404;
}
}

View File

@ -1,5 +1,9 @@
{
"presets": ["@babel/preset-react", "@babel/preset-env"],
"presets": [
"@babel/preset-react",
"@babel/preset-env",
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties"

View File

@ -56,6 +56,7 @@
"@babel/plugin-transform-runtime": "^7.15.0",
"@babel/preset-env": "^7.15.6",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.18.6",
"@codeceptjs/configure": "^0.8.0",
"@codeceptjs/examples": "^1.2.1",
"@codeceptjs/ui": "^0.4.6",
@ -77,6 +78,7 @@
"source-map-loader": "^3.0.0",
"style-loader": "3.2.1",
"terser-webpack-plugin": "^5.2.4",
"typescript": "^4.7.4",
"webpack": "5.52.1",
"webpack-cli": "4.10.0",
"webpack-dev-server": "4.3.1"

View File

@ -3,7 +3,5 @@
"Error403Text": "Təəssüf ki, giriş rədd edilmişdir.",
"Error404Text": "Təəssüf ki, resurs tapıla bilmir.",
"ErrorEmptyResponse": "Boş cavab",
"ErrorInvalidHeader": "Yanlış e-poçt ünvanı və ya vaxtı bitmiş keçid",
"ErrorInvalidText": "10 saniyədə <1>giriş səhifəsinə</1> yönləndiriləcəksiniz",
"ErrorOfflineText": "İnternet bağlantısı tapılmadı."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Съжаляваме, достъпът отказан.",
"Error404Text": "Съжаляваме, ресурсът не може да бъде открит.",
"ErrorEmptyResponse": "Празен отговор",
"ErrorInvalidHeader": "Неправилен имейл или изтекла връзка",
"ErrorInvalidText": "След 10 секунди ще бъдете пренасочени към <1>страницата за вход</1>",
"ErrorOfflineText": "Не е открита връзка с интернет."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Omlouváme se, přístup odepřen.",
"Error404Text": "Omlouváme se, zdroj nelze najít.",
"ErrorEmptyResponse": "Prázdná reakce",
"ErrorInvalidHeader": "Nesprávný e-mail nebo neplatný odkaz",
"ErrorInvalidText": "Za 10 sekund budete přesměrováni na <1>přihlašovací stránku</1>",
"ErrorOfflineText": "Nebylo nalezeno připojení k internetu."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Zugriff verweigert.",
"Error404Text": "Die Ressource kann nicht gefunden werden.",
"ErrorEmptyResponse": "Leere Antwort",
"ErrorInvalidHeader": "Inkorrekte E-Mail oder ungültiger Link",
"ErrorInvalidText": "In 10 Sekunden werden Sie auf die <1>Anmeldeseite</1> weitergeleitet",
"ErrorOfflineText": "Keine Internetverbindung gefunden"
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Δυστυχώς, η πρόσβαση απορρίφθηκε.",
"Error404Text": "Δυστυχώς, ο πόρος δεν μπορεί να βρεθεί.",
"ErrorEmptyResponse": "Κενή απάντηση",
"ErrorInvalidHeader": "Λανθασμένο email ή ληγμένος σύνδεσμος",
"ErrorInvalidText": "Σε 10 δευτερόλεπτα θα ανακατευθυνθείτε στη <1> σελίδα σύνδεσης</1>",
"ErrorOfflineText": "Δεν βρέθηκε σύνδεση στο διαδίκτυο."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Sorry, access denied.",
"Error404Text": "Sorry, the resource cannot be found.",
"ErrorEmptyResponse": "Empty response",
"ErrorInvalidHeader": "Incorrect email or expired link",
"ErrorInvalidText": "In 10 seconds you will be redirected to the <1>login page</1>",
"ErrorOfflineText": "No internet connection found."
}

View File

@ -70,6 +70,10 @@
"DataBackup": "Data backup",
"DeactivateOrDeletePortal": "Deactivate or delete portal.",
"Disabled": "Disabled",
"DNSSettings": "DNS Settings",
"DNSSettingsDescription": "DNS Settings is a way to set an alternative URL for your portal.",
"DNSSettingsMobile": "Send your request to our support team, and our specialists will help you with the settings.",
"DNSSettingsTooltip": "DNS Settings allow you to set an alternative URL address for your ONLYOFFICE portal. Send your request to our support team, and our specialists will help you with the settings.<2>{{learnMore}}</2>",
"DocumentsAdministratorsCan": "Documents administrators can link Dropbox, Box, and other accounts to Common Documents and set up access rights in this section",
"DownloadCopy": "Download the copy",
"DownloadReportBtn": "Download and open report",
@ -202,5 +206,6 @@
"UserAgreement": "I confirm and want to proceed",
"Users": "Users",
"WhiteLabel": "White label",
"YouHaveUnsavedChanges": "You have unsaved changes"
"YouHaveUnsavedChanges": "You have unsaved changes",
"YourCurrentDomain": "Your current domain"
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Perdón, acceso denegado.",
"Error404Text": "Perdón, no se puede encontrar el recurso.",
"ErrorEmptyResponse": "Respuesta vacía",
"ErrorInvalidHeader": "Correo electrónico incorrecto o enlace expirado",
"ErrorInvalidText": "Dentro de 10 segundos se le redirigirá a la página de <1>inicio de sesión</1>",
"ErrorOfflineText": "No se ha encontrado ninguna conexión a Internet."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Valitettavasti pääsy on estetty.",
"Error404Text": "Valitettavasti resurssia ei löydy.",
"ErrorEmptyResponse": "Tyhjä vastaus",
"ErrorInvalidHeader": "Väärä sähköposti tai vanhentunut linkki",
"ErrorInvalidText": "10 sekunnin kuluttua sinut ohjataan <1>kirjautumissivulle</1>",
"ErrorOfflineText": "Internet-yhteyttä ei löydy."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Désolé, accès refusé.",
"Error404Text": "Désolé, la ressource n'a pu être trouvée.",
"ErrorEmptyResponse": "Réponse vide",
"ErrorInvalidHeader": "Adresse e-mail incorrecte ou lien expiré",
"ErrorInvalidText": "En 10 secondes, vous serez redirigé vers <1>login page</1>",
"ErrorOfflineText": "Aucune connexion Internet trouvée."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Ներողություն, մատչումն արգելված է.",
"Error404Text": "Ներողություն, ռեսուրսը հնարավոր չէ գտնել:",
"ErrorEmptyResponse": "Դատարկ պատասխան",
"ErrorInvalidHeader": "Սխալ էլփոստ կամ ժամկետանց հղում",
"ErrorInvalidText": "10 վայրկյանից Դուք կվերուղղորդվեք դեպի <1>մուտքի էջ</1>",
"ErrorOfflineText": "Ինտերնետ կապ չի գտնվել."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Spiacente, accesso negato.",
"Error404Text": "Spiacente, impossibile trovare la risorsa.",
"ErrorEmptyResponse": "Risposta vuota",
"ErrorInvalidHeader": "Email errata o link scaduto",
"ErrorInvalidText": "Tra 10 secondi sarai reindirizzato alla <1>pagina di login</1>",
"ErrorOfflineText": "Nessuna connessione a internet trovata"
}

View File

@ -3,7 +3,5 @@
"Error403Text": "申し訳ありませんが、アクセスが拒否されました。",
"Error404Text": "申し訳ありませんが、リソースが見つかりません。",
"ErrorEmptyResponse": "反応なし",
"ErrorInvalidHeader": "メールアドレスが正しくないかリンクの有効期限が切れています",
"ErrorInvalidText": "10秒後、<1>ログインページ</1>にリダイレクトされます。",
"ErrorOfflineText": "インターネットに接続されていません。"
}

View File

@ -3,7 +3,5 @@
"Error403Text": "죄송하지만, 액세스가 거부되었습니다.",
"Error404Text": "죄송하지만, 해당 리소스를 찾을 수 없습니다.",
"ErrorEmptyResponse": "응답이 없습니다",
"ErrorInvalidHeader": "정확하지 않은 이메일 또는 만료된 링크입니다",
"ErrorInvalidText": "10초 내에 <1>로그인 페이지</1>로 리디렉션됩니다",
"ErrorOfflineText": "인터넷 연결을 찾을 수 없습니다."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "ຂໍ້ອະໄພ.ການເຂົ້າເຖິງຖືກປະຕິເສດ",
"Error404Text": "ຂໍອະໄພ, ບໍ່ສາມາດເຂົ້າເຖິງຊັບພະຍາກອນໄດ້",
"ErrorEmptyResponse": "ການຕອບສະຫນອງທີ່ວ່າງເປົ່າ",
"ErrorInvalidHeader": "ອີເມລ໌ບໍ່ຖືກຕ້ອງ ຫຼືລິ້ງໝົດອາຍຸ",
"ErrorInvalidText": "ໃນ 10 ວິນາທີທ່ານຈະຖືກໂອນໄປຫາ <1>ໜ້າເຂົ້າສູ່ລະບົບ</1>",
"ErrorOfflineText": "ບໍ່ພົບການເຊື່ອມຕໍ່ອິນເຕີເນັດ."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Diemžēl piekļuve liegta",
"Error404Text": "Diemžēl resursu nevar atrast.",
"ErrorEmptyResponse": "Tukša atbilde",
"ErrorInvalidHeader": "Nepareizs e-pasts vai saite, kurai beidzies derīguma termiņš",
"ErrorInvalidText": "Pēc 10 sekundēm jūs tiksiet novirzīts uz <1>pieteikšanās lapu</1>",
"ErrorOfflineText": "Interneta savienojums nav atrasts."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Sorry, toegang geweigerd.",
"Error404Text": "Sorry, de bron kan niet worden gevonden.",
"ErrorEmptyResponse": "Lege reactie",
"ErrorInvalidHeader": "Onjuiste e-mail of verlopen link",
"ErrorInvalidText": "Over 10 seconden wordt u doorverwezen naar de <1>login pagina</1>",
"ErrorOfflineText": "Geen internetverbinding gevonden."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Przepraszamy, odmówiono dostępu.",
"Error404Text": "Przepraszamy, nie znaleziono zasobu.",
"ErrorEmptyResponse": "Pusta odpowiedź",
"ErrorInvalidHeader": "Nieprawidłowy adres e-mail lub nieaktualny link",
"ErrorInvalidText": "Za 10 sekund nastąpi przekierowanie na <1>stronę logowania</1>",
"ErrorOfflineText": "Brak połączenia z Internetem."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Desculpe, acesso negado.",
"Error404Text": "Desculpe, o recurso não pode ser encontrado.",
"ErrorEmptyResponse": "Resposta vazia",
"ErrorInvalidHeader": "E-mail incorreto ou link expirado",
"ErrorInvalidText": "Em 10 segundos, você será redirecionado para a <1>página de login</1>",
"ErrorOfflineText": "Nenhuma conexão com a Internet foi encontrada."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Desculpe, acesso negado.",
"Error404Text": "Desculpe, o recurso não foi encontrado.",
"ErrorEmptyResponse": "Resposta vazia",
"ErrorInvalidHeader": "E-mail incorreto ou link expirado",
"ErrorInvalidText": "Em 10 segundos será redirecionado para a <1>página de login</1>",
"ErrorOfflineText": "Não foi encontrada qualquer conexão à internet."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Ne pare rău, accesul este refuzat.",
"Error404Text": "Ne pare rău, sursa nu s-a găsit.",
"ErrorEmptyResponse": "Răspunsul necompletat",
"ErrorInvalidHeader": "Adresa e-mail invalidă sau link-ul expirat",
"ErrorInvalidText": "Veţi fi redirecționat în 10 secunde către <1>pagina de autentificare</1>",
"ErrorOfflineText": "Nu există nicio conexiune la Internet."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Извините, доступ закрыт.",
"Error404Text": "Извините, страница не найдена.",
"ErrorEmptyResponse": "Пустой ответ",
"ErrorInvalidHeader": "Неправильный email или истек срок действия ссылки",
"ErrorInvalidText": "Через 10 секунд вы будете перенаправлены на <1>страницу авторизации</1>",
"ErrorOfflineText": "Нет подключения к интернету."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Prepáčte, prístup odmietnutý.",
"Error404Text": "Prepáčte, zdroj sa nedá nájsť.",
"ErrorEmptyResponse": "Prázdna odpoveď",
"ErrorInvalidHeader": "Nesprávny e-mail alebo platnosť odkazu vypršala",
"ErrorInvalidText": "O 10 sekúnd budete presmerovaní na <1>prihlasovaciu stránku</1>",
"ErrorOfflineText": "Nenašlo sa žiadne internetové pripojenie."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Žal je dostop zavrnjen.",
"Error404Text": "Žal vira ni mogoče najti.",
"ErrorEmptyResponse": "Prazen odziv",
"ErrorInvalidHeader": "Napačen email ali potekla povezava",
"ErrorInvalidText": "V 10 sekundah boste preusmerjeni na <1>Stran za prijavo</1>",
"ErrorOfflineText": "Internetne povezave ni bilo mogoče najti."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "Üzgünüz, erişim reddedildi.",
"Error404Text": "Üzgünüz, kaynak bulunamadı.",
"ErrorEmptyResponse": "Boş yanıt",
"ErrorInvalidHeader": "Yanlış e-posta veya süresi dolmuş bağlantı",
"ErrorInvalidText": "10 saniye içinde <1>giriş sayfasına</1> yönlendirileceksiniz",
"ErrorOfflineText": "İnternet bağlantısı bulunamadı."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "На жаль, доступ заборонено.",
"Error404Text": "На жаль, ресурс неможливо знайти.",
"ErrorEmptyResponse": "Пуста відповідь",
"ErrorInvalidHeader": "Неправильна адреса електронної пошти або прострочене посилання",
"ErrorInvalidText": "Через 10 секунд ви будете перенаправлені на <1>сторінку входу</1>",
"ErrorOfflineText": "Підключення до Інтернету не знайдено."
}

View File

@ -3,7 +3,5 @@
"Error403Text": " Xin lỗi, truy cập bị từ chối.",
"Error404Text": " Xin lỗi, không thể tìm thấy tài nguyên.",
"ErrorEmptyResponse": "Không có hồi đáp",
"ErrorInvalidHeader": "Email không chính xác hoặc liên kết hết hạn",
"ErrorInvalidText": "Trong 10 giây, bạn sẽ được chuyển hướng đến <1>trang đăng nhập</1>",
"ErrorOfflineText": "Không tìm thấy kết nối internet."
}

View File

@ -3,7 +3,5 @@
"Error403Text": "对不起,拒绝访问。",
"Error404Text": "对不起,找不到资源。",
"ErrorEmptyResponse": "空响应",
"ErrorInvalidHeader": "电子邮件不正确或链接已过期",
"ErrorInvalidText": "在10秒钟内您将重定向到<1>登录页面</1>",
"ErrorOfflineText": "未找到网络连接。"
}

View File

@ -15,6 +15,7 @@ import config from "PACKAGE_FILE";
import { getTitleWithoutExst } from "../helpers/files-helpers";
//import { getDefaultFileName } from "@docspace/client/src/helpers/filesUtils";
//import ItemIcon from "../components/ItemIcon";
import { getCookie } from "@docspace/common/utils";
export default function withContent(WrappedContent) {
class WithContent extends React.Component {
@ -38,7 +39,7 @@ export default function withContent(WrappedContent) {
const { culture, item, personal } = this.props;
const { created, updated } = item;
const locale = personal ? localStorage.getItem(LANGUAGE) : culture;
const locale = personal ? getCookie(LANGUAGE) : culture;
const date = create ? created : updated;

View File

@ -11,6 +11,7 @@ const withLoading = (WrappedComponent) => {
isLoadedSectionHeader,
isLoadedSubmenu,
isLoadedLngTZSettings,
isLoadedDNSSettings,
isLoadedPortalRenaming,
isLoadedCustomization,
isLoadedCustomizationNavbar,
@ -27,6 +28,7 @@ const withLoading = (WrappedComponent) => {
isLoadedCustomization &&
isLoadedLngTZSettings &&
isLoadedWelcomePageSettings &&
isLoadedDNSSettings &&
isLoadedPortalRenaming &&
isLoadedArticleBody &&
isLoadedArticleHeader &&
@ -58,11 +60,19 @@ const withLoading = (WrappedComponent) => {
isLoadedSectionHeader &&
isLoadedPortalRenaming;
const isLoadedCustomizationSettingDNSSettings =
isLoadedArticleBody &&
isLoadedArticleHeader &&
isLoadedSectionHeader &&
isLoadedDNSSettings;
const isLoadedPage =
setting === "language-and-time-zone"
? isLoadedCustomizationSettingLngTZSettings
: setting === "welcome-page-settings"
? isLoadedCustomizationSettingWelcomePageSettings
: setting === "dns-settings"
? isLoadedCustomizationSettingDNSSettings
: setting === "portal-renaming"
? isLoadedCustomizationSettingPortalRenaming
: viewMobile
@ -79,6 +89,7 @@ const withLoading = (WrappedComponent) => {
isLoadedSectionHeader,
isLoadedSubmenu,
isLoadedLngTZSettings,
isLoadedDNSSettings,
isLoadedPortalRenaming,
isLoadedCustomization,
isLoadedCustomizationNavbar,
@ -91,6 +102,7 @@ const withLoading = (WrappedComponent) => {
isLoadedSectionHeader,
isLoadedSubmenu,
isLoadedLngTZSettings,
isLoadedDNSSettings,
isLoadedPortalRenaming,
isLoadedCustomization,
isLoadedCustomizationNavbar,

View File

@ -41,10 +41,6 @@ import DialogsWrapper from "./components/dialogs/DialogsWrapper";
// ];
// const WIZARD_URL = combineUrl(PROXY_HOMEPAGE_URL, "/wizard");
// const ABOUT_URL = combineUrl(PROXY_HOMEPAGE_URL, "/about");
// const LOGIN_URLS = [
// combineUrl(PROXY_HOMEPAGE_URL, "/login"),
// combineUrl(PROXY_HOMEPAGE_URL, "/login/confirmed-email=:confirmedEmail"),
// ];
// const CONFIRM_URL = combineUrl(PROXY_HOMEPAGE_URL, "/confirm");
// const PAYMENTS_URL = combineUrl(PROXY_HOMEPAGE_URL, "/payments");
@ -52,7 +48,6 @@ import DialogsWrapper from "./components/dialogs/DialogsWrapper";
// const ERROR_401_URL = combineUrl(PROXY_HOMEPAGE_URL, "/error401");
// const PROFILE_MY_URL = combineUrl(PROXY_HOMEPAGE_URL, "/my");
// const ENTER_CODE_URL = combineUrl(PROXY_HOMEPAGE_URL, "/code");
// const INVALID_URL = combineUrl(PROXY_HOMEPAGE_URL, "/login/error=:error");
// const PREPARATION_PORTAL = combineUrl(
// PROXY_HOMEPAGE_URL,
// "/preparation-portal"
@ -69,8 +64,6 @@ const PortalSettings = React.lazy(() => import("./pages/PortalSettings"));
const Confirm = !IS_PERSONAL && React.lazy(() => import("./pages/Confirm"));
// const MyProfile = React.lazy(() => import("./pages/My"));
const EnterCode = !IS_PERSONAL && React.lazy(() => import("login/codeLogin"));
const InvalidError = React.lazy(() => import("./pages/Errors/Invalid"));
const PreparationPortal = React.lazy(() => import("./pages/PreparationPortal"));
const FormGallery = React.lazy(() => import("./pages/FormGallery"));
@ -155,24 +148,6 @@ const WizardRoute = (props) => (
// </React.Suspense>
// );
const EnterCodeRoute =
!IS_PERSONAL &&
((props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
<EnterCode {...props} />
</ErrorBoundary>
</React.Suspense>
));
const InvalidRoute = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
<InvalidError {...props} />
</ErrorBoundary>
</React.Suspense>
);
const FormGalleryRoute = (props) => (
<React.Suspense fallback={<AppLoader />}>
<ErrorBoundary>
@ -416,38 +391,6 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
const pathname = window.location.pathname.toLowerCase();
const isEditor = pathname.indexOf("doceditor") !== -1;
const loginRoutes = [];
if (isLoaded && !IS_PERSONAL) {
let module;
if (roomsMode) {
module = "./roomsLogin";
} else {
module = "./login";
}
const loginSystem = {
url: combineUrl(AppServerConfig.proxyURL, "/login/remoteEntry.js"),
scope: "login",
module: module,
};
loginRoutes.push(
<PublicRoute
key={loginSystem.scope}
exact
path={["/login", "/login/confirmed-email=:confirmedEmail"]}
component={System}
system={loginSystem}
/>
);
}
const roomsRoutes = [];
if (!IS_PERSONAL && roomsMode) {
roomsRoutes.push();
}
const currentTheme = isBase ? "Base" : "Dark";
const systemTheme = useThemeDetector();
useEffect(() => {
@ -508,18 +451,13 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
]}
component={FilesRoute}
/>
<PrivateRoute
path={"/form-gallery/:folderId"}
component={FormGalleryRoute}
/>
<PublicRoute exact path={"/wizard"} component={WizardRoute} />
<PrivateRoute path={"/about"} component={AboutRoute} />
{loginRoutes}
<Route path={"/code"} component={EnterCodeRoute} />
<Route path={"/confirm"} component={ConfirmRoute} />
<Route path={"/login/error=:error"} component={InvalidRoute} />
<PrivateRoute path={"/payments"} component={PaymentsRoute} />
<PrivateRoute
restricted

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
import CampaignsBanner from "@docspace/components/campaigns-banner";
import { ADS_TIMEOUT } from "@docspace/client/src/helpers/filesConstants";
import { LANGUAGE } from "@docspace/common/constants";
import { getLanguage } from "@docspace/common/utils";
import { getLanguage, getCookie } from "@docspace/common/utils";
const Banner = () => {
const [campaignImage, setCampaignImage] = useState();
@ -12,7 +12,7 @@ const Banner = () => {
.split(",")
.filter((campaign) => campaign.length > 0);
const lng = localStorage.getItem(LANGUAGE) || "en";
const lng = getCookie(LANGUAGE) || "en";
const language = getLanguage(lng instanceof Array ? lng[0] : lng);
const getImage = async (campaign) => {

View File

@ -6,7 +6,7 @@ import { isMobile } from "@docspace/components/utils/device";
import { isMobileOnly } from "react-device-detect";
import { inject, observer } from "mobx-react";
import { withRouter } from "react-router";
import { combineUrl } from "@docspace/common/utils";
import { combineUrl, getOAuthToken } from "@docspace/common/utils";
import { AppServerConfig } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import withLoader from "../../../HOCs/withLoader";
@ -109,7 +109,6 @@ const PureThirdPartyListContainer = ({
setConnectDialogVisible,
setSelectedNode,
setSelectedFolder,
getOAuthToken,
openConnectWindow,
setThirdPartyDialogVisible,
history,
@ -280,7 +279,7 @@ export default inject(
openConnectWindow,
} = settingsStore.thirdPartyStore;
const { getOAuthToken, toggleArticleOpen } = auth.settingsStore;
const { toggleArticleOpen } = auth.settingsStore;
const {
setConnectItem,
@ -300,7 +299,6 @@ export default inject(
setSelectedNode,
setConnectItem,
setConnectDialogVisible,
getOAuthToken,
openConnectWindow,
setThirdPartyDialogVisible,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",

View File

@ -9,6 +9,7 @@ import FieldContainer from "@docspace/components/field-container";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { runInAction } from "mobx";
import { getOAuthToken } from "@docspace/common/utils";
import { saveSettingsThirdParty } from "@docspace/common/api/files";
const PureConnectDialogContainer = (props) => {
@ -24,7 +25,6 @@ const PureConnectDialogContainer = (props) => {
providers,
selectedFolderId,
selectedFolderFolders,
getOAuthToken,
saveThirdParty,
openConnectWindow,
setConnectDialogVisible,
@ -396,11 +396,7 @@ export default inject(
openConnectWindow,
fetchThirdPartyProviders,
} = settingsStore.thirdPartyStore;
const {
getOAuthToken,
personal,
folderFormValidation,
} = auth.settingsStore;
const { personal, folderFormValidation } = auth.settingsStore;
const {
treeFolders,
@ -432,7 +428,6 @@ export default inject(
setSaveThirdpartyResponse,
folderFormValidation,
getOAuthToken,
getSubfolders,
saveThirdParty,
openConnectWindow,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -16,6 +16,7 @@ import Button from "@docspace/components/button";
import SelectorAddButton from "@docspace/components/selector-add-button";
import { isMobile } from "react-device-detect";
import { mobile } from "@docspace/components/utils/device";
import { getOAuthToken } from "@docspace/common/utils";
const StyledModalDialog = styled(ModalDialog)`
.modal-dialog-aside-body {
@ -180,7 +181,6 @@ const ThirdPartyDialog = (props) => {
visible,
setThirdPartyDialogVisible,
openConnectWindow,
getOAuthToken,
setConnectDialogVisible,
setConnectItem,
getThirdPartyIcon,
@ -381,7 +381,7 @@ export default inject(({ auth, settingsStore, dialogsStore }) => {
setConnectDialogVisible,
setConnectItem,
} = dialogsStore;
const { getOAuthToken, theme } = auth.settingsStore;
const { theme } = auth.settingsStore;
return {
theme: theme,
@ -401,7 +401,6 @@ export default inject(({ auth, settingsStore, dialogsStore }) => {
setConnectDialogVisible,
setConnectItem,
setThirdPartyDialogVisible,
getOAuthToken,
openConnectWindow,
getThirdPartyIcon,
};

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,11 +3,11 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import config from "PACKAGE_FILE";
import { LANGUAGE } from "@docspace/common/constants";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
const lng = localStorage.getItem(LANGUAGE) || "en";
const lng = getCookie(LANGUAGE) || "en";
newInstance
.use(Backend)

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -22,14 +22,14 @@ class ActivateEmail extends React.PureComponent {
tryRedirectTo(
combineUrl(
AppServerConfig.proxyURL,
`/login/confirmed-email=${email}`
`/login?confirmedEmail=${email}`
)
);
})
.catch((e) => {
// console.log('activate email error', e);
tryRedirectTo(
combineUrl(AppServerConfig.proxyURL, `/login/error=${e}`)
combineUrl(AppServerConfig.proxyURL, `/login/error?message=${e}`)
);
})
);

View File

@ -23,6 +23,8 @@ import Section from "@docspace/common/components/Section";
import {
createPasswordHash,
getProviderTranslation,
getOAuthToken,
getLoginLink,
} from "@docspace/common/utils";
import { providersData } from "@docspace/common/constants";
import withLoader from "../withLoader";
@ -442,8 +444,6 @@ const Confirm = (props) => {
const providerName = e.target.dataset.providername;
const url = e.target.dataset.url;
const { getOAuthToken, getLoginLink } = props;
try {
const tokenGetterWin = isDesktop
? (window.location.href = url)
@ -816,8 +816,6 @@ export default inject(({ auth }) => {
defaultPage,
getSettings,
getPortalPasswordSettings,
getOAuthToken,
getLoginLink,
} = settingsStore;
return {
@ -831,8 +829,6 @@ export default inject(({ auth }) => {
getSettings,
getPortalPasswordSettings,
thirdPartyLogin,
getOAuthToken,
getLoginLink,
setProviders,
providers,
};

View File

@ -34,7 +34,10 @@ export default function withLoader(WrappedComponent) {
.catch((error) => {
console.error(error);
history.push(
combineUrl(AppServerConfig.proxyURL, `/login/error=${error}`)
combineUrl(
AppServerConfig.proxyURL,
`/login/error?message=${error}`
)
);
});
}

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -1,36 +0,0 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
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, "Errors"),
},
react: {
useSuspense: false,
},
});
export default newInstance;

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -11,12 +11,13 @@ import {
StyledTitle,
} from "./styles/styles.js";
import getCorrectDate from "@docspace/components/utils/getCorrectDate";
import { getCookie } from "@docspace/common/utils/index";
const SingleItem = (props) => {
const { t, selectedItem, getIcon, culture, personal } = props;
const parseAndFormatDate = (date) => {
const locale = personal ? localStorage.getItem(LANGUAGE) : culture;
const locale = personal ? getCookie(LANGUAGE) : culture;
const correctDate = getCorrectDate(locale, date);

View File

@ -14,6 +14,7 @@ import {
StyledTitle,
} from "./styles/styles.js";
import getCorrectDate from "@docspace/components/utils/getCorrectDate";
import { getCookie } from "@docspace/common/utils/index";
const SingleItem = (props) => {
const {
@ -83,7 +84,7 @@ const SingleItem = (props) => {
};
const parseAndFormatDate = (date) => {
const locale = personal ? localStorage.getItem(LANGUAGE) : culture;
const locale = personal ? getCookie(LANGUAGE) : culture;
const correctDate = getCorrectDate(locale, date);
return correctDate;
};

View File

@ -123,6 +123,37 @@ const CustomizationNavbar = ({
{t("CustomTitlesSettingsDescription")}
</Text>
</div>
<div className="category-item-wrapper">
<div className="category-item-heading">
<Link
truncate={true}
className="inherit-title-link header"
onClick={onClickLink}
href={combineUrl(
AppServerConfig.proxyURL,
"/portal-settings/common/customization/dns-settings"
)}
>
{t("DNSSettings")}
</Link>
<StyledArrowRightIcon size="small" color="#333333" />
</div>
<Text className="category-item-description">
{t("DNSSettingsDescription")}
</Text>
<Box paddingProp="10px 0 3px 0">
<Link
color={theme.client.settings.common.linkColorHelp}
target="_blank"
isHovered={true}
href={helpUrlCommonSettings}
>
{t("Common:LearnMore")}
</Link>
</Box>
</div>
<div className="category-item-wrapper">
<div className="category-item-heading">
<Link

View File

@ -6,6 +6,7 @@ import withCultureNames from "@docspace/common/hoc/withCultureNames";
import LanguageAndTimeZone from "./settingsCustomization/language-and-time-zone";
import WelcomePageSettings from "./settingsCustomization/welcome-page-settings";
import PortalRenaming from "./settingsCustomization/portal-renaming";
import DNSSettings from "./settingsCustomization/dns-settings";
import { isSmallTablet } from "@docspace/components/utils/device";
import CustomizationNavbar from "./customization-navbar";
import { Base } from "@docspace/components/themes";
@ -110,6 +111,7 @@ const Customization = (props) => {
)}
<LanguageAndTimeZone isMobileView={isMobile} />
<WelcomePageSettings isMobileView={isMobile} />
<DNSSettings isMobileView={isMobile} />
<PortalRenaming isMobileView={isMobile} />
</StyledComponent>
);

View File

@ -54,6 +54,10 @@ const StyledSettingsComponent = styled.div`
padding-bottom: 12px;
}
.send-request-button {
height: 40px;
}
@media (max-width: 599px) {
${(props) =>
props.hasScroll &&
@ -68,10 +72,19 @@ const StyledSettingsComponent = styled.div`
padding-left: 16px;
}
`}
.send-request-container {
box-sizing: border-box;
position: absolute;
bottom: 0;
left: 0;
padding: 16px;
width: 100%;
}
.settings-block {
margin-top: 8px;
.send-request-button {
width: 100%;
}
}
@media (min-width: 600px) {
@ -86,6 +99,12 @@ const StyledSettingsComponent = styled.div`
}
}
@media (min-width: 1024px) {
.send-request-button {
height: 32px;
}
}
@media (orientation: landscape) and (max-width: 600px) {
${isMobileOnly &&
css`

View File

@ -0,0 +1,151 @@
import React, { useState, useEffect, useCallback } from "react";
import { withTranslation } from "react-i18next";
import HelpButton from "@docspace/components/help-button";
import FieldContainer from "@docspace/components/field-container";
import TextInput from "@docspace/components/text-input";
import Button from "@docspace/components/button";
import { inject, observer } from "mobx-react";
import { combineUrl } from "@docspace/common/utils";
import { AppServerConfig } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
import { isMobileOnly } from "react-device-detect";
import { isSmallTablet } from "@docspace/components/utils/device";
import checkScrollSettingsBlock from "../utils";
import { DNSSettingsTooltip } from "../sub-components/common-tooltips";
import { StyledSettingsComponent, StyledScrollbar } from "./StyledSettings";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import LoaderCustomization from "../sub-components/loaderCustomization";
import withLoading from "SRC_DIR/HOCs/withLoading";
const DNSSettings = (props) => {
const {
t,
isMobileView,
tReady,
isLoaded,
setIsLoadedDNSSettings,
isLoadedPage,
helpLink,
theme,
} = props;
const [hasScroll, setHasScroll] = useState(false);
const isLoadedSetting = isLoaded && tReady;
const [isCustomizationView, setIsCustomizationView] = useState(false);
useEffect(() => {
setDocumentTitle(t("DNSSettings"));
const checkScroll = checkScrollSettingsBlock();
checkInnerWidth();
window.addEventListener("resize", checkInnerWidth);
const scrollPortalName = checkScroll();
if (scrollPortalName !== hasScroll) {
setHasScroll(scrollPortalName);
}
// TODO: Remove div with height 64 and remove settings-mobile class
const settingsMobile = document.getElementsByClassName(
"settings-mobile"
)[0];
if (settingsMobile) {
settingsMobile.style.display = "none";
}
return () => window.removeEventListener("resize", checkInnerWidth);
}, []);
useEffect(() => {
if (isLoadedSetting) setIsLoadedDNSSettings(isLoadedSetting);
}, [isLoadedSetting]);
const onSendRequest = () => {
window.open("https://helpdesk.onlyoffice.com/hc/en-us/requests/new");
};
const checkInnerWidth = useCallback(() => {
if (!isSmallTablet()) {
setIsCustomizationView(true);
history.push(
combineUrl(
AppServerConfig.proxyURL,
config.homepage,
"/portal-settings/common/customization"
)
);
} else {
setIsCustomizationView(false);
}
}, [isSmallTablet, setIsCustomizationView]);
const tooltipDNSSettingsTooltip = (
<DNSSettingsTooltip t={t} theme={theme} helpLink={helpLink} />
);
const settingsBlock = (
<div className="settings-block">
<div className="settings-block-description">{t("DNSSettingsMobile")}</div>
<FieldContainer
id="fieldContainerDNSSettings"
className="field-container-width"
labelText={`${t("YourCurrentDomain")}`}
isVertical={true}
>
<TextInput
id="textInputContainerDNSSettings"
scale={true}
value={location.hostname}
isDisabled={true}
/>
</FieldContainer>
</div>
);
return !isLoadedPage ? (
<LoaderCustomization dnsSettings={true} />
) : (
<StyledSettingsComponent
hasScroll={hasScroll}
className="category-item-wrapper"
>
{isCustomizationView && !isMobileView && (
<div className="category-item-heading">
<div className="category-item-title">{t("DNSSettings")}</div>
<HelpButton
iconName="static/images/combined.shape.svg"
size={12}
tooltipContent={tooltipDNSSettingsTooltip}
/>
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (
<StyledScrollbar stype="mediumBlack">{settingsBlock}</StyledScrollbar>
) : (
<> {settingsBlock}</>
)}
<div className="send-request-container">
<Button
label={t("Common:SendRequest")}
className="save-cancel-buttons send-request-button"
onClick={onSendRequest}
primary
size="small"
/>
</div>
</StyledSettingsComponent>
);
};
export default inject(({ auth, common }) => {
const { theme, helpLink } = auth.settingsStore;
const { isLoaded, setIsLoadedDNSSettings } = common;
return {
theme,
isLoaded,
setIsLoadedDNSSettings,
helpLink,
};
})(withLoading(withTranslation(["Settings", "Common"])(observer(DNSSettings))));

View File

@ -8,9 +8,9 @@ import SaveCancelButtons from "@docspace/components/save-cancel-buttons";
import { saveToSessionStorage, getFromSessionStorage } from "../../../utils";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import { inject, observer } from "mobx-react";
import { LANGUAGE } from "@docspace/common/constants";
import { LANGUAGE, COOKIE_EXPIRATION_YEAR } from "@docspace/common/constants";
import { LanguageTimeSettingsTooltip } from "../sub-components/common-tooltips";
import { combineUrl } from "@docspace/common/utils";
import { combineUrl, setCookie } from "@docspace/common/utils";
import { AppServerConfig } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import history from "@docspace/common/history";
@ -297,7 +297,9 @@ class LanguageAndTimeZone extends React.Component {
.then(
() =>
!user.cultureName &&
localStorage.setItem(LANGUAGE, language.key || "en")
setCookie(LANGUAGE, language.key || "en", {
"max-age": COOKIE_EXPIRATION_YEAR,
})
)
.then(() => toastr.success(t("SuccessfullySaveSettingsMessage")))
.then(
@ -422,7 +424,7 @@ class LanguageAndTimeZone extends React.Component {
<div className="settings-block">
<FieldContainer
id="fieldContainerLanguage"
labelText={`${t("Common:Language")}:`}
labelText={`${t("Common:Language")}`}
isVertical={true}
>
<ComboBox
@ -440,7 +442,7 @@ class LanguageAndTimeZone extends React.Component {
</FieldContainer>
<FieldContainer
id="fieldContainerTimezone"
labelText={`${t("TimeZone")}:`}
labelText={`${t("TimeZone")}`}
isVertical={true}
>
<ComboBox

View File

@ -231,7 +231,7 @@ const PortalRenaming = (props) => {
<FieldContainer
id="fieldContainerPortalRenaming"
className="field-container-width"
labelText={`${t("PortalRenamingLabelText")}:`}
labelText={`${t("PortalRenamingLabelText")}`}
isVertical={true}
>
<TextInput

View File

@ -265,7 +265,7 @@ class WelcomePageSettings extends React.Component {
<FieldContainer
id="fieldContainerWelcomePage"
className="field-container-width"
labelText={`${t("Common:Title")}:`}
labelText={`${t("Common:Title")}`}
isVertical={true}
>
<TextInput

View File

@ -43,6 +43,7 @@ export const LanguageTimeSettingsTooltip = ({ t, theme, helpLink }) => {
color={theme.client.settings.common.linkColorHelp}
className="display-block font-size"
isHovered={true}
target="_blank"
href={`${helpLink}/administration/configuration.aspx#CustomizingPortal_block`}
>
{{ learnMore }}
@ -93,6 +94,35 @@ export const CustomTitlesTooltip = ({ t }) => {
);
};
export const DNSSettingsTooltip = ({ t, theme, helpLink }) => {
const text = t("Settings:DNSSettingsTooltip");
const learnMore = t("Common:LearnMore");
return (
<StyledTooltip>
<div className="font-size">
<Trans
ns="Settings"
i18nKey="DNSSettingsTooltip"
text={text}
learnMore={learnMore}
>
<div className="display-inline font-size"> {{ text }}</div>{" "}
<Link
color={theme.client.settings.common.linkColorHelp}
className="display-block font-size"
isHovered={true}
target="_blank"
href={`${helpLink}/administration/configuration.aspx#CustomizingPortal_block`}
>
{{ learnMore }}
</Link>
</Trans>
</div>
</StyledTooltip>
);
};
export const PortalRenamingTooltip = ({ t }) => {
const text = t("Settings:PortalRenamingDescription");
const pleaseNote = t("Settings:PleaseNote");

View File

@ -1,12 +1,11 @@
import React from "react";
import React, { useState, useEffect } from "react";
import styled, { css } from "styled-components";
import Loaders from "@docspace/common/components/Loaders";
import { isTablet } from "react-device-detect";
const tabletStyles = css`
.header {
display: block;
display: ${(props) => !props.dnsSettings && "block"};
width: ${(props) =>
props.lngTZSettings
? "283px"
@ -26,12 +25,13 @@ const tabletStyles = css`
display: block;
width: ${(props) =>
props.lngTZSettings
? "65px"
? "61px"
: props.welcomePage
? "31px"
? "28px"
: props.portalRenaming
? "113px"
? "109px"
: 0};
padding-bottom: 4px;
}
.combo-box {
@ -47,8 +47,18 @@ const tabletStyles = css`
.save-cancel-buttons {
display: block;
position: static;
width: ${(props) => (props.welcomePage ? "274px" : "197px")};
padding: 8px 0 0;
}
.dns-description {
width: 122px;
padding-bottom: 12px;
}
.dns-field {
width: 350px;
padding: 0;
padding-bottom: 12px;
}
`;
@ -63,20 +73,19 @@ const StyledLoader = styled.div`
}
.title {
width: ${(props) => (props.portalRenaming ? "49px" : "63.7px")};
padding-bottom: 4px;
width: ${(props) => (props.portalRenaming ? "109px" : "61px")};
}
.title-long {
display: block;
width: 68px;
width: 64px;
padding-bottom: 4px;
}
.combo-box {
display: block;
width: 100%;
padding-bottom: 24px;
padding-bottom: 16px;
}
.field-container {
@ -93,6 +102,24 @@ const StyledLoader = styled.div`
padding: 0 0 16px 16px;
}
.flex {
display: flex;
align-items: center;
padding-bottom: 8px;
}
.dns-description {
padding-bottom: 8px;
}
.padding-right {
padding-right: 8px;
}
.dns-field {
height: 32px;
}
@media (min-width: 600px) {
${tabletStyles}
}
@ -101,20 +128,56 @@ const StyledLoader = styled.div`
`
${tabletStyles}
`}
@media (min-width: 1024px) {
.save-cancel-buttons {
width: ${(props) => (props.welcomePage ? "264px" : "192px")};
}
}
`;
const LoaderCustomization = ({
lngTZSettings,
portalRenaming,
welcomePage,
dnsSettings,
}) => {
const heightSaveCancelButtons = window.innerWidth < 600 ? "40px" : "32px";
const [isMobileView, setIsMobileView] = useState(false);
const [isDesktopView, setIsDesktopView] = useState(false);
const checkInnerWidth = () => {
const isMobileView = window.innerWidth < 600;
const isDesktopView = window.innerWidth <= 1024;
if (isMobileView) {
setIsMobileView(true);
} else {
setIsMobileView(false);
}
if (isDesktopView) {
setIsDesktopView(true);
} else {
setIsDesktopView(false);
}
};
useEffect(() => {
checkInnerWidth();
window.addEventListener("resize", checkInnerWidth);
return () => window.removeEventListener("resize", checkInnerWidth);
});
const heightSaveCancelButtons = isDesktopView ? "40px" : "32px";
const heightDnsDescription = isMobileView ? "40px" : "22px";
return (
<StyledLoader
lngTZSettings={lngTZSettings}
portalRenaming={portalRenaming}
welcomePage={welcomePage}
dnsSettings={dnsSettings}
className="category-item-wrapper"
>
<Loaders.Rectangle height="22px" className="header" />
@ -123,8 +186,29 @@ const LoaderCustomization = ({
<Loaders.Rectangle height="80px" className="description" />
)}
{dnsSettings ? (
<>
<Loaders.Rectangle
className="dns-description"
height={heightDnsDescription}
/>
<div className="flex">
<Loaders.Rectangle
height="16px"
width="16px"
className="padding-right"
/>
<Loaders.Rectangle height="20px" width="135px" />
</div>
<Loaders.Rectangle className="dns-field" />
</>
) : (
<>
<Loaders.Rectangle height="20px" className="title" />
<Loaders.Rectangle height="32px" className="combo-box" />
</>
)}
{lngTZSettings && (
<>
<Loaders.Rectangle height="20px" className="title-long" />

View File

@ -3,40 +3,75 @@ import styled from "styled-components";
import Loaders from "@docspace/common/components/Loaders";
const StyledLoader = styled.div`
.section {
padding-bottom: 16px;
}
.title-long {
width: 283px;
padding-bottom: 8px;
padding-bottom: 4px;
}
.width {
width: 100%;
padding-bottom: 8px;
}
.link {
width: 57px;
padding-bottom: 20px;
.padding-bottom {
padding-bottom: 4px;
}
.title {
.padding-top {
padding-top: 5px;
}
.display {
display: block;
width: 132px;
padding-bottom: 8px;
}
`;
const LoaderCustomizationNavbar = () => {
return (
<StyledLoader>
<div className="section">
<Loaders.Rectangle height="22px" className="title-long" />
<Loaders.Rectangle height="100px" className="width" />
<Loaders.Rectangle height="20px" className="link" />
<Loaders.Rectangle height="80px" className="width padding-bottom" />
<Loaders.Rectangle height="20px" width="73px" />
</div>
<Loaders.Rectangle height="22px" className="title" />
<div className="section">
<Loaders.Rectangle
height="22px"
width="201px"
className="title padding-bottom display"
/>
<Loaders.Rectangle height="80px" className="width" />
</div>
<Loaders.Rectangle height="22px" className="title" />
<Loaders.Rectangle height="20px" className="width" />
<div className="section">
<Loaders.Rectangle
height="22px"
width="119px"
className="padding-top"
/>
<Loaders.Rectangle height="40px" className="width" />
<Loaders.Rectangle
height="20px"
width="73px"
className="width padding-top"
/>
</div>
<div className="section">
<Loaders.Rectangle
height="22px"
width="150px"
className="title padding-bottom display"
/>
<Loaders.Rectangle
height="20px"
width="253px"
className="padding-top"
/>
</div>
</StyledLoader>
);
};

View File

@ -5,8 +5,9 @@ import { isTablet } from "react-device-detect";
const tabletStyles = css`
.description {
width: 684px;
padding-bottom: 20px;
width: 100%;
max-width: 700px;
padding-bottom: 16px;
}
`;
@ -19,12 +20,6 @@ const StyledLoader = styled.div`
css`
${tabletStyles}
`}
@media (min-width: 1024px) {
.description {
width: 700px;
}
}
`;
const LoaderDescriptionCustomization = () => {

View File

@ -35,6 +35,11 @@ const LanguageAndTimeZoneSettings = lazy(() =>
const WelcomePageSettings = lazy(() =>
import("./categories/common/settingsCustomization/welcome-page-settings")
);
const DNSSettings = lazy(() =>
import("./categories/common/settingsCustomization/dns-settings")
);
const PortalRenaming = lazy(() =>
import("./categories/common/settingsCustomization/portal-renaming")
);
@ -91,6 +96,12 @@ const WELCOME_PAGE_SETTINGS_URL = combineUrl(
PROXY_BASE_URL,
"/common/customization/welcome-page-settings"
);
const DNS_SETTINGS = combineUrl(
PROXY_BASE_URL,
"/common/customization/dns-settings"
);
const PORTAL_RENAMING = combineUrl(
PROXY_BASE_URL,
"/common/customization/portal-renaming"
@ -170,6 +181,7 @@ const Settings = (props) => {
path={WELCOME_PAGE_SETTINGS_URL}
component={WelcomePageSettings}
/>
<Route exact path={DNS_SETTINGS} component={DNSSettings} />
<Route exact path={PORTAL_RENAMING} component={PortalRenaming} />
<Route exact path={WHITELABEL_URL} component={WhiteLabel} />
<Route exact path={TEAM_TEMPLATE_URL} component={TeamTemplate} />

View File

@ -32,6 +32,12 @@ export const settingsTree = [
{
key: "0-0-2",
icon: "",
link: "dns-settings",
tKey: "DNSSettings",
},
{
key: "0-0-3",
icon: "",
link: "portal-renaming",
tKey: "PortalRenaming",
},

View File

@ -3,7 +3,7 @@ import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/common/constants";
import config from "PACKAGE_FILE";
import { loadLanguagePath } from "@docspace/common/utils";
import { loadLanguagePath, getCookie } from "@docspace/common/utils";
const newInstance = i18n.createInstance();
@ -11,7 +11,7 @@ newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -16,6 +16,7 @@ class CommonStore {
isLoadedSectionHeader = false;
isLoadedSubmenu = false;
isLoadedLngTZSettings = false;
isLoadedDNSSettings = false;
isLoadedPortalRenaming = false;
isLoadedCustomization = false;
isLoadedCustomizationNavbar = false;
@ -111,6 +112,12 @@ class CommonStore {
});
};
setIsLoadedDNSSettings = (isLoadedDNSSettings) => {
runInAction(() => {
this.isLoadedDNSSettings = isLoadedDNSSettings;
});
};
setIsLoadedCustomization = (isLoadedCustomization) => {
runInAction(() => {
this.isLoadedCustomization = isLoadedCustomization;

View File

@ -89,7 +89,7 @@ class ProfileActionsStore {
this.authStore.logout().then(() => {
this.filesStore.reset();
this.peopleStore.reset();
history.push(combineUrl(proxyURL, "/login"));
window.location.replace(combineUrl(proxyURL, "/login"));
});
};

View File

@ -1,6 +1,8 @@
import api from "@docspace/common/api";
import { LANGUAGE } from "@docspace/common/constants";
import { LANGUAGE, COOKIE_EXPIRATION_YEAR } from "@docspace/common/constants";
import { makeAutoObservable } from "mobx";
import { setCookie } from "@docspace/common/utils";
import store from "client/store";
class TargetUserStore {
peopleStore = null;
@ -84,7 +86,9 @@ class TargetUserStore {
this.setTargetUser(res);
//caches.delete("api-cache");
//await this.peopleStore.authStore.settingsStore.init();
localStorage.setItem(LANGUAGE, culture);
setCookie(LANGUAGE, culture, {
"max-age": COOKIE_EXPIRATION_YEAR,
});
};
getUserPhoto = async (id) => {

View File

@ -68,7 +68,7 @@ const config = {
},
},
resolve: {
extensions: [".jsx", ".js", ".json"],
extensions: [".jsx", ".js", ".tsx", ".ts", ".json"],
fallback: {
crypto: false,
},
@ -154,13 +154,17 @@ const config = {
],
},
{
test: /\.(js|jsx)$/,
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-react", "@babel/preset-env"],
presets: [
"@babel/preset-react",
"@babel/preset-env",
"@babel/preset-typescript",
],
plugins: [
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties",

View File

@ -32,8 +32,8 @@ import {
import { ThemeType } from "./constants";
const ColorTheme = forwardRef(
({ currentColorScheme, isVersion, ...props }, ref) => {
switch (props.themeId) {
({ currentColorScheme, isVersion, themeId, ...props }, ref) => {
switch (themeId) {
case ThemeType.Button: {
return (
<ButtonTheme
@ -273,11 +273,15 @@ const ColorTheme = forwardRef(
}
);
export default inject(({ auth }) => {
export default inject(({ auth, loginStore }) => {
if (loginStore) {
const { currentColorScheme } = loginStore;
return { currentColorScheme };
} else {
const { settingsStore } = auth;
const { currentColorScheme } = settingsStore;
return {
currentColorScheme,
};
}
})(observer(ColorTheme));

View File

@ -1,5 +1,5 @@
import styled, { css } from "styled-components";
import { LoginContainer } from "@docspace/login/src/StyledLogin";
import { LoginContainer } from "@docspace/login/src/client/components/StyledLogin";
const getDefaultStyles = ({ $currentColorScheme }) =>
$currentColorScheme &&

View File

@ -5,10 +5,6 @@ import Headline from "../Headline";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
import store from "client/store";
const theme = store.auth.settingsStore.theme;
const ErrorContainer = (props) => {
//console.log("ErrorContainer render");

View File

@ -40,17 +40,19 @@ const PrivateRoute = ({ component: Component, ...rest }) => {
}
console.log("PrivateRoute render Redirect to login", rest);
return (
<Redirect
to={{
pathname: combineUrl(
AppServerConfig.proxyURL,
wizardCompleted ? "/login" : "/wizard"
),
state: { from: props.location },
}}
/>
);
const redirectPath = wizardCompleted ? "/login" : "/wizard";
return window.location.replace(redirectPath);
// return (
// <Redirect
// to={{
// pathname: combineUrl(
// AppServerConfig.proxyURL,
// wizardCompleted ? "/login" : "/wizard"
// ),
// state: { from: props.location },
// }}
// />
// );
}
if (location.pathname === "/" && personal) {

View File

@ -2,13 +2,13 @@ import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "../../constants";
import { loadLanguagePath } from "../../utils";
import { loadLanguagePath, getCookie } from "../../utils";
i18n
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -1,4 +1,5 @@
export const LANGUAGE = "language";
export const LANGUAGE = "asc_language";
export const COOKIE_EXPIRATION_YEAR = 31536000000;
export const ARTICLE_PINNED_KEY = "asc_article_pinned_key";
/**

View File

@ -1,9 +1,12 @@
import toastr from "@docspace/components/toast/toastr";
import isEmpty from "lodash/isEmpty";
import omit from "lodash/omit";
import { checkIsSSR } from "../utils";
const isSSR = checkIsSSR();
export const desktopConstants = Object.freeze({
domain: window.location.origin,
domain: !isSSR && window.location.origin,
provider: "onlyoffice",
cryptoEngineId: "{FFF0E1EB-13DB-4678-B67D-FF0A41DBBCEF}",
});
@ -17,6 +20,7 @@ export function regDesktop(
getEncryptionAccess,
t
) {
if (!isSSR) {
const data = {
displayName: user.displayName,
email: user.email,
@ -85,7 +89,10 @@ export function regDesktop(
}
};
console.log("Created window.cloudCryptoCommand", window.cloudCryptoCommand);
console.log(
"Created window.cloudCryptoCommand",
window.cloudCryptoCommand
);
}
window.onSystemMessage = (e) => {
@ -113,29 +120,41 @@ export function regDesktop(
console.log("Created window.onSystemMessage", window.onSystemMessage);
}
}
export function relogin() {
if (!isSSR)
setTimeout(() => {
const data = {
domain: desktopConstants.domain,
onsuccess: "reload",
};
window.AscDesktopEditor.execCommand("portal:logout", JSON.stringify(data));
window.AscDesktopEditor.execCommand(
"portal:logout",
JSON.stringify(data)
);
}, 1000);
}
export function checkPwd() {
if (!isSSR) {
const data = {
domain: desktopConstants.domain,
emailInput: "login",
pwdInput: "password",
};
window.AscDesktopEditor.execCommand("portal:checkpwd", JSON.stringify(data));
window.AscDesktopEditor.execCommand(
"portal:checkpwd",
JSON.stringify(data)
);
}
}
export function logout() {
if (!isSSR) {
const data = {
domain: desktopConstants.domain,
};
window.AscDesktopEditor.execCommand("portal:logout", JSON.stringify(data));
}
}

View File

@ -6,10 +6,22 @@ import SettingsStore from "./SettingsStore";
import UserStore from "./UserStore";
import TfaStore from "./TfaStore";
import InfoPanelStore from "./InfoPanelStore";
import { logout as logoutDesktop, desktopConstants } from "../desktop";
import { isAdmin } from "../utils";
import { LANGUAGE, TenantStatus } from "../constants";
import {
logout as logoutDesktop,
desktopConstants,
} from "../desktop";
import {
combineUrl,
isAdmin,
setCookie,
getCookie,
} from "../utils";import {
AppServerConfig,
LANGUAGE,
COOKIE_EXPIRATION_YEAR,
TenantStatus,
} from "../constants";
const { proxyURL } = AppServerConfig;
class AuthStore {
userStore = null;
@ -55,10 +67,14 @@ class AuthStore {
};
setLanguage() {
if (this.userStore.user?.cultureName) {
localStorage.getItem(LANGUAGE) !== this.userStore.user.cultureName &&
localStorage.setItem(LANGUAGE, this.userStore.user.cultureName);
getCookie(LANGUAGE) !== this.userStore.user.cultureName &&
setCookie(LANGUAGE, this.userStore.user.cultureName, {
"max-age": COOKIE_EXPIRATION_YEAR,
});
} else {
localStorage.setItem(LANGUAGE, this.settingsStore.culture || "en-US");
setCookie(LANGUAGE, this.settingsStore.culture || "en-US", {
"max-age": COOKIE_EXPIRATION_YEAR,
});
}
}
get isLoaded() {

View File

@ -1,12 +1,16 @@
import { makeAutoObservable } from "mobx";
import api from "../api";
import { LANGUAGE, TenantStatus } from "../constants";
import { combineUrl } from "../utils";
import { combineUrl, setCookie, getCookie } from "../utils";
import FirebaseHelper from "../utils/firebase";
import { AppServerConfig, ThemeKeys } from "../constants";
import {
AppServerConfig,
ThemeKeys,
COOKIE_EXPIRATION_YEAR,
LANGUAGE,
TenantStatus
} from "../constants";
import { version } from "../package.json";
import SocketIOHelper from "../utils/socket";
import { Dark, Base } from "@docspace/components/themes";
import { initPluginStore } from "../../client/src/helpers/plugins";
@ -204,9 +208,11 @@ class SettingsStore {
: newSettings[key]
);
if (key === "culture") {
const language = localStorage.getItem(LANGUAGE);
const language = getCookie(LANGUAGE);
if (!language || language == "undefined") {
localStorage.setItem(LANGUAGE, newSettings[key]);
setCookie(LANGUAGE, newSettings[key], {
"max-age": COOKIE_EXPIRATION_YEAR,
});
}
}
// if (key === "personal") {
@ -321,34 +327,6 @@ class SettingsStore {
this.updateEncryptionKeys(encryptionKeys);
};
getOAuthToken = (tokenGetterWin) => {
return new Promise((resolve, reject) => {
localStorage.removeItem("code");
let interval = null;
interval = setInterval(() => {
try {
const code = localStorage.getItem("code");
if (code) {
localStorage.removeItem("code");
clearInterval(interval);
resolve(code);
} else if (tokenGetterWin && tokenGetterWin.closed) {
clearInterval(interval);
reject();
}
} catch (e) {
clearInterval(interval);
reject(e);
}
}, 500);
});
};
getLoginLink = (token, code) => {
return combineUrl(proxyURL, `/login.ashx?p=${token}&code=${code}`);
};
setModuleInfo = (homepage, productId) => {
if (this.homepage === homepage || this.currentProductId === productId)
return;

View File

@ -7,13 +7,13 @@ import i18n from "i18next";
import { useTranslation, initReactI18next } from "react-i18next";
import Backend from "@docspace/common/utils/i18next-http-backend";
import { LANGUAGE } from "../constants";
import { loadLanguagePath } from "../utils";
import { loadLanguagePath, getCookie } from "../utils";
i18n
.use(Backend)
.use(initReactI18next)
.init({
lng: localStorage.getItem(LANGUAGE) || "en",
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,

View File

@ -1,10 +1,11 @@
import { LANGUAGE } from "../constants";
import { LANGUAGE, AppServerConfig } from "../constants";
import sjcl from "sjcl";
import { isMobile } from "react-device-detect";
import TopLoaderService from "@docspace/components/top-loading-indicator";
import { Encoder } from "./encoder";
import FilesFilter from "../api/files/filter";
const { proxyURL } = AppServerConfig;
export const toUrlParams = (obj, skipNull) => {
let str = "";
for (var key in obj) {
@ -64,10 +65,7 @@ export function getObjectByLocation(location) {
return object;
}
export function changeLanguage(
i18n,
currentLng = localStorage.getItem(LANGUAGE)
) {
export function changeLanguage(i18n, currentLng = getCookie(LANGUAGE)) {
return currentLng
? i18n.language !== currentLng
? i18n.changeLanguage(currentLng)
@ -329,7 +327,6 @@ export function convertLanguage(key) {
return key;
}
import FilesFilter from "../api/files/filter";
export function getFolderOptions(folderId, filter) {
if (folderId && typeof folderId === "string") {
folderId = encodeURIComponent(folderId.replace(/\\\\/g, "\\"));
@ -378,6 +375,41 @@ export function assign(obj, keyPath, value) {
obj[keyPath[lastKeyIndex]] = value;
}
export function getOAuthToken(
tokenGetterWin: Window | string | null
): Promise<string> {
return new Promise((resolve, reject) => {
localStorage.removeItem("code");
let interval: ReturnType<typeof setInterval>;
interval = setInterval(() => {
try {
const code = localStorage.getItem("code");
if (typeof tokenGetterWin !== "string") {
if (code) {
localStorage.removeItem("code");
clearInterval(interval);
resolve(code);
} else if (tokenGetterWin && tokenGetterWin.closed) {
clearInterval(interval);
reject();
}
}
} catch (e) {
clearInterval(interval);
reject(e);
}
}, 500);
});
}
export function getLoginLink(token: string, code: string) {
return combineUrl(proxyURL, `/login.ashx?p=${token}&code=${code}`);
}
export function checkIsSSR() {
return typeof window === "undefined";
}
export const frameCallbackData = (data) => {
window.parent.postMessage(
JSON.stringify({

View File

@ -0,0 +1,48 @@
import api from "../api";
import { setWithCredentialsStatus } from "../api/client";
export async function login(
user: string,
hash: string,
session = true
): Promise<string | object> {
try {
const response = await api.user.login(user, hash, session);
if (!response || (!response.token && !response.tfa))
throw response.error.message;
if (response.tfa && response.confirmUrl) {
const url = response.confirmUrl.replace(window.location.origin, "");
return url;
}
setWithCredentialsStatus(true);
// this.reset();
// this.init();
// const defaultPage = window["AscDesktopEditor"] !== undefined || IS_PERSONAL ? combineUrl(proxyURL, "/products/files/") : "/"
// return this.settingsStore.defaultPage;
return Promise.resolve(response);
} catch (e) {
return Promise.reject(e);
}
}
export async function thirdPartyLogin(SerializedProfile) {
try {
const response = await api.user.thirdPartyLogin(SerializedProfile);
if (!response || !response.token) throw new Error("Empty API response");
setWithCredentialsStatus(true);
// this.reset();
// this.init();
return Promise.resolve(response);
} catch (e) {
return Promise.reject(e);
}
}

View File

@ -81,7 +81,6 @@ class InputBlock extends React.Component {
break;
}
}
return (
<ColorTheme
hasError={hasError}

View File

@ -13,11 +13,15 @@ class SocialButton extends React.Component {
}
render() {
const { label, iconName, ...otherProps } = this.props;
const { label, iconName, IconComponent, ...otherProps } = this.props;
return (
<StyledSocialButton {...otherProps}>
<div>
{IconComponent ? (
<IconComponent className="iconWrapper" />
) : (
<ReactSVG className="iconWrapper" src={iconName} />
)}
</div>
<div>
{label && (

View File

@ -1,6 +1,6 @@
import difference from "lodash/difference";
import { LANGUAGE } from "@docspace/common/constants";
import { getLanguage } from "@docspace/common/utils";
import { getLanguage, getCookie } from "@docspace/common/utils";
export const getBannerAttribute = () => {
const bar = document.getElementById("bar-banner");
const mainBar = document.getElementById("main-bar");
@ -21,7 +21,7 @@ export const getBannerAttribute = () => {
const loadLanguagePath = async () => {
if (!window.firebaseHelper) return;
const lng = localStorage.getItem(LANGUAGE) || "en";
const lng = getCookie(LANGUAGE) || "en";
const language = getLanguage(lng instanceof Array ? lng[0] : lng);
const bar = (localStorage.getItem("bar") || "")

View File

@ -1,3 +1,5 @@
import { checkIsSSR } from "@docspace/common/utils";
export const size = {
mobile: 375,
hugeMobile: 428,
@ -35,7 +37,9 @@ export const isTablet = () => {
};
export const isDesktop = () => {
if (!checkIsSSR()) {
return window.innerWidth >= size.desktop;
} else return false;
};
export const isTouchDevice = !!(

Some files were not shown because too many files have changed in this diff Show More