Merge branch 'develop' into feature/active-sessions
This commit is contained in:
commit
e9032368ec
@ -8,7 +8,7 @@
|
||||
"name": "🚀 @docspace/client",
|
||||
"path": "packages/client",
|
||||
},
|
||||
{
|
||||
{
|
||||
"name": "🔑 @docspace/login",
|
||||
"path": "packages/login",
|
||||
},
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "الغرفة غير مثبتة",
|
||||
"SearchByContent": "ابحث من خلال محتويات الملف",
|
||||
"SendByEmail": "ارسل بالبريد الإلكترونى",
|
||||
"Share": "شارك",
|
||||
"ShareFolder": "مشاركة المجلد",
|
||||
"ShareFolderDescription": "سيتم إنشاء غرفة جديدة وسيتم نسخ جميع محتويات المجلد المحدد هناك. وبعد ذلك، يمكنك دعوة مستخدمين آخرين للتعاون في الملفات الموجودة داخل الغرفة.",
|
||||
"ShareRoom": "مشاركة الغرفة",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Otaq sabitləmədən çıxarıldı",
|
||||
"SearchByContent": "Fayl məzmununa görə axtarın",
|
||||
"SendByEmail": "Elektron poçt vasitəsi ilə göndər",
|
||||
"Share": "Paylaş",
|
||||
"ShareFolder": "Qovluğu paylaşın",
|
||||
"ShareFolderDescription": "Yeni otaq yaradılacaq və seçilmiş qovluğun bütün məzmunu oraya nüsxələnəcək. Daha sonra digər istifadəçiləri otaqdakı fayllar üzərində əməkdaşlığa dəvət edə bilərsiniz.",
|
||||
"ShareRoom": "Otağı paylaşın",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Стаята е освободена",
|
||||
"SearchByContent": "Търсене по съдържание на файла",
|
||||
"SendByEmail": "Изпратен по имейл",
|
||||
"Share": "Сподели",
|
||||
"ShareFolder": "Папка за споделяне",
|
||||
"ShareFolderDescription": "Ще бъде създадена нова стая и цялото съдържание на избраната папка ще бъде копирано там. След това можете да поканите други потребители да си сътрудничат по файловете в стаята.",
|
||||
"ShareRoom": "Сподели стая",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Místnost odepnuta",
|
||||
"SearchByContent": "Vyhledávání podle obsahu souboru",
|
||||
"SendByEmail": "Odeslat emailem",
|
||||
"Share": "Sdílet",
|
||||
"ShareFolder": "Sdílet složku",
|
||||
"ShareFolderDescription": "Vytvoří se nová místnost a veškerý obsah vybrané složky se do ní zkopíruje. Poté můžete ke spolupráci na souborech v místnosti přizvat další uživatele.",
|
||||
"ShareRoom": "Sdílet místnost",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Raum nicht mehr angeheftet",
|
||||
"SearchByContent": "Suche nach Dateiinhalten",
|
||||
"SendByEmail": "Per E-Mail senden",
|
||||
"Share": "Freigeben",
|
||||
"ShareFolder": "Ordner freigeben",
|
||||
"ShareFolderDescription": "Es wird ein neuer Raum erstellt und alle Inhalte des ausgewählten Ordners werden dorthin kopiert. Anschließend können Sie andere Benutzer zur Zusammenarbeit an den Dateien in einem Raum einladen.",
|
||||
"ShareRoom": "Raum freigeben",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Το δωμάτιο ξεκαρφιτσώθηκε",
|
||||
"SearchByContent": "Αναζήτηση με βάση τα περιεχόμενα του αρχείου",
|
||||
"SendByEmail": "Αποστολή μέσω email",
|
||||
"Share": "Κοινή χρήση",
|
||||
"ShareFolder": "Φάκελος κοινής χρήσης",
|
||||
"ShareFolderDescription": "Θα δημιουργηθεί ένα νέο δωμάτιο και όλα τα περιεχόμενα του επιλεγμένου φακέλου θα αντιγραφούν εκεί. Στη συνέχεια, μπορείτε να προσκαλέσετε άλλους χρήστες να συνεργαστούν στα αρχεία εντός ενός δωματίου.",
|
||||
"ShareRoom": "Κοινή χρήση δωματίου",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"ActivationRequired": "activation required",
|
||||
"ChooseRoomType": "Choose room type",
|
||||
"CollaborationRoomDescription": "Collaborate on one or multiple documents with your team",
|
||||
"CollaborationRoomTitle": "Collaboration room",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Room unpinned",
|
||||
"SearchByContent": "Search by file contents",
|
||||
"SendByEmail": "Send by email",
|
||||
"Share": "Share",
|
||||
"ShareFolder": "Share folder",
|
||||
"ShareFolderDescription": "A new room will be created and all the contents of the selected folder will be copied there. Afterward, you can invite other users to collaborate on the files within a room.",
|
||||
"ShareRoom": "Share room",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Se ha desanclado la sala",
|
||||
"SearchByContent": "Buscar por contenido del archivo",
|
||||
"SendByEmail": "Enviar por correo electrónico",
|
||||
"Share": "Compartir",
|
||||
"ShareFolder": "Compartir carpeta",
|
||||
"ShareFolderDescription": "Se creará una nueva sala y allí se copiará todo el contenido de la carpeta seleccionada. Luego, puede invitar a otros usuarios a colaborar en los archivos dentro de una sala.",
|
||||
"ShareRoom": "Compartir sala",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Huone irrotettu",
|
||||
"SearchByContent": "Etsi kansion sisällön mukaan",
|
||||
"SendByEmail": "Lähetä sähköpostitse",
|
||||
"Share": "Jaa",
|
||||
"ShareFolder": "Jaa kansio",
|
||||
"ShareFolderDescription": "Uusi huone luodaan ja koko valitun kansion sisältö kopioidaan tähän. Sen jälkeen voit kutsua käyttäjiä huoneeseen tekemään yhteistyötä tiedostoilla.",
|
||||
"ShareRoom": "Jaa huone",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Salle désépinglée",
|
||||
"SearchByContent": "Recherche par contenu de fichier",
|
||||
"SendByEmail": "Envoyer par émail",
|
||||
"Share": "Partager",
|
||||
"ShareFolder": "Partager le dossier",
|
||||
"ShareFolderDescription": "Une nouvelle salle sera créée et tout le contenu du dossier sélectionné y sera copié. Vous pouvez ensuite inviter d'autres utilisateurs à collaborer sur les fichiers d'une salle.",
|
||||
"ShareRoom": "Partager la salle",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Սենյակն ապաամրացվեց",
|
||||
"SearchByContent": "Որոնել ըստ ֆայլի բովանդակության",
|
||||
"SendByEmail": "Ուղարկել էլփոստով",
|
||||
"Share": "Համօգտագործել",
|
||||
"ShareFolder": "Համօգտագործել թղթապանակը",
|
||||
"ShareFolderDescription": "Կստեղծվի նոր սենյակ, և ընտրված թղթապանակի ամբողջ բովանդակությունը կպատճենվի այնտեղ: Այնուհետև կարող եք հրավիրել այլ օգտատերերի՝ համագործակցելու սենյակում գտնվող ֆայլերի շուրջ:",
|
||||
"ShareRoom": "Կիսվեք սենյակով",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "La stanza è stata sbloccata",
|
||||
"SearchByContent": "Cerca per contenuto del file",
|
||||
"SendByEmail": "Invia per email",
|
||||
"Share": "Condividi",
|
||||
"ShareFolder": "Condividi cartella",
|
||||
"ShareFolderDescription": "Verrà creata una nuova stanza e tutto il contenuto della cartella selezionata verrà copiato lì. Successivamente, puoi invitare altri utenti a collaborare sui file all'interno di una stanza.",
|
||||
"ShareRoom": "Condividi stanza",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "ルームの固定を削除されました",
|
||||
"SearchByContent": "ファイルの内容で検索",
|
||||
"SendByEmail": "メールで送信",
|
||||
"Share": "シェア",
|
||||
"ShareFolder": "共有フォルダ",
|
||||
"ShareFolderDescription": "新しいルームが作成され、選択したフォルダのすべての内容がそこにコピーされます。その後、あなたはルーム内のファイル上で共同作業を行うために他のユーザーを招待することができます。",
|
||||
"ShareRoom": "共有ルーム",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "방의 고정이 해제되었습니다",
|
||||
"SearchByContent": "파일 콘텐츠로 검색",
|
||||
"SendByEmail": "이메일로 전송",
|
||||
"Share": "공유",
|
||||
"ShareFolder": "폴더 공유",
|
||||
"ShareFolderDescription": "새 방이 생성되고 선택한 폴더의 모든 내용이 해당 방에 복사됩니다. 그 다음 다른 사용자를 초대하여 방에 있는 파일을 공동작업할 수 있습니다.",
|
||||
"ShareRoom": "방 공유",
|
||||
|
@ -99,7 +99,6 @@
|
||||
"RoomUnpinned": "ຖອດປັກໝຸດຫ້ອງແລ້ວ",
|
||||
"SearchByContent": "ຄົ້ນຫາໂດຍເນື້ອໃນໄຟລ໌",
|
||||
"SendByEmail": "ສົ່ງຜ່ານອີເມວ",
|
||||
"Share": "ແບ່ງປັນ",
|
||||
"ShowVersionHistory": "ສະແດງປະຫວັດສະບັບ",
|
||||
"Spreadsheet": "ຄຳນວນ",
|
||||
"TooltipElementCopyMessage": "ຄັດລອກ {{element}}",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Telpa ir atbloķēta",
|
||||
"SearchByContent": "Meklēt pēc faila satura",
|
||||
"SendByEmail": "Sūtīt pa e-pastu",
|
||||
"Share": "Kopīgot",
|
||||
"ShareFolder": "Kopīgot mapi",
|
||||
"ShareFolderDescription": "Tiks izveidota jauna telpa, un tur tiks kopēts viss atlasītās mapes saturs. Pēc tam varat uzaicināt citus lietotājus sadarboties ar telpas failiem.",
|
||||
"ShareRoom": "Kopīgot telpu",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Kamer niet gepint",
|
||||
"SearchByContent": "Zoeken op inhoud van bestanden",
|
||||
"SendByEmail": "Verstuur per e-mail",
|
||||
"Share": "Delen",
|
||||
"ShareFolder": "Deel map",
|
||||
"ShareFolderDescription": "Er wordt een nieuwe kamer aangemaakt en al het materiaal van de geselecteerde map wordt daarheen gekopieerd. Daarna kunt u andere gebruikers uitnodigen om samen te werken aan de bestanden binnen een kamer.",
|
||||
"ShareRoom": "Kamer delen",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Pokój został odpięty",
|
||||
"SearchByContent": "Wyszukaj wg zawartości pliku",
|
||||
"SendByEmail": "Wyślij e-mailem",
|
||||
"Share": "Udostępnij",
|
||||
"ShareFolder": "Udostępnij katalog",
|
||||
"ShareFolderDescription": "Zostanie utworzony nowy pokój, a cała zawartość wybranego katalogu zostanie do niego skopiowana. Następnie możesz zaprosić innych użytkowników do współpracy nad plikami w pokoju.",
|
||||
"ShareRoom": "Udostępnij pokój",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Sala desafixada",
|
||||
"SearchByContent": "Pesquise pelo conteúdo do arquivo",
|
||||
"SendByEmail": "Enviar por e-mail",
|
||||
"Share": "Compartilhar",
|
||||
"ShareFolder": "Compartilhar pasta",
|
||||
"ShareFolderDescription": "Uma nova sala será criada e todo o conteúdo da pasta selecionada será copiado para lá. Depois, você pode convidar outros usuários para colaborar nos arquivos de uma sala.",
|
||||
"ShareRoom": "Sala compartilhado",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Sala não afixada",
|
||||
"SearchByContent": "Procurar pelo conteúdo do ficheiro",
|
||||
"SendByEmail": "Enviar por e-mail",
|
||||
"Share": "Partilhar",
|
||||
"ShareFolder": "Compartilhar pasta",
|
||||
"ShareFolderDescription": "Uma nova sala será criada e todo o conteúdo da pasta selecionada será copiado para lá. Depois, você pode convidar outros usuários para colaborar nos arquivos de uma sala.",
|
||||
"ShareRoom": "Sala compartilhada",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Fixarea sălii anulată",
|
||||
"SearchByContent": "Căutare după conținutul fișierelor",
|
||||
"SendByEmail": "Trimite prin email",
|
||||
"Share": "Partajează",
|
||||
"ShareFolder": "Partajare folder",
|
||||
"ShareFolderDescription": "O sală nouă va fi creată și tot conținutul folderului selectat va fi copiat acolo. Ulterior, puteți invita alți utilizatori să colaboreze la fișiere în cadrul unei săli.",
|
||||
"ShareRoom": "Partajare sală",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Комната откреплена",
|
||||
"SearchByContent": "Поиск по содержимому файла",
|
||||
"SendByEmail": "Отправить по почте",
|
||||
"Share": "Доступ",
|
||||
"ShareFolder": "Предоставить доступ к папке",
|
||||
"ShareFolderDescription": "Будет создана новая комната, и все содержимое выбранной папки будет скопировано в нее. После этого вы сможете пригласить других пользователей для совместной работы над файлами в комнате.",
|
||||
"ShareRoom": "Предоставить доступ к комнате",
|
||||
|
@ -90,7 +90,6 @@
|
||||
"RoomUnpinned": "කාමරය ගැළවිණි",
|
||||
"SearchByContent": "ගොනු අන්තර්ගත අනුව සොයන්න",
|
||||
"SendByEmail": "වි-තැපෑලෙන් යවන්න",
|
||||
"Share": "බෙදාගන්න",
|
||||
"ShowVersionHistory": "අනුවාද ඉතිහාසය පෙන්වන්න",
|
||||
"Spreadsheet": "පැතුරුම්පත",
|
||||
"TooltipElementCopyMessage": "{{element}} පිටපත් කරන්න",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Miestnosť je odopnutá",
|
||||
"SearchByContent": "Vyhľadávanie podľa obsahu súboru",
|
||||
"SendByEmail": "Poslať e-mailom",
|
||||
"Share": "Zdieľať",
|
||||
"ShareFolder": "Zdieľať priečinok",
|
||||
"ShareFolderDescription": "Bude vytvorená nová miestnosť a skopíruje sa do nej celý obsah vybraného priečinka. Následne môžete pozvať ďalších používateľov na spoluprácu na súboroch v danej miestnosti.",
|
||||
"ShareRoom": "Zdieľať miestnosť",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Soba odpeta",
|
||||
"SearchByContent": "Išči po vsebini datotek",
|
||||
"SendByEmail": "Pošlji po email",
|
||||
"Share": "Deli",
|
||||
"ShareFolder": "Deljena mapa",
|
||||
"ShareFolderDescription": "Ustvarila se bo nova soba in vanjo bo kopirana vsa vsebina izbrane mape. Nato lahko druge uporabnike povabite k sodelovanju pri datotekah v sobi.",
|
||||
"ShareRoom": "Deli sobo",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Sobe otkačene",
|
||||
"SearchByContent": "Pretražuj po sadržaju datoteke",
|
||||
"SendByEmail": "Pošalji putem email-a",
|
||||
"Share": "Deli",
|
||||
"ShareFolder": "Deli folder",
|
||||
"ShareFolderDescription": "Nova soba će biti kreirana i sav sadržaj izabranog foldera će biti kopiran tamo. Nakon toga, možete pozvati druge korisnike da sarađuju na datotekama u sobi.",
|
||||
"ShareRoom": "Deli sobu",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Odanın sabitlemesi kaldırıldı",
|
||||
"SearchByContent": "Dosya içeriğine göre ara",
|
||||
"SendByEmail": "E-posta ile gönder",
|
||||
"Share": "Paylaş",
|
||||
"ShareFolder": "Klasörü paylaş",
|
||||
"ShareFolderDescription": "Yeni bir oda oluşturulacak ve seçilen klasörün tüm içeriği buraya kopyalanacaktır. Daha sonra, diğer kullanıcıları bir oda içindeki dosyalar üzerinde iş birliği yapmaya davet edebilirsiniz.",
|
||||
"ShareRoom": "Odayı paylaş",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Кімнату відкріплено",
|
||||
"SearchByContent": "Пошук за вмістом файлу",
|
||||
"SendByEmail": "Надіслати ел. поштою",
|
||||
"Share": "Надати спільний доступ",
|
||||
"ShareFolder": "Спільний доступ до папки",
|
||||
"ShareFolderDescription": "Буде створено нову кімнату, і весь вміст вибраної папки буде скопійовано туди. Після цього ви зможете запрошувати інших користувачів до спільної роботи над файлами в кімнаті.",
|
||||
"ShareRoom": "Поділитися кімнатою",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "Phòng đã hủy ghim",
|
||||
"SearchByContent": "Tìm kiếm theo nội dung tập tin",
|
||||
"SendByEmail": "Gửi qua email",
|
||||
"Share": "Chia sẻ",
|
||||
"ShareFolder": "Chia sẻ thư mục",
|
||||
"ShareFolderDescription": "Một phòng mới sẽ được tạo và tất cả nội dung của thư mục đã chọn sẽ được sao chép vào đó. Sau đó, bạn có thể mời những người dùng khác cộng tác trên các tập tin trong phòng.",
|
||||
"ShareRoom": "Chia sẻ phòng",
|
||||
|
@ -158,7 +158,6 @@
|
||||
"RoomUnpinned": "房间已取消置顶",
|
||||
"SearchByContent": "按文件内容搜索",
|
||||
"SendByEmail": "通过邮件发送",
|
||||
"Share": "分享",
|
||||
"ShareFolder": "共享文件夹",
|
||||
"ShareFolderDescription": "系统会创建一个新房间,并将所选文件夹的所有内容复制到其中。之后,您可以邀请其他用户在房间内协作处理文件。",
|
||||
"ShareRoom": "分享房间",
|
||||
|
@ -36,6 +36,8 @@ import ErrorBoundary from "./components/ErrorBoundaryWrapper";
|
||||
import store from "client/store";
|
||||
import i18n from "./i18n";
|
||||
|
||||
import "@docspace/shared/polyfills/broadcastchannel";
|
||||
|
||||
import "@docspace/shared/styles/custom.scss";
|
||||
|
||||
import router from "./router";
|
||||
|
@ -33,11 +33,15 @@ import {
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
//import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { getCorrectDate, getCookie } from "@docspace/shared/utils";
|
||||
import {
|
||||
getCorrectDate,
|
||||
getCookie,
|
||||
getTitleWithoutExtension,
|
||||
} from "@docspace/shared/utils";
|
||||
import { LANGUAGE } from "@docspace/shared/constants";
|
||||
import config from "PACKAGE_FILE";
|
||||
//import EditingWrapperComponent from "../components/EditingWrapperComponent";
|
||||
import { getTitleWithoutExtension } from "SRC_DIR/helpers/filesUtils";
|
||||
|
||||
//import { getDefaultFileName } from "@docspace/client/src/helpers/filesUtils";
|
||||
//import ItemIcon from "../components/ItemIcon";
|
||||
|
||||
|
@ -34,10 +34,10 @@ import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { setEncryptionAccess } from "SRC_DIR/helpers/desktop";
|
||||
import config from "PACKAGE_FILE";
|
||||
|
||||
import { getTitleWithoutExtension } from "SRC_DIR/helpers/filesUtils";
|
||||
import { getDefaultFileName } from "@docspace/client/src/helpers/filesUtils";
|
||||
|
||||
import Dialog from "./sub-components/Dialog";
|
||||
import { getTitleWithoutExtension } from "@docspace/shared/utils";
|
||||
|
||||
const CreateEvent = ({
|
||||
id,
|
||||
|
@ -29,7 +29,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import Dialog from "./sub-components/Dialog";
|
||||
import { getTitleWithoutExtension } from "SRC_DIR/helpers/filesUtils";
|
||||
import { getTitleWithoutExtension } from "@docspace/shared/utils";
|
||||
|
||||
const RenameEvent = ({
|
||||
type,
|
||||
|
@ -45,6 +45,7 @@ import { inject, observer } from "mobx-react";
|
||||
import PreparationPortalDialog from "../dialogs/PreparationPortalDialog";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import { isPublicPreview } from "@docspace/shared/utils/common";
|
||||
|
||||
const StyledContainer = styled.header`
|
||||
height: ${(props) => props.theme.header.height};
|
||||
@ -158,7 +159,7 @@ const NavMenu = (props) => {
|
||||
} = props;
|
||||
|
||||
const isAsideAvailable = !!asideContent;
|
||||
const hideHeader = !showHeader && isFrame;
|
||||
const hideHeader = (!showHeader && isFrame) || isPublicPreview();
|
||||
|
||||
if (currentDeviceType !== DeviceType.mobile || !isMobile() || hideHeader)
|
||||
return <></>;
|
||||
|
@ -453,7 +453,6 @@ export default inject(
|
||||
openConnectWindow,
|
||||
fetchThirdPartyProviders,
|
||||
setConnectDialogVisible,
|
||||
setSelectedThirdPartyAccount,
|
||||
isConnectDialogReconnect,
|
||||
saveAfterReconnectOAuth,
|
||||
setSaveAfterReconnectOAuth,
|
||||
|
@ -36,6 +36,8 @@ import { Base } from "@docspace/shared/themes";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
|
||||
import ExternalLinkReactSvgUrl from "PUBLIC_DIR/images/external.link.react.svg?url";
|
||||
|
||||
const StyledStorageLocation = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -58,10 +60,49 @@ const StyledStorageLocation = styled.div`
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.storage-unavailable {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.drop-down-item_icon {
|
||||
svg {
|
||||
path[fill] {
|
||||
fill: ${(props) => props.theme.dropDownItem.disableColor};
|
||||
}
|
||||
|
||||
path[stroke] {
|
||||
stroke: ${(props) => props.theme.dropDownItem.disableColor};
|
||||
}
|
||||
|
||||
circle[fill] {
|
||||
fill: ${(props) => props.theme.dropDownItem.disableColor};
|
||||
}
|
||||
|
||||
rect[fill] {
|
||||
fill: ${(props) => props.theme.dropDownItem.disableColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color: ${(props) => props.theme.dropDownItem.disableColor};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledStorageLocation.defaultProps = { theme: Base };
|
||||
|
||||
const services = {
|
||||
GoogleDrive: "google",
|
||||
Box: "box",
|
||||
Dropbox: "dropbox",
|
||||
OneDrive: "skydrive",
|
||||
Nextcloud: "nextcloud",
|
||||
kDrive: "kdrive",
|
||||
ownCloud: "owncloud",
|
||||
WebDav: "webdav",
|
||||
};
|
||||
|
||||
const ThirdPartyComboBox = ({
|
||||
t,
|
||||
|
||||
@ -84,14 +125,28 @@ const ThirdPartyComboBox = ({
|
||||
|
||||
isDisabled,
|
||||
}) => {
|
||||
const deafultSelectedItem = {
|
||||
key: "length",
|
||||
label:
|
||||
storageLocation?.provider?.title ||
|
||||
t("ThirdPartyStorageComboBoxPlaceholder"),
|
||||
};
|
||||
|
||||
const [selectedItem, setSelectedItem] = useState(deafultSelectedItem);
|
||||
|
||||
const thirdparties = connectItems.map((item) => ({
|
||||
...item,
|
||||
title: item.category
|
||||
? item.category
|
||||
: ProviderKeyTranslation(item.providerKey, t),
|
||||
title: ProviderKeyTranslation(item.providerKey, t),
|
||||
}));
|
||||
|
||||
const setStorageLocaiton = (thirparty) => {
|
||||
const setStorageLocaiton = (thirparty, isConnected) => {
|
||||
if (!isConnected) {
|
||||
window.open(
|
||||
`/portal-settings/integration/third-party-services?service=${services[thirparty.id]}`,
|
||||
"_blank",
|
||||
);
|
||||
return;
|
||||
}
|
||||
onChangeProvider(thirparty);
|
||||
};
|
||||
|
||||
@ -152,19 +207,26 @@ const ThirdPartyComboBox = ({
|
||||
setSaveThirdpartyResponse(null);
|
||||
}, [saveThirdpartyResponse]);
|
||||
|
||||
const options = thirdparties.map((item) => ({
|
||||
label: item.title,
|
||||
title: item.title,
|
||||
key: item?.category ?? item.id,
|
||||
}));
|
||||
const options = thirdparties
|
||||
.sort((storage) => (storage.isConnected ? -1 : 1))
|
||||
.map((item) => ({
|
||||
label:
|
||||
item.title + (item.isConnected ? "" : ` (${t("ActivationRequired")})`),
|
||||
title: item.title,
|
||||
key: item.id,
|
||||
icon: item.isConnected ? undefined : ExternalLinkReactSvgUrl,
|
||||
className: item.isConnected ? "" : "storage-unavailable",
|
||||
}));
|
||||
|
||||
const onSelect = (elem) => {
|
||||
const thirdparty = thirdparties.find((t) => {
|
||||
if (t.category) return elem.key === t.category;
|
||||
else return elem.key === t.id;
|
||||
return elem.key === t.id;
|
||||
});
|
||||
|
||||
thirdparty && setStorageLocaiton(thirdparty);
|
||||
thirdparty && setStorageLocaiton(thirdparty, thirdparty.isConnected);
|
||||
thirdparty.isConnected
|
||||
? setSelectedItem(elem)
|
||||
: setSelectedItem({ ...deafultSelectedItem });
|
||||
};
|
||||
|
||||
return (
|
||||
@ -172,12 +234,7 @@ const ThirdPartyComboBox = ({
|
||||
<div className="set_room_params-thirdparty">
|
||||
<ComboBox
|
||||
className="thirdparty-combobox"
|
||||
selectedOption={{
|
||||
key: "length",
|
||||
label:
|
||||
storageLocation?.provider?.title ||
|
||||
t("ThirdPartyStorageComboBoxPlaceholder"),
|
||||
}}
|
||||
selectedOption={selectedItem}
|
||||
options={options}
|
||||
scaled
|
||||
withBackdrop={isMobile}
|
||||
|
@ -24,7 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import styled from "styled-components";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
@ -73,7 +73,14 @@ const ThirdPartyStorage = ({
|
||||
isRoomAdmin,
|
||||
createNewFolderIsChecked,
|
||||
onCreateFolderChange,
|
||||
|
||||
fetchConnectingStorages,
|
||||
}) => {
|
||||
const channel = useRef(new BroadcastChannel("thirdpartyActivation"));
|
||||
channel.current.onmessage = (shouldRender) => {
|
||||
shouldRender && fetchConnectingStorages()
|
||||
};
|
||||
|
||||
const onChangeIsThirdparty = () => {
|
||||
if (isDisabled) return;
|
||||
|
||||
@ -125,6 +132,10 @@ const ThirdPartyStorage = ({
|
||||
storageFolderId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fetchConnectingStorages();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<StyledThirdPartyStorage>
|
||||
<ToggleParam
|
||||
@ -196,38 +207,7 @@ export default inject(
|
||||
|
||||
const thirdPartyStore = filesSettingsStore.thirdPartyStore;
|
||||
|
||||
const connectItems = [
|
||||
thirdPartyStore.googleConnectItem,
|
||||
thirdPartyStore.boxConnectItem,
|
||||
thirdPartyStore.dropboxConnectItem,
|
||||
thirdPartyStore.oneDriveConnectItem,
|
||||
thirdPartyStore.nextCloudConnectItem && [
|
||||
...thirdPartyStore.nextCloudConnectItem,
|
||||
"Nextcloud",
|
||||
],
|
||||
thirdPartyStore.kDriveConnectItem,
|
||||
thirdPartyStore.yandexConnectItem,
|
||||
thirdPartyStore.ownCloudConnectItem && [
|
||||
...thirdPartyStore.ownCloudConnectItem,
|
||||
"ownCloud",
|
||||
],
|
||||
thirdPartyStore.webDavConnectItem,
|
||||
thirdPartyStore.sharePointConnectItem,
|
||||
]
|
||||
.map(
|
||||
(item) =>
|
||||
item && {
|
||||
id: item[0],
|
||||
className: `storage_${item[0].toLowerCase()}`,
|
||||
providerKey: item[0],
|
||||
isOauth: item.length > 1 && item[0] !== "WebDav",
|
||||
oauthHref: item.length > 1 && item[0] !== "WebDav" ? item[1] : "",
|
||||
...(item[0] === "WebDav" && {
|
||||
category: item[item.length - 1],
|
||||
}),
|
||||
},
|
||||
)
|
||||
.filter((item) => !!item);
|
||||
const connectItems = thirdPartyStore.connectingStorages;
|
||||
|
||||
const { isRoomAdmin } = authStore;
|
||||
|
||||
@ -248,6 +228,7 @@ export default inject(
|
||||
getOAuthToken,
|
||||
currentColorScheme,
|
||||
isRoomAdmin,
|
||||
fetchConnectingStorages: thirdPartyStore.fetchConnectingStorages,
|
||||
};
|
||||
},
|
||||
)(observer(ThirdPartyStorage));
|
||||
|
@ -226,10 +226,3 @@ export const connectedCloudsTypeIcon = (key) => {
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
export const getTitleWithoutExtension = (item, fromTemplate) => {
|
||||
const titleWithoutExst = item.title.split(".").slice(0, -1).join(".");
|
||||
return titleWithoutExst && item.fileExst && !fromTemplate
|
||||
? titleWithoutExst
|
||||
: item.title;
|
||||
};
|
||||
|
@ -130,7 +130,7 @@ const InfoPanelHeaderContent = (props) => {
|
||||
if (selection?.canShare) {
|
||||
personalSubmenu.unshift({
|
||||
id: "info_share",
|
||||
name: t("Files:Share"),
|
||||
name: t("Common:Share"),
|
||||
onClick: setShare,
|
||||
content: null,
|
||||
});
|
||||
|
@ -50,7 +50,6 @@ class FilesTableHeader extends React.Component {
|
||||
columnInfoPanelStorageName,
|
||||
isPublicRoom,
|
||||
isFrame,
|
||||
frameTableColumns,
|
||||
isRecentTab,
|
||||
isDefaultRoomsQuotaSet,
|
||||
showStorageInfo,
|
||||
@ -362,18 +361,7 @@ class FilesTableHeader extends React.Component {
|
||||
const storageColumns = localStorage.getItem(this.props.tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
const resetColumnsSize =
|
||||
(splitColumns && splitColumns.length !== columns.length) ||
|
||||
!splitColumns ||
|
||||
isFrame;
|
||||
|
||||
if (isFrame && frameTableColumns) {
|
||||
const frameTableArray = frameTableColumns.split(",");
|
||||
|
||||
columns = columns.map((col) => {
|
||||
col.enable = frameTableArray.includes(col.key) ? true : false;
|
||||
return col;
|
||||
});
|
||||
}
|
||||
(splitColumns && splitColumns.length !== columns.length) || !splitColumns;
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
|
||||
@ -705,7 +693,6 @@ export default inject(
|
||||
publicRoomKey,
|
||||
|
||||
isFrame,
|
||||
frameTableColumns: frameConfig?.viewTableColumns,
|
||||
isRecentTab,
|
||||
showSettings: frameConfig?.showSettings,
|
||||
isDefaultRoomsQuotaSet,
|
||||
|
@ -925,7 +925,7 @@ const SectionHeaderContent = (props) => {
|
||||
{
|
||||
id: "header_option_sharing-settings",
|
||||
key: "sharing-settings",
|
||||
label: t("Files:Share"),
|
||||
label: t("Common:Share"),
|
||||
onClick: onClickShare,
|
||||
disabled: !selectedFolder.security?.CreateRoomFrom,
|
||||
icon: ShareReactSvgUrl,
|
||||
|
@ -518,7 +518,10 @@ const Manager = (props) => {
|
||||
|
||||
const onChangeSearch = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, search: e.target.value };
|
||||
return {
|
||||
...config,
|
||||
filter: { ...config.filter, filterValue: e.target.value },
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@ -1266,7 +1269,7 @@ const Manager = (props) => {
|
||||
scale={true}
|
||||
onChange={onChangeSearch}
|
||||
placeholder={t("Common:Search")}
|
||||
value={config.search}
|
||||
value={config.filter.filterValue}
|
||||
tabIndex={5}
|
||||
/>
|
||||
<Checkbox
|
||||
|
@ -116,9 +116,17 @@ class ThirdPartyServices extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { getConsumers } = this.props;
|
||||
const { getConsumers, fetchAndSetConsumers } = this.props;
|
||||
showLoader();
|
||||
getConsumers().finally(() => hideLoader());
|
||||
const urlParts = window.location.href.split("?");
|
||||
if (urlParts.length > 1) {
|
||||
const queryValue = urlParts[1].split("=")[1];
|
||||
fetchAndSetConsumers(queryValue)
|
||||
.then((isConsumerExist) => isConsumerExist && this.onModalOpen())
|
||||
.finally(() => hideLoader());
|
||||
} else {
|
||||
getConsumers().finally(() => hideLoader());
|
||||
}
|
||||
}
|
||||
|
||||
onChangeLoading = (status) => {
|
||||
@ -340,6 +348,7 @@ export default inject(
|
||||
integration,
|
||||
updateConsumerProps,
|
||||
setSelectedConsumer,
|
||||
fetchAndSetConsumers,
|
||||
} = setup;
|
||||
const { consumers } = integration;
|
||||
const { isThirdPartyAvailable } = currentQuotaStore;
|
||||
@ -351,6 +360,7 @@ export default inject(
|
||||
getConsumers,
|
||||
updateConsumerProps,
|
||||
setSelectedConsumer,
|
||||
fetchAndSetConsumers,
|
||||
setDocumentTitle,
|
||||
currentColorScheme,
|
||||
isThirdPartyAvailable,
|
||||
|
@ -111,6 +111,9 @@ class ConsumerModalDialog extends React.Component {
|
||||
onChangeLoading(false);
|
||||
hideLoader();
|
||||
toastr.success(t("ThirdPartyPropsActivated"));
|
||||
|
||||
const channel = new BroadcastChannel("thirdpartyActivation");
|
||||
channel.postMessage(true);
|
||||
})
|
||||
.catch((error) => {
|
||||
onChangeLoading(false);
|
||||
|
@ -23,12 +23,15 @@
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
// in this file you can append custom step methods to 'I' object
|
||||
|
||||
module.exports = function () {
|
||||
return actor({
|
||||
// Define custom steps here, use 'this' to access default methods of I.
|
||||
// It is recommended to place a general 'login' function here.
|
||||
});
|
||||
};
|
||||
export const DEFAULT_EXTS_IMAGE = [
|
||||
".svg",
|
||||
".bmp",
|
||||
".gif",
|
||||
".jpeg",
|
||||
".jpg",
|
||||
".png",
|
||||
".ico",
|
||||
".tif",
|
||||
".tiff",
|
||||
".webp",
|
||||
];
|
@ -0,0 +1,70 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
import { AxiosError } from "axios";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { getDeviceTypeByWidth } from "@docspace/shared/utils";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
export const useDeviceType = () => {
|
||||
const [currentDeviceType, setCurrentDeviceType] = useState<DeviceType>(() =>
|
||||
getDeviceTypeByWidth(window.innerWidth),
|
||||
);
|
||||
|
||||
const onResize = useCallback(() => {
|
||||
setCurrentDeviceType(getDeviceTypeByWidth(window.innerWidth));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
|
||||
if (isMobile) {
|
||||
if (window.screen.orientation) {
|
||||
window.screen.orientation.addEventListener("change", onResize);
|
||||
} else {
|
||||
window.addEventListener("orientationchange", onResize);
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
window.removeEventListener("orientationchange", onResize);
|
||||
window.screen?.orientation?.removeEventListener("change", onResize);
|
||||
};
|
||||
}, [onResize]);
|
||||
|
||||
return currentDeviceType;
|
||||
};
|
||||
|
||||
export const isAxiosError = (error: unknown): error is AxiosError => {
|
||||
return (
|
||||
error !== null &&
|
||||
typeof error === "object" &&
|
||||
"isAxiosError" in error &&
|
||||
typeof error.isAxiosError === "boolean" &&
|
||||
error.isAxiosError
|
||||
);
|
||||
};
|
140
packages/client/src/pages/PublicPreview/PublicPreview.tsx
Normal file
140
packages/client/src/pages/PublicPreview/PublicPreview.tsx
Normal file
@ -0,0 +1,140 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
|
||||
import api from "@docspace/shared/api";
|
||||
import { UrlActionType } from "@docspace/shared/enums";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import MediaViewer from "@docspace/shared/components/media-viewer/MediaViewer";
|
||||
import { ViewerLoader } from "@docspace/shared/components/media-viewer/sub-components/ViewerLoader";
|
||||
import Error403 from "@docspace/shared/components/errors/Error403";
|
||||
|
||||
import type { TFile } from "@docspace/shared/api/files/types";
|
||||
import type {
|
||||
NumberOrString,
|
||||
PlaylistType,
|
||||
} from "@docspace/shared/components/media-viewer/MediaViewer.types";
|
||||
|
||||
import type { PublicPreviewProps } from "./PublicPreview.types";
|
||||
import { DEFAULT_EXTS_IMAGE } from "./PublicPreview.constants";
|
||||
import { isAxiosError, useDeviceType } from "./PublicPreview.helpers";
|
||||
|
||||
const PublicPreview = ({
|
||||
getIcon,
|
||||
openUrl,
|
||||
getFilesSettings,
|
||||
extsImagePreviewed,
|
||||
}: PublicPreviewProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { id } = useParams();
|
||||
const currentDeviceType = useDeviceType();
|
||||
|
||||
const [files, setFiles] = useState<TFile[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [searchParams] = useSearchParams();
|
||||
const [errorStatus, setErrorStatus] = useState<number>();
|
||||
|
||||
const init = useCallback(async () => {
|
||||
const key = searchParams.get("share");
|
||||
|
||||
if (!id || !key) return;
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const [fileInfo] = await Promise.all([
|
||||
api.files.getFileInfo(id, key),
|
||||
getFilesSettings?.(),
|
||||
]);
|
||||
|
||||
if (!fileInfo) return;
|
||||
|
||||
setFiles([fileInfo]);
|
||||
} catch (error) {
|
||||
if (isAxiosError(error)) {
|
||||
const status = error.response?.status;
|
||||
|
||||
if (status !== undefined && status === 403) {
|
||||
return setErrorStatus(status);
|
||||
}
|
||||
|
||||
toastr.error(error);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [getFilesSettings, searchParams, id]);
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
}, [init]);
|
||||
|
||||
const getIconUrl = useCallback(
|
||||
(size: number, ext: string) => {
|
||||
return getIcon?.(size, ext) ?? "";
|
||||
},
|
||||
[getIcon],
|
||||
);
|
||||
|
||||
const playlist: PlaylistType[] = files.map((file, index) => ({
|
||||
id: index,
|
||||
fileId: file.id,
|
||||
src: file.viewUrl,
|
||||
title: file.title,
|
||||
fileExst: file.fileExst,
|
||||
fileStatus: file.fileStatus,
|
||||
canShare: file.canShare,
|
||||
version: file.version,
|
||||
thumbnailUrl: file.thumbnailUrl ?? "",
|
||||
}));
|
||||
|
||||
const onDownloadMediaFile = useCallback(
|
||||
(fileId: NumberOrString) => {
|
||||
if (playlist.length > 0) {
|
||||
const viewUrlFile = playlist.find(
|
||||
(file) => file.fileId === fileId,
|
||||
)?.src;
|
||||
|
||||
if (!viewUrlFile) return;
|
||||
|
||||
return openUrl?.(viewUrlFile, UrlActionType.Download);
|
||||
}
|
||||
},
|
||||
[playlist, openUrl],
|
||||
);
|
||||
|
||||
if (errorStatus === 403) return <Error403 />;
|
||||
|
||||
if (isLoading) return <ViewerLoader isLoading />;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{playlist.length > 0 && (
|
||||
<MediaViewer
|
||||
t={t}
|
||||
visible
|
||||
files={files}
|
||||
isPublicFile
|
||||
playlistPos={0}
|
||||
playlist={playlist}
|
||||
getIcon={getIconUrl}
|
||||
currentFileId={playlist[0].fileId}
|
||||
currentDeviceType={currentDeviceType}
|
||||
extsImagePreviewed={extsImagePreviewed ?? DEFAULT_EXTS_IMAGE}
|
||||
onDownload={onDownloadMediaFile}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject<TStore>(({ filesSettingsStore, settingsStore }) => {
|
||||
const { getFilesSettings, getIcon, extsImagePreviewed } = filesSettingsStore;
|
||||
const { openUrl } = settingsStore;
|
||||
|
||||
return { getFilesSettings, getIcon, openUrl, extsImagePreviewed };
|
||||
})(observer(PublicPreview));
|
@ -0,0 +1,6 @@
|
||||
export interface PublicPreviewProps {
|
||||
getFilesSettings?: TStore["filesSettingsStore"]["getFilesSettings"];
|
||||
getIcon?: TStore["filesSettingsStore"]["getIcon"];
|
||||
extsImagePreviewed?: TStore["filesSettingsStore"]["extsImagePreviewed"];
|
||||
openUrl?: TStore["settingsStore"]["openUrl"];
|
||||
}
|
@ -37,6 +37,9 @@ import ErrorBoundary from "../components/ErrorBoundaryWrapper";
|
||||
import FilesView from "SRC_DIR/pages/Home/View/Files";
|
||||
import AccountsView from "SRC_DIR/pages/Home/View/Accounts";
|
||||
import SettingsView from "SRC_DIR/pages/Home/View/Settings";
|
||||
const PublicPreview = loadable(() =>
|
||||
componentLoader(() => import("../pages/PublicPreview/PublicPreview")),
|
||||
);
|
||||
|
||||
import { generalRoutes } from "./general";
|
||||
|
||||
@ -380,6 +383,16 @@ const ClientRoutes = [
|
||||
</PrivateRoute>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/share/preview/:id",
|
||||
element: (
|
||||
<PublicRoute>
|
||||
<ErrorBoundary>
|
||||
<PublicPreview />
|
||||
</ErrorBoundary>
|
||||
</PublicRoute>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/rooms/share",
|
||||
element: (
|
||||
|
@ -1344,7 +1344,7 @@ class ContextOptionsStore {
|
||||
{
|
||||
id: "option_sharing-settings",
|
||||
key: "sharing-settings",
|
||||
label: t("Files:Share"),
|
||||
label: t("Common:Share"),
|
||||
icon: ShareReactSvgUrl,
|
||||
onClick: () => this.onClickShare(item),
|
||||
disabled: !isShareable,
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
} from "@docspace/shared/api/files";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
import { FolderType, RoomsType } from "@docspace/shared/enums";
|
||||
import axios from "axios";
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { presentInArray } from "@docspace/shared/utils";
|
||||
@ -40,7 +40,10 @@ import {
|
||||
iconSize96,
|
||||
} from "@docspace/shared/utils/image-helpers";
|
||||
import { HTML_EXST } from "@docspace/shared/constants";
|
||||
import { getIconPathByFolderType } from "@docspace/shared/utils/common";
|
||||
import {
|
||||
getIconPathByFolderType,
|
||||
isPublicPreview,
|
||||
} from "@docspace/shared/utils/common";
|
||||
class FilesSettingsStore {
|
||||
thirdPartyStore;
|
||||
treeFoldersStore;
|
||||
@ -150,7 +153,11 @@ class FilesSettingsStore {
|
||||
this.setFilesSettings(settings);
|
||||
this.setIsLoaded(true);
|
||||
|
||||
if (!settings.enableThirdParty || this.publicRoomStore.isPublicRoom)
|
||||
if (
|
||||
!settings.enableThirdParty ||
|
||||
this.publicRoomStore.isPublicRoom ||
|
||||
isPublicPreview()
|
||||
)
|
||||
return;
|
||||
|
||||
return axios
|
||||
@ -294,6 +301,17 @@ class FilesSettingsStore {
|
||||
isSpreadsheet = (extension) =>
|
||||
presentInArray(this.extsSpreadsheet, extension);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} [size = 24]
|
||||
* @param {string } [fileExst = null]
|
||||
* @param {string} [pproviderKey
|
||||
* @param {*} contentLength
|
||||
* @param {RoomsType | null} roomType
|
||||
* @param {boolean | null} isArchive
|
||||
* @param {FolderType} folderType
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
getIcon = (
|
||||
size = 24,
|
||||
fileExst = null,
|
||||
|
@ -249,7 +249,7 @@ class ProfileActionsStore {
|
||||
} = this.settingsStore;
|
||||
const isAdmin = this.authStore.isAdmin;
|
||||
const isCommunity = this.authStore.isCommunity;
|
||||
const { isOwner } = this.userStore.user;
|
||||
// const { isOwner } = this.userStore.user;
|
||||
|
||||
// const settingsModule = modules.find((module) => module.id === "settings");
|
||||
// const peopleAvailable = modules.some((m) => m.appName === "people");
|
||||
|
@ -498,6 +498,15 @@ class SettingsSetupStore {
|
||||
this.setConsumers(res);
|
||||
};
|
||||
|
||||
fetchAndSetConsumers = async (consumerName) => {
|
||||
const res = await api.settings.getConsumersList();
|
||||
const consumer = res.find((c) => c.name === consumerName);
|
||||
this.integration.selectedConsumer = consumer || {};
|
||||
this.setConsumers(res);
|
||||
|
||||
return !!consumer
|
||||
};
|
||||
|
||||
updateConsumerProps = async (newProps) => {
|
||||
await api.settings.updateConsumerProps(newProps);
|
||||
|
||||
|
@ -34,19 +34,16 @@ const TABLE_ACCOUNTS_INSIDE_GROUP_COLUMNS = `insideGroupTableColumns_ver-${Table
|
||||
const TABLE_ROOMS_COLUMNS = `roomsTableColumns_ver-${TableVersions.Rooms}`;
|
||||
const TABLE_TRASH_COLUMNS = `trashTableColumns_ver-${TableVersions.Trash}`;
|
||||
const TABLE_RECENT_COLUMNS = `recentTableColumns_ver-${TableVersions.Recent}`;
|
||||
const TABLE_SDK_COLUMNS = `filesSDKTableColumns_ver-${TableVersions.Files}`;
|
||||
|
||||
const COLUMNS_SIZE = `filesColumnsSize_ver-${TableVersions.Files}`;
|
||||
const COLUMNS_ROOMS_SIZE = `roomsColumnsSize_ver-${TableVersions.Rooms}`;
|
||||
const COLUMNS_TRASH_SIZE = `trashColumnsSize_ver-${TableVersions.Trash}`;
|
||||
const COLUMNS_RECENT_SIZE = `recentColumnsSize_ver-${TableVersions.Recent}`;
|
||||
const COLUMNS_SDK_SIZE = `filesSDKColumnsSize_ver-${TableVersions.Files}`;
|
||||
|
||||
const COLUMNS_SIZE_INFO_PANEL = `filesColumnsSizeInfoPanel_ver-${TableVersions.Files}`;
|
||||
const COLUMNS_ROOMS_SIZE_INFO_PANEL = `roomsColumnsSizeInfoPanel_ver-${TableVersions.Rooms}`;
|
||||
const COLUMNS_TRASH_SIZE_INFO_PANEL = `trashColumnsSizeInfoPanel_ver-${TableVersions.Trash}`;
|
||||
const COLUMNS_RECENT_SIZE_INFO_PANEL = `recentColumnsSizeInfoPanel_ver-${TableVersions.Recent}`;
|
||||
const COLUMNS_SDK_SIZE_INFO_PANEL = `filesSDKColumnsSizeInfoPanel_ver-${TableVersions.Files}`;
|
||||
|
||||
class TableStore {
|
||||
authStore;
|
||||
@ -176,9 +173,13 @@ class TableStore {
|
||||
setAccountsInsideGroupColumnGroup = (enable) =>
|
||||
(this.groupAccountsInsideGroupColumnIsEnabled = enable);
|
||||
|
||||
setColumnsEnable = () => {
|
||||
setColumnsEnable = (frameTableColumns) => {
|
||||
const storageColumns = localStorage.getItem(this.tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
const splitColumns = storageColumns
|
||||
? storageColumns.split(",")
|
||||
: frameTableColumns
|
||||
? frameTableColumns.split(",")
|
||||
: null;
|
||||
|
||||
if (splitColumns) {
|
||||
const {
|
||||
@ -360,8 +361,10 @@ class TableStore {
|
||||
};
|
||||
|
||||
getColumns = (defaultColumns) => {
|
||||
const { isFrame, frameConfig } = this.settingsStore;
|
||||
const storageColumns = localStorage.getItem(this.tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
const frameTableColumns = frameConfig?.viewTableColumns;
|
||||
|
||||
const columns = [];
|
||||
|
||||
@ -375,11 +378,20 @@ class TableStore {
|
||||
columns.push(col);
|
||||
}
|
||||
return columns;
|
||||
} else if (isFrame && frameTableColumns) {
|
||||
this.setColumnsEnable(frameTableColumns);
|
||||
|
||||
const frameTableArray = frameTableColumns.split(",");
|
||||
return defaultColumns.map((col) => {
|
||||
col.enable = frameTableArray.includes(col.key) ? true : false;
|
||||
return col;
|
||||
});
|
||||
} else {
|
||||
return defaultColumns;
|
||||
}
|
||||
};
|
||||
|
||||
// Column names
|
||||
get tableStorageName() {
|
||||
const {
|
||||
isRoomsFolder,
|
||||
@ -395,9 +407,7 @@ class TableStore {
|
||||
const userId = this.userStore.user?.id;
|
||||
const isFrame = this.settingsStore.isFrame;
|
||||
|
||||
if (isFrame) return `${TABLE_SDK_COLUMNS}=${userId}`;
|
||||
|
||||
return isRooms
|
||||
const tableStorageName = isRooms
|
||||
? `${TABLE_ROOMS_COLUMNS}=${userId}`
|
||||
: getIsAccountsPeople()
|
||||
? `${TABLE_ACCOUNTS_PEOPLE_COLUMNS}=${userId}`
|
||||
@ -410,8 +420,11 @@ class TableStore {
|
||||
: isRecentTab
|
||||
? `${TABLE_RECENT_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`;
|
||||
|
||||
return isFrame ? `SDK_${tableStorageName}` : tableStorageName;
|
||||
}
|
||||
|
||||
// Table column sizes
|
||||
get columnStorageName() {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isRecentTab } =
|
||||
this.treeFoldersStore;
|
||||
@ -419,17 +432,18 @@ class TableStore {
|
||||
const userId = this.userStore.user?.id;
|
||||
const isFrame = this.settingsStore.isFrame;
|
||||
|
||||
if (isFrame) return `${COLUMNS_SDK_SIZE}=${userId}`;
|
||||
|
||||
return isRooms
|
||||
const columnStorageName = isRooms
|
||||
? `${COLUMNS_ROOMS_SIZE}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${COLUMNS_TRASH_SIZE}=${userId}`
|
||||
: isRecentTab
|
||||
? `${COLUMNS_RECENT_SIZE}=${userId}`
|
||||
: `${COLUMNS_SIZE}=${userId}`;
|
||||
|
||||
return isFrame ? `SDK_${columnStorageName}` : columnStorageName;
|
||||
}
|
||||
|
||||
// Column names for info-panel
|
||||
get columnInfoPanelStorageName() {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isRecentTab } =
|
||||
this.treeFoldersStore;
|
||||
@ -437,15 +451,17 @@ class TableStore {
|
||||
const userId = this.userStore.user?.id;
|
||||
const isFrame = this.settingsStore.isFrame;
|
||||
|
||||
if (isFrame) return `${COLUMNS_SDK_SIZE_INFO_PANEL}=${userId}`;
|
||||
|
||||
return isRooms
|
||||
const columnInfoPanelStorageName = isRooms
|
||||
? `${COLUMNS_ROOMS_SIZE_INFO_PANEL}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${COLUMNS_TRASH_SIZE_INFO_PANEL}=${userId}`
|
||||
: isRecentTab
|
||||
? `${COLUMNS_RECENT_SIZE_INFO_PANEL}=${userId}`
|
||||
: `${COLUMNS_SIZE_INFO_PANEL}=${userId}`;
|
||||
|
||||
return isFrame
|
||||
? `SDK_${columnInfoPanelStorageName}`
|
||||
: columnInfoPanelStorageName;
|
||||
}
|
||||
|
||||
get filesColumnStorageName() {
|
||||
|
@ -51,6 +51,7 @@ import i18n from "../i18n";
|
||||
class ThirdPartyStore {
|
||||
capabilities = null;
|
||||
providers = [];
|
||||
connectingStorages = [];
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
@ -71,6 +72,20 @@ class ThirdPartyStore {
|
||||
this.setThirdPartyProviders(list);
|
||||
};
|
||||
|
||||
fetchConnectingStorages = async () => {
|
||||
const res = await api.files.getConnectingStorages();
|
||||
|
||||
this.connectingStorages = res.map((storage) => ({
|
||||
id: storage.name,
|
||||
className: `storage_${storage.key}`,
|
||||
providerKey: storage.key !== "WebDav" ? storage.key : storage.name,
|
||||
isConnected: storage.connected,
|
||||
isOauth: storage.oauth,
|
||||
oauthHref: storage.redirectUrl,
|
||||
category: storage.name,
|
||||
}));
|
||||
};
|
||||
|
||||
saveThirdParty = (
|
||||
url,
|
||||
login,
|
||||
|
@ -28,6 +28,7 @@ import { makeAutoObservable, runInAction } from "mobx";
|
||||
import api from "@docspace/shared/api";
|
||||
import { size } from "@docspace/shared/utils";
|
||||
import { FileStatus } from "@docspace/shared/enums";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
class VersionHistoryStore {
|
||||
isVisible = false;
|
||||
@ -154,7 +155,7 @@ class VersionHistoryStore {
|
||||
updatedVersions.unshift(newVersion);
|
||||
this.setVerHistoryFileVersions(updatedVersions);
|
||||
})
|
||||
.catch((e) => console.error(e))
|
||||
.catch((e) => toastr.error(e))
|
||||
.finally(() => {
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = null;
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"trailingComma":"all",
|
||||
"endOfLine": "crlf"
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-runtime",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
["styled-components", { "ssr": true }]
|
||||
]
|
||||
}
|
3
packages/login/.eslintrc.json
Normal file
3
packages/login/.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
1
packages/login/.gitattributes
vendored
1
packages/login/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
dist/* linguist-vendored=false
|
144
packages/login/.gitignore
vendored
144
packages/login/.gitignore
vendored
@ -1,123 +1,39 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
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
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# e2e test
|
||||
tests/reports
|
||||
tests/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
|
||||
# typescript
|
||||
*.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.*
|
||||
next-env.d.ts
|
||||
|
||||
|
||||
autoGeneratedTranslations.ts
|
||||
autoGeneratedTranslations.js
|
4
packages/login/.prettierrc.json
Normal file
4
packages/login/.prettierrc.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "auto"
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
const { setHeadlessWhen, setWindowSize } = require("@codeceptjs/configure");
|
||||
|
||||
// turn on headless mode when running with HEADLESS=true environment variable
|
||||
// export HEADLESS=true && npx codeceptjs run
|
||||
setHeadlessWhen(process.env.HEADLESS);
|
||||
|
||||
const sizes = {
|
||||
mobile: { width: 375, height: 667 },
|
||||
smallTablet: { width: 600, height: 667 },
|
||||
tablet: { width: 1023, height: 667 },
|
||||
desktop: { width: 1920, height: 1080 },
|
||||
};
|
||||
|
||||
const deviceType = process.env.DEVICE_TYPE || "desktop";
|
||||
|
||||
const device = sizes[deviceType];
|
||||
|
||||
setWindowSize(device.width, device.height);
|
||||
|
||||
const browser = process.env.profile || "chromium";
|
||||
|
||||
const isModel = !!process.env.MODEL;
|
||||
|
||||
const screenshotOutput = isModel
|
||||
? `./tests/screenshots/${browser}/${deviceType}`
|
||||
: `./tests/output/${browser}/${deviceType}`;
|
||||
|
||||
exports.config = {
|
||||
tests: "./tests/*_tests.js",
|
||||
output: screenshotOutput,
|
||||
helpers: {
|
||||
Playwright: {
|
||||
url: "http://localhost:8092",
|
||||
// show browser window
|
||||
show: false,
|
||||
browser: browser,
|
||||
// restart browser between tests
|
||||
restart: true,
|
||||
waitForNavigation: "networkidle0",
|
||||
// don't save screenshot on failure
|
||||
disableScreenshots: false,
|
||||
},
|
||||
ResembleHelper: {
|
||||
require: "codeceptjs-resemblehelper",
|
||||
screenshotFolder: "./tests/output/",
|
||||
baseFolder: `./tests/screenshots/${browser}/${deviceType}`,
|
||||
diffFolder: "./tests/output/diff/",
|
||||
},
|
||||
PlaywrightHelper: {
|
||||
require: "./tests/helpers/playwright.helper.js",
|
||||
},
|
||||
},
|
||||
include: {
|
||||
I: "./steps_file.js",
|
||||
},
|
||||
bootstrap: null,
|
||||
mocha: {
|
||||
reporterOptions: {
|
||||
mochawesome: {
|
||||
stdout: "-",
|
||||
options: {
|
||||
reportDir: `./tests/reports/${browser}/${deviceType}`,
|
||||
reportFilename: "report",
|
||||
},
|
||||
},
|
||||
"mocha-junit-reporter": {
|
||||
stdout: "-",
|
||||
options: {
|
||||
mochaFile: `./tests/reports/${browser}/${deviceType}/report.xml`,
|
||||
attachments: false, //add screenshot for a failed test
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
name: "ASC.Web.Login",
|
||||
plugins: {
|
||||
pauseOnFail: {},
|
||||
retryFailedStep: {
|
||||
enabled: true,
|
||||
},
|
||||
tryTo: {
|
||||
enabled: true,
|
||||
},
|
||||
screenshotOnFail: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
};
|
178
packages/login/index.d.ts
vendored
178
packages/login/index.d.ts
vendored
@ -24,174 +24,12 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { Request } from "express";
|
||||
|
||||
type WindowI18nType = {
|
||||
inLoad: object[];
|
||||
loaded: {
|
||||
[key: string]: {
|
||||
data: {
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
namespaces?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
authCallback?: (profile: string) => {};
|
||||
__ASC_INITIAL_LOGIN_STATE__: IInitialState;
|
||||
initialI18nStoreASC: IInitialI18nStoreASC;
|
||||
initialLanguage: string;
|
||||
i18n: WindowI18nType;
|
||||
[key: string]: object;
|
||||
}
|
||||
|
||||
type MatchType = {
|
||||
confirmedEmail?: string;
|
||||
message?: string;
|
||||
messageKey?: string;
|
||||
authError?: string;
|
||||
};
|
||||
|
||||
type PasswordHashType = {
|
||||
iterations: number;
|
||||
salt: string;
|
||||
size: number;
|
||||
};
|
||||
|
||||
type CaptchaPublicKeyType = string | undefined;
|
||||
|
||||
interface IEmailValid {
|
||||
value: string;
|
||||
isValid: boolean;
|
||||
errors: string[]; // TODO: check type
|
||||
}
|
||||
|
||||
interface IPortalSettings {
|
||||
culture: string;
|
||||
debugInfo: boolean;
|
||||
docSpace: boolean;
|
||||
enableAdmMess: boolean;
|
||||
enabledJoin: boolean;
|
||||
greetingSettings: string;
|
||||
ownerId: string;
|
||||
passwordHash: PasswordHashType;
|
||||
tenantAlias: string;
|
||||
tenantStatus: number;
|
||||
thirdpartyEnable: boolean;
|
||||
trustedDomainsType: number;
|
||||
utcHoursOffset: number;
|
||||
utcOffset: string;
|
||||
version: string;
|
||||
standalone: boolean;
|
||||
trustedDomains: string[];
|
||||
recaptchaPublicKey: CaptchaPublicKeyType;
|
||||
}
|
||||
|
||||
interface IBuildInfo {
|
||||
communityServer: string;
|
||||
documentServer: string;
|
||||
mailServer: string;
|
||||
}
|
||||
|
||||
interface IProvider {
|
||||
linked: boolean;
|
||||
provider: string;
|
||||
url: string;
|
||||
}
|
||||
type ProvidersType = IProvider[] | undefined;
|
||||
|
||||
interface ICapabilities {
|
||||
ldapEnabled: boolean;
|
||||
providers: string[];
|
||||
ssoLabel: string;
|
||||
ssoUrl: string;
|
||||
}
|
||||
|
||||
type TThemeObj = {
|
||||
accent: string;
|
||||
buttons: string;
|
||||
};
|
||||
|
||||
interface ITheme {
|
||||
id: number;
|
||||
main: TThemeObj;
|
||||
text: TThemeObj;
|
||||
name: string;
|
||||
}
|
||||
interface IThemes {
|
||||
limit: number;
|
||||
selected: number;
|
||||
themes: ITheme[];
|
||||
}
|
||||
|
||||
interface IError {
|
||||
status: number;
|
||||
standalone: boolean;
|
||||
message: string | undefined;
|
||||
}
|
||||
|
||||
interface ISSOSettings {
|
||||
hideAuthPage: boolean;
|
||||
}
|
||||
|
||||
interface IInitialState {
|
||||
portalSettings?: IPortalSettings;
|
||||
buildInfo?: IBuildInfo;
|
||||
providers?: ProvidersType;
|
||||
capabilities?: ICapabilities;
|
||||
match?: MatchType;
|
||||
currentColorScheme?: ITheme;
|
||||
ssoSettings?: ISSOSettings;
|
||||
logoUrls: ILogoUrl[];
|
||||
error?: IError;
|
||||
}
|
||||
|
||||
interface DevRequest {
|
||||
assets: assetsType;
|
||||
}
|
||||
var IS_DEVELOPMENT: boolean;
|
||||
var PORT: number;
|
||||
var IS_ROOMS_MODE: boolean;
|
||||
var BROWSER_DETECTOR_URL: string;
|
||||
var CONFIG_URL: string;
|
||||
|
||||
type assetsType = { [key: string]: string } | undefined;
|
||||
|
||||
interface IInitialI18nStoreASC extends Object {
|
||||
en: {
|
||||
[Common: string]: { [key: any]: string };
|
||||
[Login: string]: { [key: any]: string };
|
||||
};
|
||||
[key: string]: {
|
||||
[Common: string]: { [key: any]: string };
|
||||
[Login: string]: { [key: any]: string };
|
||||
};
|
||||
}
|
||||
|
||||
type HTMLElementEvent<T extends HTMLElement> = Event & {
|
||||
target: T;
|
||||
};
|
||||
|
||||
type TFuncType = (key: string) => string;
|
||||
|
||||
interface IParsedConfig extends Object {
|
||||
PORT: number;
|
||||
}
|
||||
interface ILoginRequest extends Request {
|
||||
i18n?: I18next;
|
||||
t?: TFuncType;
|
||||
}
|
||||
type timeoutType = ReturnType<typeof setTimeout>;
|
||||
interface IAcceptLanguage {
|
||||
code?: string;
|
||||
quality?: number;
|
||||
}
|
||||
|
||||
interface IUserTheme {
|
||||
[key: string]: string;
|
||||
isBase: boolean;
|
||||
}
|
||||
declare module "*.ico?url" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module "*.svg?url" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"components": ["@docspace/shared/components"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
115
packages/login/next.config.js
Normal file
115
packages/login/next.config.js
Normal file
@ -0,0 +1,115 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
|
||||
const path = require("path");
|
||||
const pkg = require("./package.json");
|
||||
|
||||
const nextConfig = {
|
||||
basePath: "/login",
|
||||
output: "standalone",
|
||||
compiler: {
|
||||
styledComponents: true,
|
||||
},
|
||||
generateBuildId: async () => {
|
||||
// This could be anything, using the latest git hash
|
||||
return `${pkg.name} - ${pkg.version} `;
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
typescript: {
|
||||
// !! WARN !!
|
||||
// Dangerously allow production builds to successfully complete even if
|
||||
// your project has type errors.
|
||||
// !! WARN !!
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
logging: {
|
||||
fetches: {
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
webpack(config) {
|
||||
// Grab the existing rule that handles SVG imports
|
||||
const fileLoaderRule = config.module.rules.find((rule) =>
|
||||
rule.test?.test?.(".svg"),
|
||||
);
|
||||
|
||||
const imageRule = config.module.rules.find(
|
||||
(rule) => rule.loader === "next-image-loader",
|
||||
);
|
||||
imageRule.resourceQuery = {
|
||||
not: [...fileLoaderRule.resourceQuery.not, /url/],
|
||||
};
|
||||
|
||||
config.module.rules.push(
|
||||
// Reapply the existing rule, but only for svg imports ending in ?url
|
||||
{
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
emit: false,
|
||||
filename: "static/chunks/[path][name][ext]?[hash]",
|
||||
},
|
||||
test: /\.(svg|png|jpe?g|gif|ico|woff2)$/i,
|
||||
resourceQuery: /url/, // *.svg?url
|
||||
},
|
||||
// Convert all other *.svg imports to React components
|
||||
{
|
||||
test: /\.svg$/i,
|
||||
issuer: fileLoaderRule.issuer,
|
||||
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
|
||||
|
||||
loader: "@svgr/webpack",
|
||||
options: {
|
||||
prettier: false,
|
||||
svgo: true,
|
||||
svgoConfig: {
|
||||
plugins: [
|
||||
{
|
||||
name: "preset-default",
|
||||
params: {
|
||||
overrides: { removeViewBox: false },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
titleProp: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Modify the file loader rule to ignore *.svg, since we have it handled now.
|
||||
fileLoaderRule.exclude = /\.svg$/i;
|
||||
|
||||
return config;
|
||||
},
|
||||
...nextConfig,
|
||||
};
|
@ -1,129 +1,36 @@
|
||||
{
|
||||
"name": "@docspace/login",
|
||||
"version": "2.5.1",
|
||||
"version": "2.5.0",
|
||||
"private": true,
|
||||
"homepage": "/login",
|
||||
"scripts": {
|
||||
"build": "yarn clean && yarn build:translations && yarn build:client && yarn build:server",
|
||||
"build:client": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --config webpack/webpack.client.js",
|
||||
"build:server": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --config webpack/webpack.server.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-rooms": "yarn clean && yarn build-rooms:client && yarn build-rooms-server",
|
||||
"build-rooms:client": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --env rooms=true --config webpack/webpack.client.js",
|
||||
"build-rooms:server": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production --env rooms=true --config webpack/webpack.server.js",
|
||||
"build-rooms:dev-server": "NODE_OPTIONS=--openssl-legacy-provider webpack --env rooms=true --config webpack/webpack.server.js",
|
||||
"build-rooms:dev-client": "NODE_OPTIONS=--openssl-legacy-provider webpack --env rooms=true --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-rooms": "yarn clean && npm-run-all --parallel start-rooms:client start-rooms:server start-rooms:common",
|
||||
"start-rooms:client": "NODE_OPTIONS=--openssl-legacy-provider webpack --env rooms=true --config webpack/webpack.client.js --watch --no-cache",
|
||||
"start-rooms:server": "NODE_OPTIONS=--openssl-legacy-provider webpack --env rooms=true --config webpack/webpack.server.js --watch --no-cache",
|
||||
"start-rooms:common": "yarn build-rooms:dev-client && yarn build-rooms:dev-server && 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/login && shx cp -r dist/* ../../../publish/web/login && shx cp -f src/server/config/config-deploy.json ../../../publish/web/login/config.json"
|
||||
"build": "node ./scripts/buildTranslations.js && next build",
|
||||
"start": "node ./scripts/buildTranslations.js && NODE_ENV=development node server.js",
|
||||
"start-prod": "NODE_ENV=production node server.js",
|
||||
"lint": "next lint",
|
||||
"clean": "shx rm -rf .next",
|
||||
"deploy": "shx --silent mkdir -p ../../../publish/web/login && shx --silent mkdir -p ../../../publish/web/login/.next && shx --silent mkdir -p ../../../publish/web/login/node_modules && shx --silent mkdir -p ../../../publish/web/login/.next/static && shx cp -r .next/standalone/node_modules/* ../../../publish/web/login/node_modules && shx cp -r .next/static/* ../../../publish/web/login/.next/static && shx cp -r .next/standalone/packages/login/.next/* ../../../publish/web/login/.next && shx cp -f server.prod.js ../../../publish/web/login/server.js"
|
||||
},
|
||||
"old-scripts": {
|
||||
"build:test": "NODE_OPTIONS=--openssl-legacy-provider webpack --env minimize=false --mode production",
|
||||
"build:test.translation": "NODE_OPTIONS=--openssl-legacy-provider webpack --env minimize=false hideText=true --mode production",
|
||||
"test:codeceptjs": "npx codeceptjs run --reporter mocha-multi",
|
||||
"test:mobile": "cross-env DEVICE_TYPE=mobile yarn test:codeceptjs",
|
||||
"test:smallTablet": "cross-env DEVICE_TYPE=smallTablet yarn test:codeceptjs",
|
||||
"test:tablet": "cross-env DEVICE_TYPE=tablet yarn test:codeceptjs",
|
||||
"test:desktop": "cross-env DEVICE_TYPE=desktop yarn test:codeceptjs ",
|
||||
"test:mobile:model": "cross-env DEVICE_TYPE=mobile MODEL=true yarn test:codeceptjs",
|
||||
"test:smallTablet:model": "cross-env DEVICE_TYPE=smallTablet MODEL=true yarn test:codeceptjs",
|
||||
"test:tablet:model": "cross-env DEVICE_TYPE=tablet MODEL=true yarn test:codeceptjs",
|
||||
"test:desktop:model": "cross-env DEVICE_TYPE=desktop MODEL=true yarn test:codeceptjs",
|
||||
"test:chromium:parallel": "run-p -c \"test:mobile --profile chromium \" \"test:smallTablet --profile chromium \" \"test:tablet --profile chromium \" \"test:desktop --profile chromium \" && yarn test:parse-xml",
|
||||
"test:chromium:sequential": "run-s -c \"test:mobile --profile chromium \" \"test:smallTablet --profile chromium \" \"test:tablet --profile chromium \" \"test:desktop --profile chromium \" && yarn test:parse-xml",
|
||||
"test:chromium:model": "run-s -c \"test:mobile:model --profile chromium \" \"test:smallTablet:model --profile chromium \" \"test:tablet:model --profile chromium \" \"test:desktop:model --profile chromium \" && yarn test:parse-xml",
|
||||
"test:firefox:parallel": "run-p -c \"test:mobile --profile firefox \" \"test:smallTablet --profile firefox \" \"test:tablet --profile firefox \" \"test:desktop --profile firefox \" && yarn test:parse-xml",
|
||||
"test:firefox:sequential": "run-s -c \"test:mobile --profile firefox \" \"test:smallTablet --profile firefox \" \"test:tablet --profile firefox \" \"test:desktop --profile firefox \" && yarn test:parse-xml",
|
||||
"test:firefox:model": "run-s -c \"test:mobile:model --profile firefox \" \"test:smallTablet:model --profile firefox \" \"test:tablet:model --profile firefox \" \"test:desktop:model --profile firefox \" && yarn test:parse-xml",
|
||||
"test:webkit:parallel": "run-p -c \"test:mobile --profile webkit \" \"test:smallTablet --profile webkit \" \"test:tablet --profile webkit \" \"test:desktop --profile webkit \" && yarn test:parse-xml",
|
||||
"test:webkit:sequential": "run-s -c \"test:mobile --profile webkit \" \"test:smallTablet --profile webkit \" \"test:tablet --profile webkit \" \"test:desktop --profile webkit \" && yarn test:parse-xml",
|
||||
"test:webkit:model": "run-s -c \"test:mobile:model --profile webkit \" \"test:smallTablet:model --profile webkit \" \"test:tablet:model --profile webkit \" \"test:desktop:model --profile webkit \" && yarn test:parse-xml",
|
||||
"test:parallel": "run-s -c test:chromium:parallel test:firefox:parallel test:webkit:parallel && yarn test:parse-xml",
|
||||
"test:sequential": "run-s -c test:chromium:sequential test:firefox:sequential test:webkit:sequential && yarn test:parse-xml",
|
||||
"test:model": "run-s -c test:chromium:model test:firefox:model test:webkit:model && yarn test:parse-xml",
|
||||
"test:parse-xml": "node tests/helpers/parserXML.js"
|
||||
"dependencies": {
|
||||
"i18next": "^20.6.1",
|
||||
"next": "14.0.4",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"react-i18next": "^13.2.1",
|
||||
"sass": "^1.59.3",
|
||||
"styled-components": "^5.3.9"
|
||||
},
|
||||
"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",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@types/accept-language-parser": "^1.5.3",
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/i18next-fs-backend": "^1.1.2",
|
||||
"@types/morgan": "^1.9.4",
|
||||
"@types/node": "^18.15.5",
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"@types/winston": "^2.4.4",
|
||||
"babel-loader": "^8.3.0",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^9.1.0",
|
||||
"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",
|
||||
"mocha": "^9.2.2",
|
||||
"mocha-junit-reporter": "^2.2.0",
|
||||
"mocha-multi": "^1.1.7",
|
||||
"mochawesome": "^7.1.3",
|
||||
"nodemon": "^2.0.22",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"playwright": "^1.32.0",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^12.6.0",
|
||||
"serve": "14.2.0",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"@types/react-google-recaptcha": "^2.1.9",
|
||||
"babel-plugin-styled-components": "^2.1.4",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.0.4",
|
||||
"prettier": "^3.2.4",
|
||||
"shx": "^0.3.4",
|
||||
"source-map-loader": "^3.0.2",
|
||||
"style-loader": "3.3.2",
|
||||
"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-manifest-plugin": "^5.0.0",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"title": "ONLYOFFICE",
|
||||
"socketPath": "/login/ws",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.297.0",
|
||||
"@types/ws": "^8.5.4",
|
||||
"aws-crt": "^1.15.13",
|
||||
"bufferutil": "^4.0.7",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"date-and-time": "^2.4.3",
|
||||
"express": "^4.18.2",
|
||||
"express-xss-sanitizer": "^1.1.6",
|
||||
"i18next-express-middleware": "^2.0.0",
|
||||
"i18next-fs-backend": "^1.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"morgan": "^1.10.0",
|
||||
"nconf": "^0.12.0",
|
||||
"react-google-recaptcha": "^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"
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<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" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="icon" type="image/x-icon" href="/logo.ashx?logotype=3" />
|
||||
<link rel="mask-icon" href="/logo.ashx?logotype=3" />
|
||||
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<!-- Tell the browser it's a PWA -->
|
||||
<!-- <meta name="mobile-web-app-capable" content="yes" /> -->
|
||||
<!-- Tell iOS it's a PWA -->
|
||||
<!-- <meta name="apple-mobile-web-app-capable" content="yes" /> -->
|
||||
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body ondragstart="return false">
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script>
|
||||
console.log("It's Login INIT");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "طلب التسجيل",
|
||||
"RegistrationEmailWatermark": "بريد إلكتروني",
|
||||
"RememberHelper": "العمر الافتراضي للجلسة هو 20 دقيقة. حدد هذا الخيار لتعيينه على عام واحد. لتعيين القيمة الخاصة بك ، انتقل إلى الإعدادات.",
|
||||
"ResendCode": "أعد إرسال الرمز",
|
||||
"UserIsAlreadyRegistered": "المستخدم <1>{{email}}</1> مسجل بالفعل في DocSpace، أدخل كلمة المرور الخاصة بك أو ارجع للمتابعة باستخدام بريد إلكتروني آخر."
|
||||
"ResendCode": "أعد إرسال الرمز"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Sorğunun qeydiyyatı",
|
||||
"RegistrationEmailWatermark": "Elektron poçt",
|
||||
"RememberHelper": "Susmaya görə sessiya müddəti 20 dəqiqədir. Müddəti 1 ilə uzatmaq üçün qutunu klikləyin. Digər müddəti təyin etmək üçün, Ayarlar bölməsinə keçin.",
|
||||
"ResendCode": "Kodu yenidən göndərin",
|
||||
"UserIsAlreadyRegistered": "<1>{{email}}</1> istifadəçisi artıq bu DocSpace-də qeydiyyatdan keçib, parolunuzu daxil edin və ya başqa e-poçtla davam etmək üçün geri qayıdın."
|
||||
"ResendCode": "Kodu yenidən göndərin"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Заявка за регистрация",
|
||||
"RegistrationEmailWatermark": "Имейл",
|
||||
"RememberHelper": "Продължителността на сесията по подразбиране е 20 минути. Проверете тази опция, за да я настроите за 1 година. За да зададете собствена стойност, отидете в Настройки.",
|
||||
"ResendCode": "Код за препращане",
|
||||
"UserIsAlreadyRegistered": "Потребителят <1>{{email}}</1> вече е регистриран в този DocSpace, въведете паролата си или се върнете, за да продължите с друг имейл."
|
||||
"ResendCode": "Код за препращане"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Žádost o registraci",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "Výchozí doba trvání relace je 20 minut. Zaškrtnutím této možnosti ji nastavíte na 1 rok. Chcete-li nastavit vlastní hodnotu, přejděte do Nastavení.",
|
||||
"ResendCode": "Opětovné zaslání kódu",
|
||||
"UserIsAlreadyRegistered": "Uživatel <1>{{email}}</1> je již v tomto DocSpace zaregistrován, zadejte své heslo nebo se vraťte zpět a pokračujte jiným e-mailem."
|
||||
"ResendCode": "Opětovné zaslání kódu"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Registrierungsanfrage",
|
||||
"RegistrationEmailWatermark": "E-Mail",
|
||||
"RememberHelper": "Lebensdauer der Sitzung ist standardmäßig 20 Minuten. Wählen Sie diese Option aus, um den Wert 1 Jahr zu setzen. Für benutzerdefinierte Werte öffnen Sie Einstellungen.",
|
||||
"ResendCode": "Code nochmals senden",
|
||||
"UserIsAlreadyRegistered": "Benutzer <1>{{email}}</1> ist bereits in diesem DocSpace registriert. Geben Sie Ihr Passwort ein oder gehen Sie zurück, um mit einer anderen E-Mail fortzufahren."
|
||||
"ResendCode": "Code nochmals senden"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Αίτημα εγγραφής",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "Η προεπιλεγμένη διάρκεια περιόδου λειτουργίας είναι 20 λεπτά. Ενεργοποιήστε αυτή την επιλογή για να την ορίσετε σε 1 έτος. Για να ορίσετε τη δική σας τιμή, μεταβείτε στις Ρυθμίσεις.",
|
||||
"ResendCode": "Επαναποστολή κωδικού",
|
||||
"UserIsAlreadyRegistered": "Ο χρήστης <1>{{email}}</1> είναι ήδη εγγεγραμμένος σε αυτό το DocSpace. Πληκτρολογήστε τον κωδικό πρόσβασής σας ή επιστρέψτε για να συνεχίσετε με άλλο email."
|
||||
"ResendCode": "Επαναποστολή κωδικού"
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"ErrorNotAllowedOption": "Your pricing plan does not support this option",
|
||||
"ErrorUserNotFound": "The user could not be found",
|
||||
"InvalidUsernameOrPassword": "Invalid username or password",
|
||||
"LoginWithAccountNotFound": "Can't find associated third-party account. You need to connect your social networking account at the profile editing page first.",
|
||||
"LoginWithAccountNotFound": "Can't find associated third-party account. You need to connect your social networking account at the profile editing page first.",
|
||||
"LoginWithBruteForce": "Authorization temporarily blocked",
|
||||
"LoginWithBruteForceCaptcha": "Confirm that you are not a robot",
|
||||
"RecaptchaInvalid": "Invalid Recaptcha",
|
||||
|
@ -8,7 +8,7 @@
|
||||
"InvalidCode": "This code is invalid. Try again.",
|
||||
"MessageAuthorize": "Log in to continue",
|
||||
"MessageEmailConfirmed": "Your email address was activated successfully.",
|
||||
"MessageSendPasswordRecoveryInstructionsOnEmail": "Please enter the email address you used for registration. The password recovery instructions will be sent to it.",
|
||||
"MessageSendPasswordRecoveryInstructionsOnEmail": "Please, enter the email address you used for registration. The password recovery instructions will be sent to it.",
|
||||
"NotFoundCode": "Can't find the code? Check your spam folder.",
|
||||
"PasswordRecoveryTitle": "Password recovery",
|
||||
"RecoverAccess": "Recover access",
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Solicitud de registro",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "La duración de la sesión por defecto es de 20 minutos. Marque esta opción para establecerla en 1 año. Para establecer su propio valor, vaya a Ajustes.",
|
||||
"ResendCode": "Reenviar código",
|
||||
"UserIsAlreadyRegistered": "El usuario <1>{{email}}</1> ya está registrado en este DocSpace, introduzca su contraseña o regrese para continuar con otro correo electrónico."
|
||||
"ResendCode": "Reenviar código"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Rekisteröintipyyntö",
|
||||
"RegistrationEmailWatermark": "sähköposti",
|
||||
"RememberHelper": "Istunnon oletuskesto on 20 minuuttia. Valitse tämä vaihtoehto, jos haluat asettaa sen 1 vuodeksi. Voit asettaa oman arvon Asetuksissa.",
|
||||
"ResendCode": "Lähetä koodi uudelleen",
|
||||
"UserIsAlreadyRegistered": "Käyttäjä <1>{{email}}</1> on jo rekisteröity tähän DocSpaceen, syötä salasanasi tai mene takaisin jatkaaksesi toisella sähköpostilla."
|
||||
"ResendCode": "Lähetä koodi uudelleen"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Demande d'inscription",
|
||||
"RegistrationEmailWatermark": "Adresse de courriel",
|
||||
"RememberHelper": "Par défaut, la durée de validité de la session est de 20 minutes. Cochez cette option pour la définir sur 1 an. Vous pouvez définir votre propre valeur en accédant aux paramètres.",
|
||||
"ResendCode": "Renvoyer le code",
|
||||
"UserIsAlreadyRegistered": "L'utilisateur <1>{{email}}</1> est déjà enregistré dans ce DocSpace, saisissez votre mot de passe ou revenez en arrière pour continuer avec un autre e-mail."
|
||||
"ResendCode": "Renvoyer le code"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Գրանցման հայցում",
|
||||
"RegistrationEmailWatermark": "Էլ․փոստ",
|
||||
"RememberHelper": "Նախնական աշխատաշրջանի աշխատաժամը 20 րոպե է: Նշեք այս տարբերակը՝ այն 1 տարի սահմանելու համար: Ձեր սեփական արժեքը սահմանելու համար անցեք Կարգավորումներ:",
|
||||
"ResendCode": "Կրկին ուղարկել կոդը",
|
||||
"UserIsAlreadyRegistered": "Օգտվող <1>{{email}}</1>-ն արդեն գրանցված է այս DocSpace-ում, մուտքագրեք ձեր գաղտնաբառը կամ վերադարձեք՝ շարունակելու մեկ այլ էլ։"
|
||||
"ResendCode": "Կրկին ուղարկել կոդը"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Richiesta di inscrizione ",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "La durata predefinita della sessione è di 20 minuti. Selezionare questa opzione per impostarla su 1 anno. Per impostare il proprio valore, passare a Impostazioni.",
|
||||
"ResendCode": "Invia nuovamente il codice",
|
||||
"UserIsAlreadyRegistered": "L'utente <1>{{email}}</1> è già registrato in questo DocSpace, inserisci la tua password o torna indietro per continuare con un'altra email."
|
||||
"ResendCode": "Invia nuovamente il codice"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "登録申請",
|
||||
"RegistrationEmailWatermark": "メール",
|
||||
"RememberHelper": "デフォルトのセッションライフタイムは20分です。このオプションをチェックすると、1年間に設定されます。独自の値を設定するには、「設定」で設定します。",
|
||||
"ResendCode": "コードの再送信",
|
||||
"UserIsAlreadyRegistered": "ユーザー<1>{{email}}</1>はすでにこのDocSpaceに登録されています。パスワードを入力するか、前に戻って別のメールアドレスでログインしてください。"
|
||||
"ResendCode": "コードの再送信"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "가입 요청",
|
||||
"RegistrationEmailWatermark": "이메일",
|
||||
"RememberHelper": "기본 세션 기간은 20분입니다. 1년으로 설정하려면 이 옵션을 확인하세요. 원하시는 값으로 설정하려면 설정으로 이동하세요.",
|
||||
"ResendCode": "코드 재전송",
|
||||
"UserIsAlreadyRegistered": "<1>{{email}}</1> 사용자는 이미 이 DocSpace에 등록되어 있습니다. 비밀번호를 입력하거나 돌아가서 다른 이메일로 계속 진행하세요."
|
||||
"ResendCode": "코드 재전송"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Reģistrācijas pieprasījums",
|
||||
"RegistrationEmailWatermark": "E-pasts",
|
||||
"RememberHelper": "Noklusējuma sesijas ilgums ir 20 minūtes. Atzīmējiet šo opciju, lai iestatītu to uz vienu gadu. Lai iestatītu savu vērtību, dodieties uz Iestatījumi.",
|
||||
"ResendCode": "Atkārtoti nosūtīt kodu",
|
||||
"UserIsAlreadyRegistered": "Lietotājs <1>{{email}}</1> jau ir reģistrēts šajā DocSpace, ievadiet savu paroli vai dodieties atpakaļ, lai turpinātu ar citu e-pasta adresi."
|
||||
"ResendCode": "Atkārtoti nosūtīt kodu"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Registratieverzoek",
|
||||
"RegistrationEmailWatermark": "E-mail",
|
||||
"RememberHelper": "De standaard sessieduur is 20 minuten. Vink deze optie aan om deze in te stellen op 1 jaar. Om uw eigen waarde in te stellen, ga naar Instellingen.",
|
||||
"ResendCode": "Code opnieuw versturen",
|
||||
"UserIsAlreadyRegistered": "Gebruiker <1>{{email}}</1> is al geregistreerd in deze DocSpace, voer uw wachtwoord in of ga terug om verder te gaan met een andere e-mail."
|
||||
"ResendCode": "Code opnieuw versturen"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Wniosek o rejestrację",
|
||||
"RegistrationEmailWatermark": "E-mail",
|
||||
"RememberHelper": "Domyślny czas trwania sesji to 20 min. Zaznacz tę opcję, aby ustawić go na 1 rok. Aby ustawić wartość niestandardową, przejdź do Ustawień.",
|
||||
"ResendCode": "Wyślij kod jeszcze raz",
|
||||
"UserIsAlreadyRegistered": "Użytkownik <1>{{email}}</1> jest już zarejestrowany w tym DocSpace, wpisz swoje hasło lub wróć, aby kontynuować z innym adresem e-mail."
|
||||
"ResendCode": "Wyślij kod jeszcze raz"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Pedido de registro",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "A duração padrão da sessão é de 20 minutos. Marque esta opção para defini-la como 1 ano. Para definir seu próprio valor, vá para Configurações",
|
||||
"ResendCode": "Reenviar código",
|
||||
"UserIsAlreadyRegistered": "O usuário <1>{{email}}</1> já está cadastrado neste DocSpace, digite sua senha ou volte para continuar com outro e-mail."
|
||||
"ResendCode": "Reenviar código"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Pedido de registo",
|
||||
"RegistrationEmailWatermark": "E-mail",
|
||||
"RememberHelper": "A duração da sessão predefinida é de 20 minutos. Clique nesta opção para configurá-la para 1 ano. Para introduzir um período à sua escolha, aceda às definições.",
|
||||
"ResendCode": "Reenviar código",
|
||||
"UserIsAlreadyRegistered": "O usuário <1>{{email}}</1> já está cadastrado neste DocSpace, digite sua senha ou volte para continuar com outro e-mail."
|
||||
"ResendCode": "Reenviar código"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Solicitarea de înregistrare",
|
||||
"RegistrationEmailWatermark": "E-mail",
|
||||
"RememberHelper": "Durata sesiunii implicită este de 20 de minute. Bifați caseta de selectare pentru a prelungi durata până la un an. Pentru stabilirea perioadei personalizate, accesați Setările.",
|
||||
"ResendCode": "Retrimite codul",
|
||||
"UserIsAlreadyRegistered": "Utilizatorul <1>{{email}}</1> este deja înregistrat în acest spațiu DocSpace, introduceţi parola dvs sau reveniți pentru a continua cu un alt e-mail."
|
||||
"ResendCode": "Retrimite codul"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Запрос на регистрацию",
|
||||
"RegistrationEmailWatermark": "Регистрационный email",
|
||||
"RememberHelper": "Время существования сессии по умолчанию составляет 20 минут. Отметьте эту опцию, чтобы установить значение 1 год. Чтобы задать собственное значение, перейдите в настройки.",
|
||||
"ResendCode": "Отправить код повторно",
|
||||
"UserIsAlreadyRegistered": "Пользователь <1>{{email}}</1> уже зарегистрирован в этом DocSpace. Введите свой пароль или вернитесь назад, чтобы продолжить с другим адресом электронной почты."
|
||||
"ResendCode": "Отправить код повторно"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Požiadavka registrácie",
|
||||
"RegistrationEmailWatermark": "E-mail",
|
||||
"RememberHelper": "Predvolená doba trvania relácie je 20 minút. Začiarknutím tejto možnosti ju nastavíte na 1 rok. Ak chcete nastaviť vlastnú hodnotu, prejdite do časti Nastavenia.",
|
||||
"ResendCode": "Poslať kód ešte raz",
|
||||
"UserIsAlreadyRegistered": "Používateľ <1>{{email}}</1> je už zaregistrovaný v tomto priestore DocSpace, zadajte svoje heslo alebo sa vráťte späť a pokračujte s iným e-mailom."
|
||||
"ResendCode": "Poslať kód ešte raz"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Zahteva za registracijo",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "Privzeta življenjska doba seje je 20 minut. Preverite to možnost, če jo želite nastaviti na 1 leto. Če želite nastaviti poljubno vrednost, pojdite v Nastavitve.",
|
||||
"ResendCode": "Ponovno pošlji kodo",
|
||||
"UserIsAlreadyRegistered": "Uporabnik <1>{{email}}</1> je že registriran v tem prostoru DocSpace. Vnesite svoje geslo ali se vrnite nazaj in nadaljujte z drugim e-mail naslovom."
|
||||
"ResendCode": "Ponovno pošlji kodo"
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"ErrorConfirmURLError": "Nevažeći email ili istekao link",
|
||||
"ErrorExpiredActivationLink": "Link je istekao",
|
||||
"ErrorInvalidActivationLink": "Nevažeći aktivacioni link",
|
||||
"ErrorNotAllowedOption": "Vaš cenovni plan ne podržava ovu opciju",
|
||||
"ErrorUserNotFound": "Korisnik nije pronađen",
|
||||
"InvalidUsernameOrPassword": "Nevažeće korisničko ime ili lozinka",
|
||||
"LoginWithAccountNotFound": "Ne mogu da pronađem povezani nalog treće strane. Prvo morate da povežete svoj nalog na društvenoj mreži na stranici za uređivanje profila.",
|
||||
"LoginWithBruteForce": "Ovlašćenje je privremeno blokirano",
|
||||
"LoginWithBruteForceCaptcha": "Potvrdi da nisi robot",
|
||||
"RecaptchaInvalid": "Nevažeći Recaptcha",
|
||||
"SsoAttributesNotFound": "Neuspela autentifikacija (atributi tvrdnje nisu pronađeni)",
|
||||
"SsoAuthFailed": "Autentifikacija neuspela",
|
||||
"SsoError": "Interna greška servera",
|
||||
"SsoSettingsCantCreateUser": "Nije moguće kreirati korisnika sa ovim autentifikacionim tokenom",
|
||||
"SsoSettingsDisabled": "Jedinstvena prijava (Single sign-on) je onemogućena",
|
||||
"SsoSettingsEmptyToken": "Autentifikacioni token nije pronađen",
|
||||
"SsoSettingsNotValidToken": "Nevažeći autentifikacioni token",
|
||||
"SsoSettingsUserTerminated": "Ovaj korisnik je onemogućen"
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"CodeSubtitle": "Poslali smo šestocifreni kod na {{email}}. Kod ima ograničen period važenja, pa ga unesite što je pre moguće.",
|
||||
"CodeTitle": "Kod vam je poslat email-om",
|
||||
"CookieSettingsTitle": "Trajanje sesije",
|
||||
"ErrorInvalidText": "Za 10 sekundi bićete preusmereni na <1>DocSpace</1>",
|
||||
"ExpiredCode": "Ovaj kod više ne važi. Zatražite novi kod i pokušajte ponovo.",
|
||||
"ForgotPassword": "Zaboravili ste vašu lozinku?",
|
||||
"InvalidCode": "Ovaj kod je nevažeći. Pokušajte ponovo.",
|
||||
"MessageAuthorize": "Prijavite se da biste nastavili",
|
||||
"MessageEmailConfirmed": "Vaša email adresa je uspešno aktivirana.",
|
||||
"MessageSendPasswordRecoveryInstructionsOnEmail": "Molim vas unesite email adresu koju ste koristili za registraciju. Uputstva za oporavak lozinke će tamo biti poslata.",
|
||||
"NotFoundCode": "Ne možete pronaći kod? Proverite vaš spam folder.",
|
||||
"PasswordRecoveryTitle": "Oporavak lozinke",
|
||||
"RecoverAccess": "Obnovi pristup",
|
||||
"RecoverContactEmailPlaceholder": "Kontakt email",
|
||||
"RecoverTextBody": "Ako ne možete da se prijavite sa svojim postojećim nalogom ili želite da se registrujete kao novi korisnik, kontaktirajte administratora portala.",
|
||||
"Register": "Registrujte se",
|
||||
"RegisterTextBodyAfterDomainsList": "Da biste se registrovali, unesite svoju email adresu i kliknite na Pošalji zahtev. Poruka sa linkom za aktivaciju vašeg naloga biće poslata na navedenu adresu.",
|
||||
"RegisterTextBodyBeforeDomainsList": "Registracija je dostupna korisnicima sa email nalogom na",
|
||||
"RegisterTitle": "Zahtev za registraciju",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "Podrazumevano trajanje sesije je 20 minuta. Označite ovu opciju da biste je postavili na 1 godinu. Da biste podesili sopstvenu vrednost, idite na Podešavanja.",
|
||||
"ResendCode": "Pošalji ponovo kod",
|
||||
"UserIsAlreadyRegistered": "Korisnik <1>{{email}}</1> je već registrovan u ovom DocSpace-u, unesite svoju lozinku ili se vratite da biste nastavili sa drugim email-om."
|
||||
}
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Kayıt talebi",
|
||||
"RegistrationEmailWatermark": "E-posta",
|
||||
"RememberHelper": "Varsayılan oturum ömrü 20 dakikadır. 1 yıla ayarlamak için bu seçeneği işaretleyin. Kendi sürenizi ayarlamak için Ayarlar'a gidin.",
|
||||
"ResendCode": "Kodu yeniden gönder",
|
||||
"UserIsAlreadyRegistered": "Kullanıcı <1>{{email}}</1> bu DocSpace'e zaten kayıtlı, şifrenizi girin veya başka bir e-posta ile devam etmek için geri dönün."
|
||||
"ResendCode": "Kodu yeniden gönder"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Запит на реєстрацію",
|
||||
"RegistrationEmailWatermark": "Електронна пошта",
|
||||
"RememberHelper": "Термін дії сеансу за замовчуванням складає 20 хвилин. Оберіть цей параметр, щоб задати для нього значення 1 рік. Щоб задати власне значення, перейдіть до налаштувань.",
|
||||
"ResendCode": "Надіслати код повторно",
|
||||
"UserIsAlreadyRegistered": "Користувач <1>{{email}}</1> вже зареєстрований у цьому просторі DocSpace. Введіть свій пароль або поверніться й продовжте з іншою адресою електронної пошти."
|
||||
"ResendCode": "Надіслати код повторно"
|
||||
}
|
||||
|
@ -20,6 +20,5 @@
|
||||
"RegisterTitle": "Yêu cầu đăng ký",
|
||||
"RegistrationEmailWatermark": "Email",
|
||||
"RememberHelper": "Thời lượng của phiên mặc định là 20 phút. Hãy chọn tùy chọn này để đặt thành 1 năm. Để đặt giá trị của riêng bạn, hãy đi đến Cài đặt.",
|
||||
"ResendCode": "Gửi lại mã",
|
||||
"UserIsAlreadyRegistered": "Người dùng <1>{{email}} </1> đã được đăng ký trong DocSpace này, hãy nhập mật khẩu của bạn hoặc quay lại để tiếp tục với một email khác."
|
||||
"ResendCode": "Gửi lại mã"
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user