Merge branch 'hotfix/v2.6.1' into feature/translations_v2.6

# Conflicts:
#	packages/client/public/locales/en/Translations.json
#	packages/client/public/locales/lo-LA/Settings.json
This commit is contained in:
Alexey Safronov 2024-08-01 18:08:40 +04:00
commit adc9d0c3db
95 changed files with 931 additions and 881 deletions

View File

@ -1,6 +1,6 @@
{
"name": "docspace",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"workspaces": {
"packages": [

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/client",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"homepage": "",
"scripts": {

View File

@ -114,7 +114,6 @@
"DownloadLog": "سجل التنزيل",
"DownloadReportBtnText": "تنزيل التقرير",
"DownloadReportDescription": "سيتم حفظ التقرير في المستندات",
"DownloadStatisticsText": "يمكنك تنزيل التقرير الخاص بالبيانات المتاحة خلال فترة التخزين المحددة لعرض الإحصائيات التفصيلية.",
"DuplicateNoun": "متكرر",
"EditColorScheme": "تحرير نظام الألوان",
"Employees": "المستخدمين",

View File

@ -112,7 +112,6 @@
"DownloadLog": "Gündəliyi endirin",
"DownloadReportBtnText": "Hesabatı yükləyin",
"DownloadReportDescription": "Hesabat Sənədlərdə saxlanacaq",
"DownloadStatisticsText": "Ətraflı statistikaya baxmaq üçün seçilmiş saxlama müddəti ərzində mövcud olan məlumat üçün hesabatı yükləyə bilərsiniz.",
"DuplicateNoun": "Dublikat edin",
"EditColorScheme": "Rəng sxemini redaktə edin",
"Employees": "istifadəçilər",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Дневник на изтеглянията",
"DownloadReportBtnText": "Изтегляне на доклад",
"DownloadReportDescription": "Отчетът ще бъде записан в Документи",
"DownloadStatisticsText": "Можете да изтеглите отчета за наличните данни през избрания период на съхранение, за да видите подробната статистика.",
"DuplicateNoun": "Дублирай",
"EditColorScheme": "Редактиране на цветовата схема",
"Employees": "потребители",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Stáhnout protokol",
"DownloadReportBtnText": "Stáhnout zprávu",
"DownloadReportDescription": "Zpráva se uloží do složky Dokumenty",
"DownloadStatisticsText": "Můžete si stáhnout zprávu pro data dostupná během vybraného období ukládání a zobrazit podrobné statistiky.",
"DuplicateNoun": "Duplikát",
"EditColorScheme": "Úprava barevného schématu",
"Employees": "uživatelé",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Log herunterladen",
"DownloadReportBtnText": "Bericht herunterladen",
"DownloadReportDescription": "Der Bericht wird unter Dateien gespeichert",
"DownloadStatisticsText": "Sie können den Bericht für die verfügbaren Daten während des ausgewählten Speicherzeitraums herunterladen, um die detaillierten Statistiken anzuzeigen.",
"DuplicateNoun": "Duplizieren",
"EditColorScheme": "Farbschema bearbeiten",
"Employees": "Benutzer",

View File

@ -111,7 +111,6 @@
"DownloadLog": "Λήψη αρχείου καταγραφής",
"DownloadReportBtnText": "Λήψη αναφοράς",
"DownloadReportDescription": "Η έκθεση θα αποθηκευτεί στα Έγγραφά",
"DownloadStatisticsText": "Μπορείτε να κατεβάσετε την αναφορά για τα δεδομένα που ήταν διαθέσιμα κατά την επιλεγμένη περίοδο αποθήκευσης για να δείτε τα λεπτομερή στατιστικά στοιχεία.",
"DuplicateNoun": "Διπλότυπο",
"EditColorScheme": "Επεξεργασία χρωμάτων",
"Employees": "χρήστες",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Download log",
"DownloadReportBtnText": "Download report",
"DownloadReportDescription": "The report will be saved to Documents",
"DownloadStatisticsText": "You can download the report for the data available during the selected storage period to view the detailed statistics.",
"DuplicateNoun": "Duplicate",
"EditColorScheme": "Edit color scheme",
"Employees": "users",

View File

@ -34,10 +34,13 @@
"RoleFormFiller": "Form filler",
"RoleFormFillerDescription": "Operations with existing files: viewing, form filling, reviewing, commenting.",
"RolePortalAdminDescription": "{{productName}} admins can access {{productName}} settings, manage and archive rooms, invite new users and assign roles below their level. All admins have access to the Documents section.",
"RoleFormFillerFormRoomDescription": "Form fillers can fill out forms and view only their completed/started forms within the Complete and In Process folders.",
"RolePowerUserDescription": "Power users can create and edit files in the room, but can't create rooms, manage users, or access settings.",
"RolePowerUserFormRoomDescription": "Power users can upload forms to the room and have full access to the Complete and In Process folders.",
"RoleReviewer": "Reviewer",
"RoleReviewerDescription": "Operations with existing files: viewing, reviewing, commenting.",
"RoleRoomAdminDescription": "Room admins can create and manage the assigned rooms, invite new users, and assign roles of room admin and lower. All admins have access to the Documents section.",
"RoleRoomAdminFormRoomDescription": "Room admins can create and manage rooms, invite new users and assign roles of room admin or lower. Room admins can upload forms to the room and have full access to the Complete and In Process folders.",
"RoleUserDescription": "Users can only access the rooms they are invited to by admins. They can't create own rooms, folders or files.",
"RoleViewer": "Viewer",
"RoleViewerDescription": "File viewing",

View File

@ -113,7 +113,6 @@
"DownloadLog": "Descargar registro",
"DownloadReportBtnText": "Descargar informe",
"DownloadReportDescription": "El informe se guardará en Documentos",
"DownloadStatisticsText": "Usted puede descargar el informe para los datos disponibles durante el período de almacenamiento seleccionado para ver estadísticas detalladas.",
"DuplicateNoun": "Duplicar",
"EditColorScheme": "Editar combinación de colores",
"Employees": "usuarios",

View File

@ -109,7 +109,6 @@
"DownloadLog": "Lataa loki",
"DownloadReportBtnText": "Lataa raportti",
"DownloadReportDescription": "Raportti tallennetaan Dokumentteihin",
"DownloadStatisticsText": "Voit ladata raportin valitun tallennusjakson aikana saatavilla olevista tiedoista nähdäksesi yksityiskohtaiset tilastot.",
"DuplicateNoun": "Kopioi",
"EditColorScheme": "Muokkaa värijärjestelmää",
"Employees": "Käyttäjät",

View File

@ -113,7 +113,6 @@
"DownloadLog": "Télécharger le journal",
"DownloadReportBtnText": "Télécharger le rapport",
"DownloadReportDescription": "Le rapport sera enregistré dans Documents",
"DownloadStatisticsText": "Vous pouvez télécharger un rapport des données accessibles pour la période de stockage sélectionnée pour voir les statistiques détaillées. ",
"DuplicateNoun": "Dupliquer",
"EditColorScheme": "Modifier le jeu de couleurs",
"Employees": "Utilisateurs",

View File

@ -112,7 +112,6 @@
"DownloadLog": "Ներբեռնման մատյան",
"DownloadReportBtnText": "Ներբեռնել զեկույցը",
"DownloadReportDescription": "Զեկույցը կպահվի Փաստաթղթերում",
"DownloadStatisticsText": "Դուք կարող եք ներբեռնել զեկույցը ընտրված պահպանման ժամանակահատվածում առկա տվյալների համար՝ մանրամասն վիճակագրությունը դիտելու համար:",
"DuplicateNoun": "Դուբլիկատ",
"EditColorScheme": "Խմբագրել գունավորումը",
"Employees": "Օգտվողներ",

View File

@ -113,7 +113,6 @@
"DownloadLog": "Scarica registro",
"DownloadReportBtnText": "Scarica il report",
"DownloadReportDescription": "Il report verrà salvato in Documenti",
"DownloadStatisticsText": "È possibile scaricare il report per i dati disponibili durante il periodo di archiviazione selezionato per visualizzare le statistiche dettagliate.",
"DuplicateNoun": "Duplica",
"EditColorScheme": "Modifica la combinazione di colori",
"Employees": "utenti",

View File

@ -111,7 +111,6 @@
"DownloadLog": "ダウンロードログ",
"DownloadReportBtnText": "ダウンロードのレポート",
"DownloadReportDescription": "レポートは「文書」に保存されます",
"DownloadStatisticsText": "選択した保存期間中に利用可能なデータのレポートをダウンロードして、詳細な統計情報を確認することができます。",
"DuplicateNoun": "複製",
"EditColorScheme": "カラースキームを編集する",
"Employees": "ユーザー",

View File

@ -113,7 +113,6 @@
"DownloadLog": "로그 다운로드",
"DownloadReportBtnText": "보고서 다운로드",
"DownloadReportDescription": "보고서가 문서에 저장됩니다",
"DownloadStatisticsText": "선택한 저장 기간 동안 이용 가능한 데이터에 대한 보고서를 다운로드하여 자세한 통계를 볼 수 있습니다.",
"DuplicateNoun": "복제",
"EditColorScheme": "색 구성표 편집",
"Employees": "사용자",

View File

@ -111,7 +111,6 @@
"DownloadLog": "ບັນທຶກການດາວໂຫຼດ",
"DownloadReportBtnText": "ດາວໂຫລດບົດລາຍງານ",
"DownloadReportDescription": "ບົດລາຍງານຈະຖືກບັນທຶກໄວ້ໃນເອກະສານຂອງຂ້ອຍ",
"DownloadStatisticsText": "ທ່ານສາມາດດາວໂຫລດບົດລາຍງານສໍາລັບຂໍ້ມູນທີ່ມີ ຢູ່ໃນໄລຍະເວລາການເກັບຮັກສາທີ່ເລືອກເພື່ອເບິ່ງສະຖິຕິລາຍລະອຽດ.",
"DuplicateNoun": "ຊໍ້າກັນ",
"EditColorScheme": "ແກ້ໄຂຮູບແບບສີ",
"Employees": "ຜຸ້ໃຊ້",

View File

@ -112,7 +112,6 @@
"DownloadLog": "Lejupielādēt žurnālu",
"DownloadReportBtnText": "Lejupielādēt pārskatu",
"DownloadReportDescription": "Atskaite tiks saglabāta mapē Dokumenti",
"DownloadStatisticsText": "Varat lejupielādēt pārskatu par datiem, kas pieejami atlasītajā uzglabāšanas periodā, lai skatītu detalizētu statistiku.",
"DuplicateNoun": "Dublicēt",
"EditColorScheme": "Rediģēt krāsu shēmu",
"Employees": "lietotāji",

View File

@ -113,7 +113,6 @@
"DownloadLog": "Download log",
"DownloadReportBtnText": "Download verslag",
"DownloadReportDescription": "Het verslag wordt opgeslagen in Documenten",
"DownloadStatisticsText": "U kunt het verslag downloaden voor de gegevens die beschikbaar zijn tijdens de geselecteerde opslagperiode om de gedetailleerde statistieken te bekijken.",
"DuplicateNoun": "Dupliceren",
"EditColorScheme": "Kleurenschema bewerken",
"Employees": "gebruikers",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Rejestr pobranych plików",
"DownloadReportBtnText": "Pobierz raport",
"DownloadReportDescription": "Raport zostanie zapisany w Dokumentach",
"DownloadStatisticsText": "Możesz pobrać raport dla danych dostępnych w wybranym okresie przechowywania, aby zobaczyć szczegółowe statystyki.",
"DuplicateNoun": "Duplikat",
"EditColorScheme": "Edytuj schemat kolorów",
"Employees": "użytkownicy",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Baixar registro",
"DownloadReportBtnText": "Baixar relatório",
"DownloadReportDescription": "O relatório será salvo em Documentos",
"DownloadStatisticsText": "Você pode baixar o relatório dos dados disponíveis durante o período de armazenamento selecionado para visualizar as estatísticas detalhadas.",
"DuplicateNoun": "Duplicado",
"EditColorScheme": "Editar esquema de cores",
"Employees": "Usuários",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Baixar registro",
"DownloadReportBtnText": "Transferir o relatório",
"DownloadReportDescription": "O relatório será guardado nos Documentos",
"DownloadStatisticsText": "Pode descarregar o relatório com os dados disponíveis durante o período de armazenamento selecionado para ver estatísticas detalhadas.",
"DuplicateNoun": "Duplicado",
"EditColorScheme": "Editar Esquema de Cores",
"Employees": "utilizadores",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Descărcare jurnal",
"DownloadReportBtnText": "Descărcare raport",
"DownloadReportDescription": "Raportul va fi salvat în Documentele",
"DownloadStatisticsText": "Puteţi descărca raportul pentru datele disponibile în perioada de stocare selectată pentru a vizualiza statisticile detaliate.",
"DuplicateNoun": "Dublare",
"EditColorScheme": "Editare schemă culori",
"Employees": "utilizatori",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Скачать журнал",
"DownloadReportBtnText": "Скачать отчет",
"DownloadReportDescription": "Отчет будет сохранен в \"Документы\"",
"DownloadStatisticsText": "Для просмотра подробной статистики вы можете скачать отчет по данным, доступным в течение выбранного периода хранения.",
"DuplicateNoun": "Дубликат",
"EditColorScheme": "Редактирование цветовой схемы",
"Employees": "Пользователи",

View File

@ -106,7 +106,6 @@
"DownloadLog": "සටහන බාගන්න",
"DownloadReportBtnText": "වාර්තාව බාගන්න",
"DownloadReportDescription": "ලේඛන වෙත වාර්තාව සුරැකෙනු ඇත",
"DownloadStatisticsText": "තෝරාගත් ආචයන පරාසයක පවතින දත්ත බාගැනීමෙන් සවිස්තරාත්මක සංඛ්‍යාලේඛන වාර්තාවක් බැලීමට හැකිය.",
"DuplicateNoun": "අනුපිටපතක්",
"EditColorScheme": "වත්මන් තේමාව සංස්කරණය",
"Employees": "පරිශ්‍රීලකයින්",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Stiahnuť log",
"DownloadReportBtnText": "Stiahnuť správu",
"DownloadReportDescription": "Správa sa uloží do priečinka Dokumenty",
"DownloadStatisticsText": "Ak chcete zobraziť podrobné štatistiky, môžete si stiahnuť správu o dátach dostupných pre zvolené obdobie uchovávania.",
"DuplicateNoun": "Duplikovať",
"EditColorScheme": "Upraviť farebnú schému",
"Employees": "užívatelia",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Dnevnik prenosa",
"DownloadReportBtnText": "Prenesi poročilo",
"DownloadReportDescription": "Poročilo bo shranjeno v Dokumenti",
"DownloadStatisticsText": "Za ogled podrobne statistike lahko prenesete poročilo za podatke, ki so na voljo v izbranem obdobju shranjevanja.",
"DuplicateNoun": "Podvoji",
"EditColorScheme": "Uredi barvno shemo",
"Employees": "uporabniki",

View File

@ -113,7 +113,6 @@
"DownloadLog": "Преузми лог",
"DownloadReportBtnText": "Преузми извештај",
"DownloadReportDescription": "Извештај ће бити сачуван у Документи",
"DownloadStatisticsText": "Можете преузети извештај за доступне податке током изабраног периода складиштења како бисте прегледали детаљну статистику.",
"DuplicateNoun": "Дуплицирај",
"EditColorScheme": "Уреди шему боја",
"Employees": "корисници",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Preuzmi log",
"DownloadReportBtnText": "Preuzmi izveštaj",
"DownloadReportDescription": "Izveštaj će biti sačuvan u Dokumenti",
"DownloadStatisticsText": "Možete preuzeti izveštaj za dostupne podatke tokom izabranog perioda skladištenja kako biste pregledali detaljnu statistiku.",
"DuplicateNoun": "Dupliciraj",
"EditColorScheme": "Uredi šemu boja",
"Employees": "korisnici",

View File

@ -114,7 +114,6 @@
"DownloadLog": "İndirme günlüğü",
"DownloadReportBtnText": "Raporu indir",
"DownloadReportDescription": "Rapor Belgeler'e kaydedilecek",
"DownloadStatisticsText": "Ayrıntılı istatistikleri görüntülemek için seçilen depolama süresi boyunca mevcut olan veriler için raporu indirebilirsiniz.",
"DuplicateNoun": "Yinelenen",
"EditColorScheme": "Renk düzenini düzenle",
"Employees": "kullanıcılar",

View File

@ -114,7 +114,6 @@
"DownloadLog": "Завантажити журнал",
"DownloadReportBtnText": "Завантажити звіт",
"DownloadReportDescription": "Звіт буде збережено в розділі «Документи»",
"DownloadStatisticsText": "Ви можете завантажити звіт із даними, доступними для вибраного періоду зберігання, щоб переглянути детальну статистику.",
"DuplicateNoun": "Дублікат",
"EditColorScheme": "Редагувати колірну схему",
"Employees": "користувачі",

View File

@ -112,7 +112,6 @@
"DownloadLog": "Tải log",
"DownloadReportBtnText": "Tải báo cáo xuống",
"DownloadReportDescription": "Báo cáo sẽ được lưu vào Tài liệu",
"DownloadStatisticsText": "Bạn có thể tải xuống báo cáo cho dữ liệu hữu dụng trong thời gian lưu trữ đã chọn để xem số liệu thống kê chi tiết.",
"DuplicateNoun": "Trùng lặp",
"EditColorScheme": "Chỉnh sửa bảng màu",
"Employees": "người dùng",

View File

@ -114,7 +114,6 @@
"DownloadLog": "下载日志",
"DownloadReportBtnText": "下载报告",
"DownloadReportDescription": "报告将被保存至“文档”",
"DownloadStatisticsText": "您可以下载所选存储期间可用数据的报告,以查看详细统计信息。",
"DuplicateNoun": "复制",
"EditColorScheme": "编辑配色方案",
"Employees": "用户",

View File

@ -44,6 +44,7 @@ import { CategoryType } from "SRC_DIR/helpers/constants";
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import { showProgress } from "@docspace/shared/utils/common";
import { openingNewTab } from "@docspace/shared/utils/openingNewTab";
const ArticleBodyContent = (props) => {
@ -105,6 +106,17 @@ const ArticleBodyContent = (props) => {
case myFolderId:
const myFilter = FilesFilter.getDefault();
myFilter.folder = folderId;
const filterStorageItem =
userId && localStorage.getItem(`UserFilter=${userId}`);
if (filterStorageItem) {
const splitFilter = filterStorageItem.split(",");
myFilter.sortBy = splitFilter[0];
myFilter.sortOrder = splitFilter[1];
}
params = myFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Personal);
@ -123,6 +135,17 @@ const ArticleBodyContent = (props) => {
case recycleBinFolderId:
const recycleBinFilter = FilesFilter.getDefault();
recycleBinFilter.folder = folderId;
const filterStorageTrash =
userId && localStorage.getItem(`UserFilterTrash=${userId}`);
if (filterStorageTrash) {
const splitFilterTrash = filterStorageTrash.split(",");
recycleBinFilter.sortBy = splitFilterTrash[0];
recycleBinFilter.sortOrder = splitFilterTrash[1];
}
params = recycleBinFilter.toUrlParams();
path = getCategoryUrl(CategoryType.Trash);
@ -165,6 +188,7 @@ const ArticleBodyContent = (props) => {
setSelection && setSelection([]);
setIsLoading(true, withTimer);
navigate(path, { state });
if (currentDeviceType === DeviceType.mobile) {
@ -292,6 +316,8 @@ export default inject(
const setIsLoading = (param, withTimer) => {
setIsSectionFilterLoading(param, withTimer);
if (param && withTimer) showProgress();
};
const { roomsFolderId, archiveFolderId, myFolderId, recycleBinFolderId } =

View File

@ -26,10 +26,9 @@
import React, { useMemo, useState, useCallback, useEffect } from "react";
import { useTranslation, Trans } from "react-i18next";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { toastr } from "@docspace/shared/components/toast";
import {
Events,
FilesSelectorFilterTypes,
@ -78,7 +77,6 @@ import FilesSelector from "../FilesSelector";
import LeaveRoomDialog from "../dialogs/LeaveRoomDialog";
import ChangeRoomOwnerPanel from "../panels/ChangeRoomOwnerPanel";
import { CreatedPDFFormDialog } from "../dialogs/CreatedPDFFormDialog";
import { PDFFormEditingDialog } from "../dialogs/PDFFormEditingDialog";
import { SharePDFFormDialog } from "../dialogs/SharePDFFormDialog";
import { FillPDFDialog } from "../dialogs/FillPDFDialog";
@ -141,13 +139,6 @@ const Panels = (props) => {
shareCollectSelector,
} = props;
const [createPDFFormFile, setCreatePDFFormFile] = useState({
visible: false,
file: null,
localKey: "",
onClose: null,
});
const [sharePDFForm, setSharePDFForm] = useState({
visible: false,
data: null,
@ -175,41 +166,6 @@ const Panels = (props) => {
return text[selectFileFormRoomFilterParam];
}, [selectFileFormRoomFilterParam, t]);
const handleCreatePDFFormFile = useCallback(
/**
* @param {CustomEvent} event
*/
(event) => {
const { file, show, localKey } = event.detail;
if (!show) {
return toastr.success(
<Trans
ns="PDFFormDialog"
i18nKey="PDFFormIsReadyToast"
components={{ 1: <strong /> }}
values={{ filename: file.title }}
/>,
);
}
setCreatePDFFormFile({
visible: true,
file,
localKey,
onClose: () => {
setCreatePDFFormFile({
visible: false,
onClose: null,
file: null,
localKey: "",
});
},
});
},
[],
);
const handleSharePDFForm = useCallback(
/**
* @param {CustomEvent} event
@ -229,20 +185,12 @@ const Panels = (props) => {
);
useEffect(() => {
window.addEventListener(
Events.CREATE_PDF_FORM_FILE,
handleCreatePDFFormFile,
);
window.addEventListener(Events.Share_PDF_Form, handleSharePDFForm);
return () => {
window.removeEventListener(
Events.CREATE_PDF_FORM_FILE,
handleCreatePDFFormFile,
);
window.removeEventListener(Events.Share_PDF_Form, handleSharePDFForm);
};
}, [handleCreatePDFFormFile, handleSharePDFForm]);
}, [handleSharePDFForm]);
return [
settingsPluginDialogVisible && (
@ -357,12 +305,6 @@ const Panels = (props) => {
<ChangeRoomOwnerPanel key="change-room-owner" />
),
shareFolderDialogVisible && <ShareFolderDialog key="share-folder-dialog" />,
createPDFFormFile.visible && (
<CreatedPDFFormDialog
key="created-pdf-form-dialog"
{...createPDFFormFile}
/>
),
pdfFormEditVisible && <PDFFormEditingDialog key="pdf-form-edit-dialog" />,
sharePDFForm.visible && (
<SharePDFFormDialog key="share-pdf-form-dialog" {...sharePDFForm} />

View File

@ -24,13 +24,14 @@
// 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 { useState, useRef } from "react";
import { useCallback, useState } from "react";
import { inject, observer } from "mobx-react";
import { useTranslation } from "react-i18next";
import { toastr } from "@docspace/shared/components/toast";
import { ChangeQuotaDialog } from "../dialogs";
let timerId = null;
const ChangeQuotaEvent = (props) => {
const {
@ -105,13 +106,13 @@ const ChangeQuotaEvent = (props) => {
onClose && onClose();
};
const onCloseClick = () => {
const onCloseClick = useCallback(() => {
timerId && clearTimeout(timerId);
timerId = null;
abortCallback && abortCallback();
onClose && onClose();
};
}, [onClose, abortCallback]);
return (
<ChangeQuotaDialog

View File

@ -24,12 +24,13 @@
// 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 { useState, useEffect, useCallback, useRef, memo } from "react";
import { useState, useEffect, useCallback, useRef } from "react";
import { Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import { FileAction } from "@docspace/shared/enums";
import { Events } from "@docspace/shared/enums";
import { toastr } from "@docspace/shared/components/toast";
import CreateEvent from "./CreateEvent";
import RenameEvent from "./RenameEvent";
@ -40,6 +41,8 @@ import EditGroupEvent from "./GroupEvents/EditGroupEvent";
import ChangeUserTypeEvent from "./ChangeUserTypeEvent";
import CreatePluginFile from "./CreatePluginFileEvent";
import ChangeQuotaEvent from "./ChangeQuotaEvent";
import { CreatedPDFFormDialog } from "../dialogs/CreatedPDFFormDialog";
const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
const [createDialogProps, setCreateDialogProps] = useState({
visible: false,
@ -98,6 +101,13 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
onClose: null,
});
const [createPDFFormFile, setCreatePDFFormFile] = useState({
visible: false,
file: null,
localKey: "",
onClose: null,
});
const eventHandlersList = useRef([]);
const onCreate = useCallback((e) => {
@ -236,6 +246,45 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
[enablePlugins],
);
const handleCreatePDFFormFile = useCallback(
/**
* @typedef {Object} DetailType
* @property {import("@docspace/shared/api/files/types").TFile} file
* @property {boolean} show
* @property {string} localKey
* @param {CustomEvent<DetailType>} event
*/
(event) => {
const { file, show, localKey } = event.detail;
if (!show) {
return toastr.success(
<Trans
ns="PDFFormDialog"
i18nKey="PDFFormIsReadyToast"
components={{ 1: <strong /> }}
values={{ filename: file.title }}
/>,
);
}
setCreatePDFFormFile({
visible: true,
file,
localKey,
onClose: () => {
setCreatePDFFormFile({
visible: false,
onClose: null,
file: null,
localKey: "",
});
},
});
},
[],
);
const onChangeQuota = useCallback((e) => {
const { payload } = e;
@ -261,6 +310,21 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
},
});
}, []);
useEffect(() => {
window.addEventListener(
Events.CREATE_PDF_FORM_FILE,
handleCreatePDFFormFile,
);
return () => {
window.removeEventListener(
Events.CREATE_PDF_FORM_FILE,
handleCreatePDFFormFile,
);
};
}, [handleCreatePDFFormFile]);
useEffect(() => {
window.addEventListener(Events.CREATE, onCreate);
window.addEventListener(Events.RENAME, onRename);
@ -360,6 +424,12 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
changeQuotaDialog.visible && (
<ChangeQuotaEvent key={Events.CHANGE_QUOTA} {...changeQuotaDialog} />
),
createPDFFormFile.visible && !createDialogProps.visible && (
<CreatedPDFFormDialog
key="created-pdf-form-dialog"
{...createPDFFormFile}
/>
),
];
};

View File

@ -66,7 +66,7 @@ const DeleteGroupDialog = (props) => {
if (hasMoreGroups) {
onDeleteAllGroups(t);
} else {
onDeleteGroup(t, bufferSelection?.id || selection[0].id);
onDeleteGroup(t, bufferSelection?.id || selection[0]?.id);
}
} catch (err) {
toastr.error(err.message);

View File

@ -30,4 +30,5 @@ export const Container = styled.div`
flex-direction: column;
gap: 16px;
margin-top: 16px;
`;

View File

@ -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 { useState, useEffect } from "react";
import { useState } from "react";
import { inject, observer } from "mobx-react";
import styled, { css } from "styled-components";
import { Aside } from "@docspace/shared/components/aside";
@ -83,20 +83,12 @@ const ChangeRoomOwner = (props) => {
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
document.addEventListener("keyup", onKeyUp, false);
return () => {
document.removeEventListener("keyup", onKeyUp, false);
};
}, []);
const onKeyUp = (e) => {
if (e.keyCode === 27) onClose();
if (e.keyCode === 13 || e.which === 13) onChangeRoomOwner();
};
const onChangeRoomOwner = async (user, isChecked) => {
const onChangeRoomOwner = async (
user,
selectedAccess,
newFooterInputValue,
isChecked,
) => {
if (showBackButton) {
setRoomParams && setRoomParams(user[0]);
} else {

View File

@ -34,7 +34,7 @@ import React, {
import { observer, inject } from "mobx-react";
import { withTranslation } from "react-i18next";
import { DeviceType } from "@docspace/shared/enums";
import { DeviceType, EmployeeType } from "@docspace/shared/enums";
import { LOADER_TIMEOUT } from "@docspace/shared/constants";
import { Backdrop } from "@docspace/shared/components/backdrop";
@ -72,11 +72,6 @@ const InvitePanel = ({
visible,
setRoomSecurity,
getRoomSecurityInfo,
getPortalInviteLinks,
userLink,
guestLink,
adminLink,
collaboratorLink,
defaultAccess,
inviteUsers,
setInfoPanelIsMobileHidden,
@ -88,9 +83,7 @@ const InvitePanel = ({
currentDeviceType,
}) => {
const [invitePanelIsLoding, setInvitePanelIsLoading] = useState(
() =>
((!userLink || !guestLink || !collaboratorLink) && !adminLink) ||
roomId !== -1,
roomId !== -1,
);
const [selectedRoom, setSelectedRoom] = useState(null);
const [hasErrors, setHasErrors] = useState(false);
@ -117,6 +110,33 @@ const InvitePanel = ({
setExternalLinksVisible(visible);
};
const accessModel = [
{
id: "user",
title: "User",
shareLink: "",
access: EmployeeType.User,
},
{
id: "guest",
title: "Guest",
shareLink: "",
access: EmployeeType.Guest,
},
{
id: "admin",
title: "Admin",
shareLink: "",
access: EmployeeType.Admin,
},
{
id: "collaborator",
title: "Collaborator",
shareLink: "",
access: EmployeeType.Collaborator,
},
];
const selectRoom = () => {
const room = folders.find((folder) => folder.id === roomId);
@ -167,40 +187,7 @@ const InvitePanel = ({
useEffect(() => {
if (roomId === -1) {
if ((!userLink || !guestLink || !collaboratorLink) && !adminLink) {
setInvitePanelIsLoading(true);
getPortalInviteLinks().finally(() => {
disableInvitePanelLoader();
});
}
setShareLinks([
{
id: "user",
title: "User",
shareLink: userLink,
access: 1,
},
{
id: "guest",
title: "Guest",
shareLink: guestLink,
access: 2,
},
{
id: "admin",
title: "Admin",
shareLink: adminLink,
access: 3,
},
{
id: "collaborator",
title: "Collaborator",
shareLink: collaboratorLink,
access: 4,
},
]);
setShareLinks(accessModel);
return;
}
@ -208,7 +195,7 @@ const InvitePanel = ({
Promise.all([selectRoom(), getInfo()]).finally(() => {
disableInvitePanelLoader(false);
});
}, [roomId, userLink, guestLink, adminLink, collaboratorLink]);
}, [roomId]);
useEffect(() => {
const hasErrors = inviteItems.some((item) => !!item.errors?.length);
@ -487,14 +474,6 @@ export default inject(
isRoomMembersPanelOpen,
} = infoPanelStore;
const {
getPortalInviteLinks,
userLink,
guestLink,
adminLink,
collaboratorLink,
} = peopleStore.inviteLinksStore;
const {
inviteItems,
invitePanelOptions,
@ -520,11 +499,6 @@ export default inject(
visible: invitePanelOptions.visible,
defaultAccess: invitePanelOptions.defaultAccess,
getFolderInfo,
getPortalInviteLinks,
userLink,
guestLink,
adminLink,
collaboratorLink,
inviteUsers,
setInfoPanelIsMobileHidden,
updateInfoPanelMembers,

View File

@ -64,20 +64,26 @@ const ExternalLinks = ({
setActiveLink,
activeLink,
isMobileView,
getPortalInviteLink,
}) => {
const [actionLinksVisible, setActionLinksVisible] = useState(false);
const inputsRef = useRef();
const toggleLinks = () => {
const toggleLinks = async (e) => {
if (roomId === -1) {
const link = shareLinks.find((l) => l.access === +defaultAccess);
if (e?.target?.checked) {
const link = shareLinks.find((l) => l.access === defaultAccess);
setActiveLink(link);
copyLink(link.shareLink);
link.shareLink = await getPortalInviteLink(defaultAccess);
setActiveLink(link);
copyLink(link.shareLink);
}
} else {
!externalLinksVisible ? editLink() : disableLink();
}
onChangeExternalLinksVisible(!externalLinksVisible);
};
@ -106,11 +112,13 @@ const ExternalLinks = ({
setActiveLink(activeLink);
};
const onSelectAccess = (access) => {
const onSelectAccess = async (access) => {
let link = null;
if (roomId === -1) {
link = shareLinks.find((l) => l.access === access.access);
link.shareLink = await getPortalInviteLink(access.access);
setActiveLink(link);
} else {
setInvitationLinks(roomId, "Invite", +access.access, shareLinks[0].id);
@ -254,17 +262,21 @@ const ExternalLinks = ({
);
};
export default inject(({ userStore, dialogsStore, filesStore }) => {
const { isOwner } = userStore.user;
const { invitePanelOptions } = dialogsStore;
const { setInvitationLinks } = filesStore;
const { roomId, hideSelector, defaultAccess } = invitePanelOptions;
export default inject(
({ userStore, dialogsStore, filesStore, peopleStore }) => {
const { isOwner } = userStore.user;
const { invitePanelOptions } = dialogsStore;
const { setInvitationLinks } = filesStore;
const { roomId, hideSelector, defaultAccess } = invitePanelOptions;
const { getPortalInviteLink } = peopleStore.inviteLinksStore;
return {
setInvitationLinks,
roomId,
hideSelector,
defaultAccess,
isOwner,
};
})(observer(ExternalLinks));
return {
setInvitationLinks,
roomId,
hideSelector,
defaultAccess,
isOwner,
getPortalInviteLink,
};
},
)(observer(ExternalLinks));

View File

@ -31,6 +31,50 @@ import {
} from "@docspace/shared/enums";
import { checkIfAccessPaid } from "SRC_DIR/helpers";
/**
* @param {RoomsType} roomType
* @param {(key: string) => string} t
* @returns {string}
*/
const getRoomAdminDescription = (roomType, t) => {
switch (roomType) {
case RoomsType.FormRoom:
return t("Translations:RoleRoomAdminFormRoomDescription");
default:
return t("Translations:RoleRoomAdminDescription");
}
};
/**
* @param {RoomsType} roomType
* @param {(key: string)=> string} t
* @returns {string}
*/
const getPowerUserDescription = (roomType, t) => {
switch (roomType) {
case RoomsType.FormRoom:
return t("Translations:RolePowerUserFormRoomDescription");
default:
return t("Translations:RolePowerUserDescription");
}
};
/**
* @param {RoomsType} roomType
* @param {(key: string)=> string} t
* @returns {string}
*/
const getFormFillerDescription = (roomType, t) => {
switch (roomType) {
case RoomsType.FormRoom:
return t("Translations:RoleFormFillerFormRoomDescription");
default:
return t("Translations:RoleFormFillerDescription");
}
};
export const getAccessOptions = (
t,
roomType = RoomsType.CustomRoom,
@ -56,7 +100,7 @@ export const getAccessOptions = (
roomAdmin: {
key: "roomAdmin",
label: t("Common:RoomAdmin"),
description: t("Translations:RoleRoomAdminDescription"),
description: getRoomAdminDescription(roomType, t),
...(!standalone && { quota: t("Common:Paid") }),
color: "#EDC409",
access:
@ -66,7 +110,7 @@ export const getAccessOptions = (
collaborator: {
key: "collaborator",
label: t("Common:PowerUser"),
description: t("Translations:RolePowerUserDescription"),
description: getPowerUserDescription(roomType, t),
...(!standalone && { quota: t("Common:Paid") }),
color: "#EDC409",
access:
@ -92,7 +136,7 @@ export const getAccessOptions = (
formFiller: {
key: "formFiller",
label: t("Translations:RoleFormFiller"),
description: t("Translations:RoleFormFillerDescription"),
description: getFormFillerDescription(roomType, t),
access: ShareAccessRights.FormFilling,
type: "user",
},

View File

@ -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 ClearActiveReactSvgUrl from "PUBLIC_DIR/images/clear.active.react.svg?url";
import ClearReactSvgUrl from "PUBLIC_DIR/images/clear.react.svg?url";
import ButtonCancelReactSvgUrl from "PUBLIC_DIR/images/button.cancel.react.svg?url";
import React from "react";
@ -136,8 +136,8 @@ class UploadPanelComponent extends React.Component {
<div>
{uploaded && converted ? (
<IconButton
size="20"
iconName={ClearActiveReactSvgUrl}
size={17}
iconName={ClearReactSvgUrl}
isClickable
onClick={this.clearUploadPanel}
/>

View File

@ -0,0 +1,27 @@
import { getLanguage } from "@docspace/shared/utils";
import { translations } from "./autoGeneratedTranslations";
export function loadLanguagePath(homepage, fixedNS = null) {
return (lng, ns) => {
const language = getLanguage(lng instanceof Array ? lng[0] : lng);
const lngCollection = translations?.get(language);
const data = lngCollection?.get(`${fixedNS || ns}`);
if (!data) return `/locales/${language}/${fixedNS || ns}.json`;
let path = data?.split("/");
const length = path?.length;
const isCommonPath = path[length - 1].indexOf("Common") > -1;
path = `/${path[length - 3]}/${path[length - 2]}/${path[length - 1]}`;
if (ns.length > 0 && ns[0] === "Common" && isCommonPath) {
return `/static${path}`;
}
return path;
};
}

View File

@ -25,12 +25,10 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { authStore } from "@docspace/shared/store";
import { getLanguage } from "@docspace/shared/utils";
import { toCommunityHostname } from "@docspace/shared/utils/common";
import { CategoryType } from "./constants";
import { FolderType, ShareAccessRights } from "@docspace/shared/enums";
import { translations } from "./autoGeneratedTranslations";
import { FolderType } from "@docspace/shared/enums";
// import router from "SRC_DIR/router";
import i18n from "../i18n";
@ -54,31 +52,6 @@ export const setDocumentTitle = (subTitle = "") => {
document.title = title;
};
export function loadLanguagePath(homepage, fixedNS = null) {
return (lng, ns) => {
const language = getLanguage(lng instanceof Array ? lng[0] : lng);
const lngCollection = translations?.get(language);
const data = lngCollection?.get(`${fixedNS || ns}`);
if (!data) return `/locales/${language}/${fixedNS || ns}.json`;
let path = data?.split("/");
const length = path?.length;
const isCommonPath = path[length - 1].indexOf("Common") > -1;
path = `/${path[length - 3]}/${path[length - 2]}/${path[length - 1]}`;
if (ns.length > 0 && ns[0] === "Common" && isCommonPath) {
return `/static${path}`;
}
return path;
};
}
export const checkIfModuleOld = (link) => {
if (
!link ||

View File

@ -31,7 +31,7 @@ import config from "PACKAGE_FILE";
import { LANGUAGE } from "@docspace/shared/constants";
import { getCookie } from "@docspace/shared/utils";
import { loadLanguagePath } from "./helpers/utils";
import { loadLanguagePath } from "./helpers/language-helpers";
const newInstance = i18n.createInstance();

View File

@ -32,7 +32,7 @@ import FilesFilter from "@docspace/shared/api/files/filter";
import RoomsFilter from "@docspace/shared/api/rooms/filter";
import { getGroup } from "@docspace/shared/api/groups";
import { getUserById } from "@docspace/shared/api/people";
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
import { CREATED_FORM_KEY, MEDIA_VIEW_URL } from "@docspace/shared/constants";
import {
Events,
@ -78,6 +78,7 @@ const useFiles = ({
scrollToTop,
selectedFolderStore,
wsCreatedPDFForm,
}) => {
const navigate = useNavigate();
const { id } = useParams();
@ -292,7 +293,15 @@ const useFiles = ({
);
} else {
const folderId = filter.folder;
return fetchFiles(folderId, filter);
return fetchFiles(folderId, filter)?.finally(() => {
const data = sessionStorage.getItem(CREATED_FORM_KEY);
if (data) {
wsCreatedPDFForm({
data,
});
sessionStorage.removeItem(CREATED_FORM_KEY);
}
});
}
}
@ -306,7 +315,7 @@ const useFiles = ({
const isFormRoom =
selectedFolderStore.roomType === RoomsType.FormRoom ||
selectedFolderStore.type === FolderType.FormRoom;
selectedFolderStore.parentRoomType === FolderType.FormRoom;
const payload = {
extension: "pdf",

View File

@ -54,23 +54,23 @@ const HistoryMainTextFolderInfo = ({
if (!parentTitle) return null;
const isParentType = parentType === 0;
const isFromParentType = fromParentType === 0;
const isFolder = parentType === 0;
const isFromFolder = fromParentType === 0;
const destination = isParentType
? t("FeedLocationRoomLabel", { folderTitle: parentTitle })
: t("FeedLocationLabel", { folderTitle: parentTitle });
const destination = isFolder
? t("FeedLocationLabel", { folderTitle: parentTitle })
: t("FeedLocationRoomLabel", { folderTitle: parentTitle });
const sourceDestination = isFromParentType
const sourceDestination = isFromFolder
? t("FeedLocationLabelFrom", { folderTitle: fromParentTitle })
: t("FeedLocationRoomLabel", { folderTitle: parentTitle });
const className = !isFromParentType ? "folder-label" : "source-folder-label";
const className = isFromFolder ? "source-folder-label" : "folder-label";
return (
<StyledHistoryBlockMessage className="message">
<span className={className}>
{!isFromParentType ? destination : sourceDestination}
{isFromFolder ? sourceDestination : destination}
</span>
</StyledHistoryBlockMessage>
);

View File

@ -114,7 +114,7 @@ export default inject<TStore>(({ dialogsStore, infoPanelStore }) => {
const { infoPanelSelection } = infoPanelStore;
const { setLinkParams, setEditLinkPanelIsVisible } = dialogsStore;
const { id, roomType, security } = infoPanelSelection!;
const { EditRoom } = security!;
const { EditRoom } = security || {};
const isFormRoom = roomType === RoomsType.FormRoom;

View File

@ -61,6 +61,8 @@ class GroupsTableHeader extends React.Component {
];
const columns = props.getColumns(defaultColumns);
const tableColumns = columns.map((c) => c.enable && c.key);
this.setTableColumns(tableColumns);
this.state = { columns };
}
@ -77,7 +79,7 @@ class GroupsTableHeader extends React.Component {
this.setState({ columns });
const tableColumns = columns.map((c) => c.enable && c.key);
localStorage.setItem(`${TABLE_COLUMNS}=${this.props.userId}`, tableColumns);
this.setTableColumns(tableColumns);
const event = new Event(Events.CHANGE_COLUMN);
window.dispatchEvent(event);
@ -103,6 +105,10 @@ class GroupsTableHeader extends React.Component {
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
setTableColumns = (tableColumns) => {
localStorage.setItem(`${TABLE_COLUMNS}=${this.props.userId}`, tableColumns);
};
render() {
const { columns } = this.state;
const {

View File

@ -102,6 +102,8 @@ class InsideGroupTableHeader extends React.Component {
});
const columns = props.getColumns(defaultColumns);
const tableColumns = columns.map((c) => c.enable && c.key);
this.setTableColumns(tableColumns);
this.state = { columns };
}
@ -118,7 +120,7 @@ class InsideGroupTableHeader extends React.Component {
this.setState({ columns });
const tableColumns = columns.map((c) => c.enable && c.key);
localStorage.setItem(`${TABLE_COLUMNS}=${this.props.userId}`, tableColumns);
this.setTableColumns(tableColumns);
const event = new Event(Events.CHANGE_COLUMN);
@ -156,6 +158,10 @@ class InsideGroupTableHeader extends React.Component {
navigate(`${location.pathname}?${newFilter.toUrlParams()}`);
};
setTableColumns = (tableColumns) => {
localStorage.setItem(`${TABLE_COLUMNS}=${this.props.userId}`, tableColumns);
};
render() {
const { columns } = this.state;
const {

View File

@ -54,6 +54,8 @@ class FilesTableHeader extends React.Component {
showStorageInfo,
isArchiveFolder,
tableStorageName,
roomsFilter,
filter,
} = this.props;
const defaultColumns = [];
@ -365,6 +367,9 @@ class FilesTableHeader extends React.Component {
const tableColumns = columns.map((c) => c.enable && c.key);
const sortBy = isRooms ? roomsFilter.sortBy : filter.sortBy;
const sortOrder = isRooms ? roomsFilter.sortOrder : filter.sortOrder;
this.setTableColumns(tableColumns);
if (fromUpdate) {
this.setState({
@ -372,6 +377,8 @@ class FilesTableHeader extends React.Component {
resetColumnsSize,
columnStorageName,
columnInfoPanelStorageName,
sortBy,
sortOrder,
});
} else {
this.state = {
@ -379,6 +386,8 @@ class FilesTableHeader extends React.Component {
resetColumnsSize,
columnStorageName,
columnInfoPanelStorageName,
sortBy,
sortOrder,
};
}
};
@ -425,8 +434,13 @@ class FilesTableHeader extends React.Component {
isRecentTab,
isArchiveFolder,
showStorageInfo,
roomsFilter,
filter,
} = this.props;
const sortBy = isRooms ? roomsFilter.sortBy : filter.sortBy;
const sortOrder = isRooms ? roomsFilter.sortOrder : filter.sortOrder;
if (
isArchiveFolder !== prevProps.isArchiveFolder ||
isRooms !== prevProps.isRooms ||
@ -434,12 +448,15 @@ class FilesTableHeader extends React.Component {
columnStorageName !== prevProps.columnStorageName ||
columnInfoPanelStorageName !== prevProps.columnInfoPanelStorageName ||
isRecentTab !== prevProps.isRecentTab ||
showStorageInfo !== prevProps.showStorageInfo
showStorageInfo !== prevProps.showStorageInfo ||
sortBy !== this.state.sortBy ||
sortOrder !== this.state.sortOrder
) {
return this.getTableColumns(true);
}
const { columns } = this.state;
if (this.props.withContent !== prevProps.withContent) {
const columnIndex = columns.findIndex((c) => c.key === "Share");
if (columnIndex === -1) return;
@ -528,9 +545,6 @@ class FilesTableHeader extends React.Component {
t,
containerRef,
isHeaderChecked,
filter,
roomsFilter,
isRooms,
firstElemChecked,
sortingVisible,
infoPanelVisible,
@ -547,11 +561,10 @@ class FilesTableHeader extends React.Component {
resetColumnsSize,
columnStorageName,
columnInfoPanelStorageName,
sortBy,
sortOrder,
} = this.state;
const sortBy = isRooms ? roomsFilter.sortBy : filter.sortBy;
const sortOrder = isRooms ? roomsFilter.sortOrder : filter.sortOrder;
return (
<TableHeader
isLengthenHeader={firstElemChecked || isHeaderChecked}

View File

@ -2012,42 +2012,8 @@ const SectionFilterContent = ({
hideableColumns.Storage = storage;
}
options.push(firstName, lastName);
if (accountsViewAs === "table") {
const tableColumns = isInsideGroup
? TABLE_INSIDE_GROUP_COLUMNS
: TABLE_PEOPLE_COLUMNS;
const columnsSizeInfoPanel = isInsideGroup
? COLUMNS_INSIDE_GROUP_SIZE_INFO_PANEL
: COLUMNS_PEOPLE_SIZE_INFO_PANEL;
const availableSort = localStorage
?.getItem(`${tableColumns}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${columnsSizeInfoPanel}=${userId}`)
?.split(" ");
availableSort?.forEach((columnTitle) => {
if (!hideableColumns[columnTitle]) return;
if (availableSort?.includes(columnTitle)) {
const idx = availableSort.findIndex((x) => x === columnTitle);
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && options.push(hideableColumns[columnTitle]);
}
});
} else {
options.push(type, department, email);
if (showStorageInfo) options.push(storage);
}
options.push(firstName, lastName, type, department, email);
if (showStorageInfo) options.push(storage);
return options;
}
@ -2069,29 +2035,7 @@ const SectionFilterContent = ({
default: true,
};
groupsOptions.push(title);
if (accountsViewAs === "table") {
const availableSort = localStorage
?.getItem(`${TABLE_GROUPS_COLUMNS}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${COLUMNS_GROUPS_SIZE_INFO_PANEL}=${userId}`)
?.split(" ");
if (availableSort?.includes("Head of Group")) {
const idx = availableSort.findIndex((x) => x === "Head of Group");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && groupsOptions.push(manager);
}
} else {
groupsOptions.push(manager);
}
groupsOptions.push(title, manager);
return groupsOptions;
}
@ -2181,220 +2125,25 @@ const SectionFilterContent = ({
commonOptions.push(name);
if (viewAs === "table") {
if (isRooms) {
const availableSort = localStorage
?.getItem(`${TABLE_ROOMS_COLUMNS}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${COLUMNS_ROOMS_SIZE_INFO_PANEL}=${userId}`)
?.split(" ");
const hideOption = infoPanelVisible && infoPanelColumnsSize;
if (availableSort?.includes("Type")) {
const idx = availableSort.findIndex((x) => x === "Type");
const hide = hideOption && infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(roomType);
}
if (availableSort?.includes("Tags")) {
const idx = availableSort.findIndex((x) => x === "Tags");
const hide = hideOption && infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(tags);
}
if (availableSort?.includes("Owner")) {
const idx = availableSort.findIndex((x) => x === "Owner");
const hide = hideOption && infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(owner);
}
if (availableSort?.includes("Activity")) {
const idx = availableSort.findIndex((x) => x === "Activity");
const hide = hideOption && infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(modifiedDate);
}
if (showStorageInfo && availableSort?.includes("Storage")) {
const idx = availableSort.findIndex(
(x) => x === SortByFieldName.UsedSpace,
);
const hide = hideOption && infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(sortByStorage);
}
} else if (isTrash) {
const availableSort = localStorage
?.getItem(`${TABLE_TRASH_COLUMNS}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${COLUMNS_TRASH_SIZE_INFO_PANEL}=${userId}`)
?.split(" ");
if (availableSort?.includes("Room")) {
const idx = availableSort.findIndex((x) => x === "Room");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(room);
}
if (availableSort?.includes("AuthorTrash")) {
const idx = availableSort.findIndex((x) => x === "AuthorTrash");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(authorOption);
}
if (availableSort?.includes("CreatedTrash")) {
const idx = availableSort.findIndex((x) => x === "CreatedTrash");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(creationDate);
}
if (availableSort?.includes("Erasure")) {
const idx = availableSort.findIndex((x) => x === "Erasure");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(erasure);
}
if (availableSort?.includes("SizeTrash")) {
const idx = availableSort.findIndex((x) => x === "SizeTrash");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(size);
}
if (availableSort?.includes("TypeTrash")) {
const idx = availableSort.findIndex((x) => x === "TypeTrash");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(type);
}
} else if (isRecentTab) {
const availableSort = localStorage
?.getItem(`${TABLE_RECENT_COLUMNS}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${COLUMNS_RECENT_SIZE_INFO_PANEL}=${userId}`)
?.split(" ");
if (availableSort?.includes("LastOpened")) {
const idx = availableSort.findIndex((x) => x === "LastOpened");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(lastOpenedDate);
}
if (availableSort?.includes("Size")) {
const idx = availableSort.findIndex((x) => x === "Size");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(size);
}
} else {
const availableSort = localStorage
?.getItem(`${TABLE_COLUMNS}=${userId}`)
?.split(",");
const infoPanelColumnsSize = localStorage
?.getItem(`${COLUMNS_SIZE_INFO_PANEL}=${userId}`)
?.split(" ");
if (availableSort?.includes("Author")) {
const idx = availableSort.findIndex((x) => x === "Author");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(authorOption);
}
if (availableSort?.includes("Created")) {
const idx = availableSort.findIndex((x) => x === "Created");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(creationDate);
}
if (availableSort?.includes("Modified")) {
const idx = availableSort.findIndex((x) => x === "Modified");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(modifiedDate);
}
if (availableSort?.includes("Size")) {
const idx = availableSort.findIndex((x) => x === "Size");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
!hide && commonOptions.push(size);
}
if (availableSort?.includes("Type")) {
const idx = availableSort.findIndex((x) => x === "Type");
const hide =
infoPanelVisible &&
infoPanelColumnsSize &&
infoPanelColumnsSize[idx] === "0px";
// !hide && commonOptions.push(type);
}
}
if (isRooms) {
commonOptions.push(roomType);
commonOptions.push(tags);
commonOptions.push(owner);
commonOptions.push(modifiedDate);
showStorageInfo && commonOptions.push(sortByStorage);
} else if (isTrash) {
// commonOptions.push(authorOption);
// commonOptions.push(creationDate);
commonOptions.push(erasure);
commonOptions.push(size);
// commonOptions.push(type);
} else {
if (isRooms) {
commonOptions.push(roomType);
commonOptions.push(tags);
commonOptions.push(owner);
commonOptions.push(modifiedDate);
showStorageInfo && commonOptions.push(sortByStorage);
} else if (isTrash) {
// commonOptions.push(authorOption);
// commonOptions.push(creationDate);
commonOptions.push(erasure);
commonOptions.push(size);
// commonOptions.push(type);
} else {
// commonOptions.push(authorOption);
// commonOptions.push(creationDate);
commonOptions.push(modifiedDate);
commonOptions.push(size);
// commonOptions.push(type);
}
// commonOptions.push(authorOption);
// commonOptions.push(creationDate);
commonOptions.push(modifiedDate);
commonOptions.push(size);
// commonOptions.push(type);
isRecentTab && commonOptions.push(lastOpenedDate);
}
return commonOptions;

View File

@ -224,6 +224,7 @@ const SectionHeaderContent = (props) => {
onEmptyTrashAction,
getHeaderOptions,
setBufferSelection,
setGroupsBufferSelection,
} = props;
const location = useLocation();
@ -259,7 +260,9 @@ const SectionHeaderContent = (props) => {
};
const onContextOptionsClick = () => {
setBufferSelection(selectedFolder);
isInsideGroup
? setGroupsBufferSelection(currentGroup)
: setBufferSelection(selectedFolder);
};
const onSelect = (e) => {
@ -655,6 +658,7 @@ export default inject(
currentGroup,
getGroupContextOptions,
setSelected: setGroupsSelected,
setBufferSelection: setGroupsBufferSelection,
insideGroupTempTitle,
} = peopleStore.groupsStore;
@ -797,6 +801,7 @@ export default inject(
onEmptyTrashAction,
getHeaderOptions,
setBufferSelection,
setGroupsBufferSelection,
};
},
)(

View File

@ -38,6 +38,7 @@ const MyDocumentsTabs = ({
setFilter,
showBodyLoader,
isRoot,
user,
}) => {
const { t } = useTranslation(["Common", "Files"]);
@ -56,13 +57,25 @@ const MyDocumentsTabs = ({
const filter = FilesFilter.getDefault();
const url = window.DocSpace.location.pathname;
if (e.id === "recent") {
const recent = e.id === "recent";
const filterStorageItem = user?.id
? recent
? localStorage.getItem(`UserFilterRecent=${user.id}`)
: localStorage.getItem(`UserFilter=${user.id}`)
: null;
if (filterStorageItem) {
const splitFilter = filterStorageItem.split(",");
filter.sortBy = splitFilter[0];
filter.sortOrder = splitFilter[1];
} else if (recent) filter.sortBy = "LastOpened";
if (recent) {
filter.folder = e.id;
filter.searchArea = 3;
filter.sortBy = "LastOpened";
} else {
filter.searchArea = null;
}
} else filter.searchArea = null;
setFilter(filter);
window.DocSpace.navigate(`${url}?${filter.toUrlParams()}`);
@ -83,17 +96,18 @@ const MyDocumentsTabs = ({
};
export default inject(
({ treeFoldersStore, filesStore, clientLoadingStore }) => {
({ treeFoldersStore, filesStore, clientLoadingStore, userStore }) => {
const { isPersonalRoom, isRecentTab, isRoot } = treeFoldersStore;
const { setFilter } = filesStore;
const { showBodyLoader } = clientLoadingStore;
const { user } = userStore;
return {
isPersonalRoom,
isRecentTab,
setFilter,
showBodyLoader,
isRoot,
user,
};
},
)(observer(MyDocumentsTabs));

View File

@ -160,6 +160,7 @@ const PureHome = (props) => {
getFolderModel,
scrollToTop,
isEmptyGroups,
wsCreatedPDFForm,
} = props;
//console.log(t("ComingSoon"))
@ -206,6 +207,7 @@ const PureHome = (props) => {
scrollToTop,
selectedFolderStore,
wsCreatedPDFForm,
});
const { showUploadPanel } = useOperations({
@ -500,6 +502,7 @@ export default inject(
removeTagsFromRoom,
getRooms,
scrollToTop,
wsCreatedPDFForm,
} = filesStore;
const { updateProfileCulture } = peopleStore.targetUserStore;
@ -564,8 +567,15 @@ export default inject(
const { usersStore, groupsStore, viewAs: accountsViewAs } = peopleStore;
const { getUsersList: fetchPeople } = usersStore;
const { getGroups: fetchGroups, fetchGroup, groups } = groupsStore;
const isEmptyGroups = (groups && groups.length === 0) || !Boolean(groups);
const {
getGroups: fetchGroups,
fetchGroup,
groups,
groupsIsFiltered,
} = groupsStore;
const isEmptyGroups =
!groupsIsFiltered &&
((groups && groups.length === 0) || !Boolean(groups));
if (!firstLoad) {
if (isLoading) {
@ -679,6 +689,7 @@ export default inject(
getFolderModel,
scrollToTop,
isEmptyGroups,
wsCreatedPDFForm,
};
},
)(observer(Home));

View File

@ -95,7 +95,6 @@ const AuditTrail = (props) => {
storagePeriod={t("StoragePeriod")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:CancelButton")}
downloadText={t("DownloadStatisticsText")}
securityLifetime={securityLifetime}
lifetime={securityLifetime.auditTrailLifeTime}
setLifetimeAuditSettings={setLifetimeAuditSettings}

View File

@ -93,7 +93,6 @@ const LoginHistory = (props) => {
storagePeriod={t("StoragePeriod")}
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("Common:CancelButton")}
downloadText={t("DownloadStatisticsText")}
lifetime={securityLifetime.loginHistoryLifeTime}
securityLifetime={securityLifetime}
setLifetimeAuditSettings={setLifetimeAuditSettings}

View File

@ -61,6 +61,7 @@ const MainContainer = styled.div`
.login-history-description {
color: ${(props) => props.theme.client.settings.common.descriptionColor};
padding-bottom: 24px;
}
.save-cancel {
@ -82,11 +83,6 @@ const MainContainer = styled.div`
padding: 20px 0 16px;
}
.download-text {
font-size: 13px;
padding: 16px 0 24px 0;
}
.storage-label {
font-weight: 600;
}
@ -173,7 +169,6 @@ const HistoryMainContent = (props) => {
lifetime,
saveButtonLabel,
cancelButtonLabel,
downloadText,
setLifetimeAuditSettings,
securityLifetime,
content,
@ -384,9 +379,6 @@ const HistoryMainContent = (props) => {
/>
</>
)} */}
<Text className="download-text settings_unavailable">
{downloadText}
</Text>
</div>
{content}
<DownLoadWrapper>

View File

@ -70,6 +70,7 @@ export const StyledPage = styled.div`
.public-room-text {
margin: 8px 0;
white-space: wrap;
}
.public-room-name {
@ -83,12 +84,6 @@ export const StyledPage = styled.div`
min-width: 32px;
min-height: 32px;
}
.public-room-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
`;

View File

@ -28,7 +28,7 @@ import { makeAutoObservable } from "mobx";
import { isMobile } from "@docspace/shared/utils";
import { checkDialogsOpen } from "@docspace/shared/utils/checkDialogsOpen";
import { TUser, TUserGroup } from "@docspace/shared/api/people/types";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/components/table/Table.constants";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/utils/device";
type AccountsType = TUser | TUserGroup;

View File

@ -188,7 +188,7 @@ class ContextOptionsStore {
};
onClickLinkFillForm = (item) => {
if (!item.startFilling)
if (!item.startFilling && item.isPDFForm)
return this.dialogsStore.setFillPDFDialogData(true, item);
return this.gotoDocEditor(false, item);
@ -974,7 +974,7 @@ class ContextOptionsStore {
const filterUrlParams = filesFilter.toUrlParams();
const url = getCategoryUrl(
this.filesStore.categoryType,
filterUrlParams.folder,
filesFilter.folder,
);
navigate(
@ -1220,6 +1220,8 @@ class ContextOptionsStore {
);
}
const { isPublicRoom } = this.publicRoomStore;
const { contextOptions, isEditing } = item;
const isRootThirdPartyFolder =
@ -1412,9 +1414,11 @@ class ContextOptionsStore {
const isArchive = item.rootFolderType === FolderType.Archive;
const hasShareLinkRights = item.shared
const hasShareLinkRights = isPublicRoom
? item.security?.Read
: item.security?.EditAccess;
: item.shared
? item.security.CopySharedLink
: item.security?.EditAccess;
const optionsModel = [
{
@ -1587,7 +1591,7 @@ class ContextOptionsStore {
label: t("Common:Info"),
icon: InfoOutlineReactSvgUrl,
onClick: () => this.onShowInfoPanel(item),
disabled: this.publicRoomStore.isPublicRoom,
disabled: isPublicRoom,
},
...pinOptions,
...muteOptions,
@ -1765,8 +1769,7 @@ class ContextOptionsStore {
label: t("LeaveTheRoom"),
icon: LeaveRoomSvgUrl,
onClick: this.onLeaveRoom,
disabled:
isArchive || !item.inRoom || this.publicRoomStore.isPublicRoom,
disabled: isArchive || !item.inRoom || isPublicRoom,
},
{
id: "option_unarchive-room",
@ -1942,7 +1945,7 @@ class ContextOptionsStore {
selection.findIndex((k) => k.security.Download) !== -1;
const favoriteItems = selection.filter((k) =>
k.contextOptions.includes("mark-as-favorite"),
k.contextOptions?.includes("mark-as-favorite"),
);
const moveItems = selection.filter((k) =>

View File

@ -1459,6 +1459,23 @@ class FilesActionStore {
filter.folder = id;
if (isRoom) {
const key =
categoryType === CategoryType.Archive
? `UserFilterArchiveRoom=${this.userStore.user?.id}`
: `UserFilterSharedRoom=${this.userStore.user?.id}`;
const filterStorageSharedRoom =
this.userStore.user?.id && localStorage.getItem(key);
if (filterStorageSharedRoom) {
const splitFilter = filterStorageSharedRoom.split(",");
filter.sortBy = splitFilter[0];
filter.sortOrder = splitFilter[1];
}
}
const url = getCategoryUrl(categoryType, id);
window.DocSpace.navigate(`${url}?${filter.toUrlParams()}`, { state });
@ -2334,7 +2351,8 @@ class FilesActionStore {
onMarkAsRead = (item) => this.markAsRead([], [`${item.id}`], item);
openFileAction = (item, t, e) => {
const { openDocEditor, isPrivacyFolder, setSelection } = this.filesStore;
const { openDocEditor, isPrivacyFolder, setSelection, categoryType } =
this.filesStore;
const { currentDeviceType } = this.settingsStore;
const { fileItemsList } = this.pluginStore;
const { enablePlugins } = this.settingsStore;
@ -2384,6 +2402,30 @@ class FilesActionStore {
);
const filter = FilesFilter.getDefault();
const filterObj = FilesFilter.getFilter(window.location);
if (isRoom) {
const key =
categoryType === CategoryType.Archive
? `UserFilterArchiveRoom=${this.userStore.user?.id}`
: `UserFilterSharedRoom=${this.userStore.user?.id}`;
const filterStorageSharedRoom =
this.userStore.user?.id && localStorage.getItem(key);
if (filterStorageSharedRoom) {
const splitFilter = filterStorageSharedRoom.split(",");
filter.sortBy = splitFilter[0];
filter.sortOrder = splitFilter[1];
}
} else {
// For the document section at all levels there is one sorting
filter.sortBy = filterObj.sortBy;
filter.sortOrder = filterObj.sortOrder;
}
filter.folder = id;
const url = `${path}?${filter.toUrlParams()}`;
@ -2605,6 +2647,11 @@ class FilesActionStore {
const filter = FilesFilter.getDefault();
const filterObj = FilesFilter.getFilter(window.location);
filter.sortBy = filterObj.sortBy;
filter.sortOrder = filterObj.sortOrder;
filter.folder = id;
const categoryType = getCategoryType(window.DocSpace.location);

View File

@ -53,6 +53,7 @@ import config from "PACKAGE_FILE";
import { thumbnailStatuses } from "@docspace/client/src/helpers/filesConstants";
import { getDaysRemaining } from "@docspace/shared/utils/common";
import {
LOADER_TIMEOUT,
MEDIA_VIEW_URL,
PDF_FORM_DIALOG_KEY,
ROOMS_PROVIDER_TYPE_NAME,
@ -72,7 +73,7 @@ import debounce from "lodash.debounce";
import clone from "lodash/clone";
import Queue from "queue-promise";
import { parseHistory } from "SRC_DIR/pages/Home/InfoPanel/Body/helpers/HistoryHelper";
import { toJSON } from "@docspace/shared/api/rooms/filter";
const { FilesFilter, RoomsFilter } = api;
const storageViewAs = localStorage.getItem("viewAs");
@ -380,7 +381,7 @@ class FilesStore {
socketHelper.on("s:modify-room", (option) => {
switch (option.cmd) {
case "create-form":
this.wsCreatedPDFForm(option);
setTimeout(() => this.wsCreatedPDFForm(option), LOADER_TIMEOUT * 2);
break;
default:
@ -1300,10 +1301,24 @@ class FilesStore {
};
//TODO: FILTER
setFilesFilter = (filter) => {
if (!this.publicRoomStore.isPublicRoom) {
const key = `UserFilter=${this.userStore.user?.id}`;
const value = `${filter.sortBy},${filter.pageCount},${filter.sortOrder}`;
setFilesFilter = (filter, folderId = null) => {
const { recycleBinFolderId } = this.treeFoldersStore;
const key =
this.categoryType === CategoryType.Archive
? `UserFilterArchiveRoom=${this.userStore.user?.id}`
: this.categoryType === CategoryType.SharedRoom
? `UserFilterSharedRoom=${this.userStore.user?.id}`
: folderId === "recent"
? `UserFilterRecent=${this.userStore.user?.id}`
: +folderId === recycleBinFolderId
? `UserFilterTrash=${this.userStore.user?.id}`
: !this.publicRoomStore.isPublicRoom
? `UserFilter=${this.userStore.user?.id}`
: null;
if (key) {
const value = `${filter.sortBy},${filter.sortOrder}`;
localStorage.setItem(key, value);
}
@ -1330,6 +1345,21 @@ class FilesStore {
setRoomsFilter = (filter) => {
if (!this.settingsStore.withPaging) filter.pageCount = 100;
const isArchive = this.categoryType === CategoryType.Archive;
const key = isArchive
? `UserRoomsArchivedFilter=${this.userStore.user?.id}`
: `UserRoomsSharedFilter=${this.userStore.user?.id}`;
const sharedStorageFilter = JSON.parse(localStorage.getItem(key));
if (sharedStorageFilter) {
sharedStorageFilter.sortBy = filter.sortBy;
sharedStorageFilter.sortOrder = filter.sortOrder;
const value = toJSON(sharedStorageFilter);
localStorage.setItem(key, value);
}
// this.setFilterUrl(filter, true);
this.roomsFilter = filter;
@ -1463,8 +1493,7 @@ class FilesStore {
const splitFilter = filterStorageItem.split(",");
filterData.sortBy = splitFilter[0];
filterData.pageCount = +splitFilter[1];
filterData.sortOrder = splitFilter[2];
filterData.sortOrder = splitFilter[1];
}
if (!this.settingsStore.withPaging) {
@ -1540,7 +1569,7 @@ class FilesStore {
//save filter for after closing preview change url
this.setTempFilter(filterData);
} else {
this.setFilesFilter(filterData); //TODO: FILTER
this.setFilesFilter(filterData, folderId); //TODO: FILTER
}
const isPrivacyFolder =
@ -3470,6 +3499,7 @@ class FilesStore {
type,
hasDraft,
isForm,
isPDFForm: item.isForm,
requestToken,
lastOpened,
quotaLimit,

View File

@ -432,6 +432,10 @@ class GroupsStore {
};
onDeleteGroup = async (t, groupId) => {
const { getIsInsideGroup, setInfoPanelSelectedGroup } = this.infoPanelStore;
const isDeletingCurrentGroup =
getIsInsideGroup() && this.currentGroup?.id === groupId;
this.setIsLoading(true);
if (!groupId) {
@ -447,6 +451,12 @@ class GroupsStore {
this.infoPanelStore.setInfoPanelSelection(null);
this.setIsLoading(false);
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(false);
if (isDeletingCurrentGroup) {
setInfoPanelSelectedGroup(null);
this.setBufferSelection(null);
window.DocSpace.navigate(`accounts/groups`);
}
} catch (err) {
toastr.error(err.message);
console.error(err);

View File

@ -37,7 +37,7 @@ import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-fil
import config from "PACKAGE_FILE";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { encryptionUploadDialog } from "../helpers/encryptionUploadDialog";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/components/table/Table.constants";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/utils/device";
class HotkeyStore {
filesStore;

View File

@ -27,9 +27,12 @@
import { makeAutoObservable, runInAction } from "mobx";
import {
getInvitationLinks,
getInvitationLink,
getShortenedLink,
} from "@docspace/shared/api/portal";
import { EmployeeType } from "@docspace/shared/enums";
class InviteLinksStore {
peopleStore = null;
userLink = null;
@ -59,9 +62,7 @@ class InviteLinksStore {
};
getPortalInviteLinks = async () => {
const isViewerAdmin = !this.peopleStore.authStore.isVisitor;
if (!isViewerAdmin) return Promise.resolve();
if (this.peopleStore.authStore.isVisitor) return Promise.resolve();
const links = await getInvitationLinks();
@ -73,6 +74,31 @@ class InviteLinksStore {
});
};
getPortalInviteLink = async (type) => {
if (this.peopleStore.authStore.isVisitor) return Promise.resolve();
const link = await getInvitationLink(type);
runInAction(() => {
switch (type) {
case EmployeeType.User:
this.setUserLink(link);
break;
case EmployeeType.Guest:
this.setGuestLink(link);
break;
case EmployeeType.Admin:
this.setAdminLink(link);
break;
case EmployeeType.Collaborator:
this.setCollaboratorLink(link);
break;
}
});
return link;
};
getShortenedLink = async (link, forUser = false) => {
if (forUser) {
const userLink = await getShortenedLink(link);

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/doceditor",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"scripts": {
"build": "node ./scripts/buildTranslations.js && next build",

View File

@ -27,33 +27,61 @@
import styled from "styled-components";
import { mobile } from "@docspace/shared/utils";
import { mobile, mobileMore } from "@docspace/shared/utils";
import type { CompletedFormLayoutProps } from "./CompletedForm.types";
export const CompletedFormLayout = styled.section<CompletedFormLayoutProps>`
display: flex;
align-items: center;
flex-direction: column;
export const ContainerCompletedForm = styled.section<CompletedFormLayoutProps>`
box-sizing: border-box;
* {
box-sizing: border-box;
}
width: 100%;
min-height: 100dvh;
padding: 100px 16px 16px;
background-image: ${(props) => props.bgPattern};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
background-position: center;
width: 100%;
min-height: 100dvh;
height: 100%;
.scroller {
> .scroll-body {
display: flex;
flex-direction: column;
padding-inline-end: 16px !important;
}
}
.completed-form__default-layout {
padding: clamp(42px, 8vh, 100px) 16px 16px;
picture {
}
}
@media ${mobile} {
.completed-form__default-layout {
padding: 0px 16px 16px;
}
background-image: none;
}
`;
export const CompletedFormLayout = styled.div`
display: flex;
align-items: center;
flex-direction: column;
padding: clamp(42px, 8vh, 100px) 0px 16px 16px;
picture {
margin-bottom: clamp(40px, 10vh, 125px);
margin-bottom: clamp(40px, 8vh, 125px);
user-select: none;
}
.link {
@ -68,9 +96,14 @@ export const CompletedFormLayout = styled.section<CompletedFormLayoutProps>`
margin-top: 24px;
}
@media ${mobile} {
background-image: none;
@media ${mobileMore} and (max-height: 650px) {
padding-top: 42px;
.completed-form__logo {
margin-bottom: 40px;
}
}
@media ${mobile} {
padding-top: 0px;
.completed-form__icon {
@ -95,6 +128,11 @@ export const CompletedFormLayout = styled.section<CompletedFormLayoutProps>`
align-self: center;
}
}
.completed-form__empty {
gap: 20px;
margin-top: 24px;
}
}
`;
@ -228,6 +266,19 @@ export const FormNumberWrapper = styled.div`
grid-area: form-number;
.form-number--big {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
@media ${mobileMore} {
.form-number--big {
font-size: 23px;
line-height: 28px;
}
}
> div {
justify-content: center;
flex-grow: 1;

View File

@ -46,10 +46,11 @@ import { isNullOrUndefined } from "@docspace/shared/utils/typeGuards";
import { Button, ButtonSize } from "@docspace/shared/components/button";
import { WhiteLabelLogoType } from "@docspace/shared/enums";
import { mobile, mobileMore } from "@docspace/shared/utils";
import { classNames, mobile, mobileMore } from "@docspace/shared/utils";
import { Heading, HeadingLevel } from "@docspace/shared/components/heading";
import { IconButton } from "@docspace/shared/components/icon-button";
import { copyShareLink } from "@docspace/shared/utils/copy";
import { Scrollbar } from "@docspace/shared/components/scrollbar";
import {
Avatar,
@ -69,10 +70,13 @@ import {
FormNumberWrapper,
ManagerWrapper,
MainContent,
ContainerCompletedForm,
} from "./CompletedForm.styled";
import type { CompletedFormProps } from "./CompletedForm.types";
const BIG_FORM_NUMBER = 9_999_999;
export const CompletedForm = ({
session,
share,
@ -92,25 +96,29 @@ export const CompletedForm = ({
if (!session)
return (
<CompletedFormLayout bgPattern={bgPattern}>
<picture className="completed-form__logo">
<source media={mobile} srcSet={smallLogoUrl} />
<source media={mobileMore} srcSet={logoUrl} />
<img src={logoUrl} alt="logo" />
</picture>
<Image
priority
src={iconUrl}
className="completed-form__icon"
alt="icon"
width={416}
height={200}
/>
<TextWrapper className="completed-form__empty">
<Heading level={HeadingLevel.h1}>{t("CompletedForm:Title")}</Heading>
<Text noSelect>{t("CompletedForm:Description")}</Text>
</TextWrapper>
</CompletedFormLayout>
<ContainerCompletedForm bgPattern={bgPattern}>
<CompletedFormLayout className="completed-form__default-layout">
<picture className="completed-form__logo">
<source media={mobile} srcSet={smallLogoUrl} />
<source media={mobileMore} srcSet={logoUrl} />
<img src={logoUrl} alt="logo" />
</picture>
<Image
priority
src={iconUrl}
className="completed-form__icon"
alt="icon"
width={416}
height={200}
/>
<TextWrapper className="completed-form__empty">
<Heading level={HeadingLevel.h1}>
{t("CompletedForm:Title")}
</Heading>
<Text noSelect>{t("CompletedForm:Description")}</Text>
</TextWrapper>
</CompletedFormLayout>
</ContainerCompletedForm>
);
const {
@ -142,10 +150,6 @@ export const CompletedForm = ({
return `${origin}${path}${filter.toUrlParams()}`;
};
const setHistory = (url: string) => {
history.pushState({}, "", url);
};
const copyLinkFile = async () => {
const origin = window.location.origin;
@ -161,14 +165,12 @@ export const CompletedForm = ({
const gotoCompleteFolder = () => {
const url = getFolderUrl(completedForm.folderId, false);
setHistory(url);
window.location.replace(url);
window.location.assign(url);
};
const handleBackToRoom = () => {
const url = getFolderUrl(roomId, isAnonim);
setHistory(url);
window.location.replace(url);
window.location.assign(url);
};
const fillAgainSearchParams = new URLSearchParams({
@ -178,85 +180,100 @@ export const CompletedForm = ({
});
return (
<CompletedFormLayout bgPattern={bgPattern}>
<picture className="completed-form__logo">
<source media={mobile} srcSet={smallLogoUrl} />
<source media={mobileMore} srcSet={logoUrl} />
<img src={logoUrl} alt="logo" />
</picture>
<TextWrapper>
<Heading level={HeadingLevel.h1}>
{t("CompletedForm:FormCompletedSuccessfully")}
</Heading>
<Text noSelect>
{isAnonim
? t("CompletedForm:DescriptionForAnonymous")
: t("CompletedForm:DescriptionForRegisteredUser")}
</Text>
</TextWrapper>
<MainContent>
<Box className="completed-form__file">
<PDFIcon />
<Heading className="completed-form__filename" level={HeadingLevel.h5}>
{completedForm.title}
</Heading>
<IconButton
size={16}
className="completed-form__download"
iconName={isAnonim ? DownloadIconUrl : LinkIconUrl}
onClick={isAnonim ? handleDownload : copyLinkFile}
/>
</Box>
<FormNumberWrapper>
<span className="label">{t("CompletedForm:FormNumber")}</span>
<Box>
<Text className="completed-form__form-number">{formNumber}</Text>
</Box>
</FormNumberWrapper>
<ManagerWrapper>
<span className="label">{t("CompletedForm:FormOwner")}</span>
<Box>
<Avatar
className="manager__avatar"
size={AvatarSize.medium}
role={AvatarRole.manager}
source={manager.avatar}
/>
<Heading level={HeadingLevel.h3} className="manager__user-name">
{decode(manager.displayName)}
<ContainerCompletedForm bgPattern={bgPattern}>
<Scrollbar fixedSize>
<CompletedFormLayout>
<picture className="completed-form__logo">
<source media={mobile} srcSet={smallLogoUrl} />
<source media={mobileMore} srcSet={logoUrl} />
<img src={logoUrl} alt="logo" />
</picture>
<TextWrapper>
<Heading level={HeadingLevel.h1}>
{t("CompletedForm:FormCompletedSuccessfully")}
</Heading>
<Link
className="manager__mail link"
href={`mailto:${manager.email}`}
>
<MailIcon />
<span>{manager.email}</span>
</Link>
</Box>
</ManagerWrapper>
</MainContent>
<ButtonWrapper isShreFile={isShreFile && !isRoomMember}>
<Button
scale
primary
size={ButtonSize.medium}
label={
isAnonim ? t("Common:Download") : t("CompletedForm:CheckReadyForms")
}
onClick={isAnonim ? handleDownload : gotoCompleteFolder}
/>
{(!isShreFile || isRoomMember) && (
<Button
scale
size={ButtonSize.medium}
label={t("CompletedForm:BackToRoom")}
onClick={handleBackToRoom}
/>
)}
</ButtonWrapper>
<Link className="link" href={`/?${fillAgainSearchParams.toString()}`}>
{t("CompletedForm:FillItOutAgain")}
</Link>
</CompletedFormLayout>
<Text noSelect>
{isAnonim
? t("CompletedForm:DescriptionForAnonymous")
: t("CompletedForm:DescriptionForRegisteredUser")}
</Text>
</TextWrapper>
<MainContent>
<Box className="completed-form__file">
<PDFIcon />
<Heading
className="completed-form__filename"
level={HeadingLevel.h5}
>
{completedForm.title}
</Heading>
<IconButton
size={16}
className="completed-form__download"
iconName={isAnonim ? DownloadIconUrl : LinkIconUrl}
onClick={isAnonim ? handleDownload : copyLinkFile}
/>
</Box>
<FormNumberWrapper>
<span className="label">{t("CompletedForm:FormNumber")}</span>
<Box>
<Text
className={classNames("completed-form__form-number", {
["form-number--big"]: formNumber > BIG_FORM_NUMBER,
})}
>
{formNumber}
</Text>
</Box>
</FormNumberWrapper>
<ManagerWrapper>
<span className="label">{t("CompletedForm:FormOwner")}</span>
<Box>
<Avatar
className="manager__avatar"
size={AvatarSize.medium}
role={AvatarRole.manager}
source={manager.avatar}
/>
<Heading level={HeadingLevel.h3} className="manager__user-name">
{decode(manager.displayName)}
</Heading>
<Link
className="manager__mail link"
href={`mailto:${manager.email}`}
>
<MailIcon />
<span>{manager.email}</span>
</Link>
</Box>
</ManagerWrapper>
</MainContent>
<ButtonWrapper isShreFile={isShreFile && !isRoomMember}>
<Button
scale
primary
size={ButtonSize.medium}
label={
isAnonim
? t("Common:Download")
: t("CompletedForm:CheckReadyForms")
}
onClick={isAnonim ? handleDownload : gotoCompleteFolder}
/>
{(!isShreFile || isRoomMember) && (
<Button
scale
size={ButtonSize.medium}
label={t("CompletedForm:BackToRoom")}
onClick={handleBackToRoom}
/>
)}
</ButtonWrapper>
<Link className="link" href={`/?${fillAgainSearchParams.toString()}`}>
{t("CompletedForm:FillItOutAgain")}
</Link>
</CompletedFormLayout>
</Scrollbar>
</ContainerCompletedForm>
);
};

View File

@ -34,7 +34,7 @@ import {
} from "@docspace/shared/api/files";
// import { getOperationProgress } from "@docspace/shared/utils/getOperationProgress";
import { toastr } from "@docspace/shared/components/toast";
import { EDITOR_ID } from "@docspace/shared/constants";
import { CREATED_FORM_KEY, EDITOR_ID } from "@docspace/shared/constants";
import type {
TFile,
@ -52,6 +52,13 @@ import type { TData } from "@docspace/shared/components/toast/Toast.type";
import { saveAs } from "@/utils";
import type { ConflictStateType } from "@/types";
type SuccessResponseType = {
form: TFile;
message: string;
};
type FaildResponseType = string;
type ResponseType = SuccessResponseType | FaildResponseType;
const DefaultConflictDataDialogState: ConflictStateType = {
visible: false,
resolve: () => {},
@ -70,6 +77,12 @@ const hasFileUrl = (arg: object): arg is { data: { url: string } } => {
);
};
const isSuccessResponse = (
res: ResponseType | undefined,
): res is SuccessResponseType => {
return Boolean(res) && typeof res === "object" && "form" in res;
};
const useStartFillingSelectDialog = (fileInfo: TFile | undefined) => {
// const { t } = useTranslation(["Common"]);
const resolveRef = useRef<(value: string | PromiseLike<string>) => void>();
@ -179,14 +192,22 @@ const useStartFillingSelectDialog = (fileInfo: TFile | undefined) => {
const fileUrl = await getFileUrl();
const response = await saveAs(
const response = await saveAs<ResponseType>(
fileInfo.title,
fileUrl,
selectedItemId,
false,
"createForm",
);
const [key, value] = response?.split(":") ?? [];
if (isSuccessResponse(response)) {
const { form } = response;
sessionStorage.setItem(CREATED_FORM_KEY, JSON.stringify(form));
}
const [key, value] =
typeof response === "string" ? response.split(":") : [];
// await copyToFolder(
// Number(selectedItemId),

View File

@ -393,28 +393,28 @@ export const checkIsAuthenticated = async () => {
return isAuth.response as boolean;
};
export async function checkFillFromDraft(
templateFileId: number,
share?: string,
) {
const [checkFillFormDraft] = createRequest(
[`/files/masterform/${templateFileId}/checkfillformdraft`],
[
share ? ["Request-Token", share] : ["", ""],
["Content-Type", "application/json;charset=utf-8"],
],
"POST",
JSON.stringify({ fileId: templateFileId }),
);
// export async function checkFillFromDraft(
// templateFileId: number,
// share?: string,
// ) {
// const [checkFillFormDraft] = createRequest(
// [`/files/masterform/${templateFileId}/checkfillformdraft`],
// [
// share ? ["Request-Token", share] : ["", ""],
// ["Content-Type", "application/json;charset=utf-8"],
// ],
// "POST",
// JSON.stringify({ fileId: templateFileId }),
// );
const response = await fetch(checkFillFormDraft);
// const response = await fetch(checkFillFormDraft);
if (!response.ok) return null;
// if (!response.ok) return null;
const { response: formUrl } = await response.json();
// const { response: formUrl } = await response.json();
return formUrl as string;
}
// return formUrl as string;
// }
export async function openEdit(
fileId: number | string,

View File

@ -81,30 +81,31 @@ export const onSDKRequestEditRights = async (
const url = window.location.href;
const isPDF = documentType === "pdf";
if (isPDF) {
const newURL = new URL(url);
let newURL = new URL(url);
if (newURL.searchParams.has("action")) {
newURL.searchParams.delete("action");
if (
!isPDF &&
fileInfo?.viewAccessibility?.MustConvert &&
fileInfo?.security?.Convert
) {
try {
const response = await convertDocumentUrl(fileInfo.id);
if (response && response.webUrl) {
newURL = new URL(response.webUrl);
} else {
throw new Error("Invalid response data");
}
} catch (error) {
console.error("Error converting document", { error });
return;
}
} else {
if (newURL.searchParams.has("action")) newURL.searchParams.delete("action");
newURL.searchParams.append("action", "edit");
history.pushState({}, "", newURL.toString());
document.location.reload();
return;
}
let convertUrl = url;
if (fileInfo?.viewAccessibility?.MustConvert && fileInfo?.security?.Convert) {
const newUrl = await convertDocumentUrl(fileInfo.id);
if (newUrl) {
convertUrl = newUrl.webUrl;
}
}
history.pushState({}, "", convertUrl);
history.pushState({}, "", newURL.toString());
document.location.reload();
};

View File

@ -48,6 +48,8 @@ export const getBackUrl = (
} else {
backUrl = `/rooms/shared/${folderId}/filter?folder=${folderId}`;
}
} else if (rootFolderType === FolderType.Archive) {
backUrl = `/rooms/archived/${folderId}/filter?folder=${folderId}`;
} else {
if (
rootFolderType === FolderType.SHARE ||
@ -99,14 +101,15 @@ export const getDataSaveAs = async (params: string) => {
}
};
export const saveAs = (
export const saveAs = <T = string>(
title: string,
url: string,
folderId: string | number,
openNewTab: boolean,
action = "create",
) => {
const options = {
action: "create",
action,
fileuri: url,
title: title,
folderid: folderId,
@ -115,7 +118,7 @@ export const saveAs = (
const params = toUrlParams(options, true);
if (!openNewTab) {
return getDataSaveAs(params);
return getDataSaveAs(params) as Promise<T>;
} else {
const handlerUrl = combineUrl(
window.ClientConfig?.proxy?.url,

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/login",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"scripts": {
"build": "node ./scripts/buildTranslations.js && next build",

View File

@ -65,6 +65,8 @@ import { LoginDispatchContext, LoginValueContext } from "../Login";
import LDAPContainer from "./sub-components/LDAPContainer";
import { RecaptchaType } from "@docspace/shared/enums";
let showToastr = true;
const LoginForm = ({
hashSettings,
cookieSettingsEnabled,
@ -195,8 +197,7 @@ const LoginForm = ({
!toastr.isActive(toastId.current || "confirm-email-toast")
)
toastId.current = toastr.success(text);
if (authError && ready) toastr.error(t("Common:ProviderLoginError"));
}, [message, confirmedEmail, t, ready, authError, authCallback]);
}, [message, confirmedEmail, t, ready, authCallback]);
const onChangeLogin = (e: React.ChangeEvent<HTMLInputElement>) => {
//console.log("onChangeLogin", e.target.value);
@ -380,6 +381,11 @@ const LoginForm = ({
const passwordErrorMessage = errorMessage();
if (authError && ready) {
if (showToastr) toastr.error(t("Common:ProviderLoginError"));
showToastr = false;
}
return (
<form className="auth-form-container">
<EmailContainer

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/management",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"homepage": "/management",
"scripts": {

View File

@ -1180,15 +1180,15 @@ export async function getPresignedUri(fileId: number | string) {
return res;
}
export async function checkFillFormDraft(fileId: number | string) {
const res = (await request({
method: "post",
url: `files/masterform/${fileId}/checkfillformdraft`,
data: { fileId },
})) as string;
// export async function checkFillFormDraft(fileId: number | string) {
// const res = (await request({
// method: "post",
// url: `files/masterform/${fileId}/checkfillformdraft`,
// data: { fileId },
// })) as string;
return res;
}
// return res;
// }
export async function fileCopyAs(
fileId: number,

View File

@ -35,7 +35,7 @@ import {
TTenantExtra,
} from "./types";
export function getShortenedLink(link) {
export function getShortenedLink(link: string) {
return request({
method: "put",
url: "/portal/getshortenlink",
@ -43,13 +43,13 @@ export function getShortenedLink(link) {
});
}
export function getInvitationLink(type) {
return request({
export async function getInvitationLink(type: EmployeeType) {
const res = await request({
method: "get",
url: `/portal/users/invite/${type}`,
}).then((link) => {
return Promise.resolve(link);
});
return res;
}
export function getInvitationLinks() {

View File

@ -64,10 +64,10 @@ const DEFAULT_SEARCH_AREA = RoomSearchArea.Active;
const TAGS = "tags";
const DEFAULT_TAGS = null;
const SORT_BY = "sortby";
const SORT_BY = "sortBy";
const DEFAULT_SORT_BY = "DateAndTime";
const SORT_ORDER = "sortorder";
const SORT_ORDER = "sortOrder";
const DEFAULT_SORT_ORDER = "descending";
const EXCLUDE_SUBJECT = "excludeSubject";
@ -85,6 +85,21 @@ const DEFAULT_QUOTA_FILTER = null;
const STORAGE_FILTER = "storageFilter";
const DEFAULT_STORAGE_FILTER = null;
export const toJSON = (filter) => {
const filterObject = transform(
filter,
(result, value, key) => {
if (value instanceof Function) return result;
if (value === null || value === false) return result;
result[key] = value;
},
{},
);
return JSON.stringify(filterObject);
};
class RoomsFilter {
static getDefault(userId, searchArea) {
const defaultFilter = new RoomsFilter(
@ -264,19 +279,6 @@ class RoomsFilter {
return this.page > 0;
};
toJSON = (filter) => {
const filterObject = transform(
filter,
(result, value, key) => {
if (value instanceof Function) return result;
if (value === null || value === false) return result;
result[key] = value;
},
{},
);
return JSON.stringify(filterObject);
};
toApiUrlParams = () => {
const {
page,
@ -422,7 +424,7 @@ class RoomsFilter {
if (!sharedStorageFilter && userId) {
localStorage.setItem(
`UserRoomsSharedFilter=${userId}`,
this.toJSON(defaultFilter),
toJSON(defaultFilter),
);
}
@ -430,11 +432,11 @@ class RoomsFilter {
defaultFilter.searchArea = RoomSearchArea.Archive;
localStorage.setItem(
`UserRoomsArchivedFilter=${userId}`,
this.toJSON(defaultFilter),
toJSON(defaultFilter),
);
}
const filterJSON = this.toJSON(dtoFilter);
const filterJSON = toJSON(dtoFilter);
const currentStorageFilter =
dtoFilter.searchArea === RoomSearchArea.Active

View File

@ -112,11 +112,11 @@ const StyledBody = styled.div<{
height: ${(props) =>
props.footerVisible
? props.withHeader
? `calc(100% - 16px - ${props.footerHeight}px - ${props.headerHeight}px)`
: `calc(100% - 16px - ${props.footerHeight}px)`
? `calc(100% - ${props.footerHeight}px - ${props.headerHeight}px)`
: `calc(100% - ${props.footerHeight}px)`
: props.withHeader
? `calc(100% - 16px - ${props.headerHeight}px)`
: `calc(100% - 16px)`};
? `calc(100% - ${props.headerHeight}px)`
: "100%"};
padding: ${({ withTabs }) => (withTabs ? "0" : "16px 0 0 0")};

View File

@ -216,7 +216,9 @@ const Body = ({
: FOOTER_HEIGHT
}
className="selector_body"
headerHeight={HEADER_HEIGHT}
headerHeight={
withTabs ? HEADER_HEIGHT : HEADER_HEIGHT + CONTAINER_PADDING
}
footerVisible={footerVisible}
withHeader={withHeader}
withTabs={withTabs}

View File

@ -1,31 +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
export const DEFAULT_MIN_COLUMN_SIZE = 110;
export const SETTINGS_SIZE = 24;
export const CONTAINER_MARGIN = 25;
export const MIN_SIZE_FIRST_COLUMN = 210;
export const TABLE_HEADER_HEIGHT = 40;

View File

@ -24,7 +24,10 @@
// 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 { SETTINGS_SIZE } from "./Table.constants";
export const MIN_SIZE_FIRST_COLUMN = 210;
export const DEFAULT_MIN_COLUMN_SIZE = 110;
export const SETTINGS_SIZE = 24;
export const HANDLE_OFFSET = 8;
export const getSubstring = (str: string) => +str.substring(0, str.length - 2);
@ -33,7 +36,6 @@ export const checkingForUnfixedSize = (
defaultColumnSize: number,
) => {
return (
item !== "24px" && // TODO: SETTINGS_SIZE is not imported
item !== `${SETTINGS_SIZE}px` &&
item !== `${defaultColumnSize}px` &&
item !== "0px"

View File

@ -38,16 +38,17 @@ import {
import { TTableColumn, TableHeaderProps } from "./Table.types";
import { TableSettings } from "./sub-components/TableSettings";
import { TableHeaderCell } from "./sub-components/TableHeaderCell";
import { checkingForUnfixedSize, getSubstring } from "./Table.utils";
import {
DEFAULT_MIN_COLUMN_SIZE,
MIN_SIZE_FIRST_COLUMN,
SETTINGS_SIZE,
HANDLE_OFFSET,
checkingForUnfixedSize,
getSubstring,
} from "./Table.utils";
import { isDesktop } from "../../utils";
const defaultMinColumnSize = 110;
const settingsSize = 24;
const minSizeFirstColumn = 210;
const handleOffset = 8;
class TableHeader extends React.Component<
class TableHeaderComponent extends React.Component<
TableHeaderProps,
{ hideColumns: boolean; columnIndex: null | number }
> {
@ -76,6 +77,8 @@ class TableHeader extends React.Component<
infoPanelVisible,
columnStorageName,
columnInfoPanelStorageName,
sortBy,
sorted,
} = this.props;
if (columnStorageName === prevProps.columnStorageName) {
@ -83,6 +86,14 @@ class TableHeader extends React.Component<
? localStorage.getItem(columnInfoPanelStorageName)
: localStorage.getItem(columnStorageName);
if (sortBy !== prevProps.sortBy || sorted !== prevProps.sorted) {
const columnIndex = columns.findIndex((c) => c?.sortBy === sortBy);
if (columnIndex > -1 && !columns[columnIndex].enable) {
columns[columnIndex].onChange?.(columns[columnIndex].key);
}
}
// columns.length + 1 - its settings column
if (storageSize && storageSize.split(" ").length !== columns.length + 1) {
return this.resetColumns();
@ -137,7 +148,7 @@ class TableHeader extends React.Component<
if (leftColumn) {
const minSize = leftColumn.dataset.minWidth
? leftColumn.dataset.minWidth
: defaultMinColumnSize;
: DEFAULT_MIN_COLUMN_SIZE;
if (leftColumn.getBoundingClientRect().width <= +minSize) {
if (colIndex < 0) return false;
@ -185,17 +196,17 @@ class TableHeader extends React.Component<
const defaultColumn = document.getElementById(`column_${colIndex}`);
if (!defaultColumn || defaultColumn.dataset.defaultSize) return;
if (column2Width + offset - handleOffset >= defaultMinColumnSize) {
widths[+columnIndex] = `${newWidth + handleOffset}px`;
widths[colIndex] = `${column2Width + offset - handleOffset}px`;
} else if (column2Width !== defaultMinColumnSize) {
if (column2Width + offset - HANDLE_OFFSET >= DEFAULT_MIN_COLUMN_SIZE) {
widths[+columnIndex] = `${newWidth + HANDLE_OFFSET}px`;
widths[colIndex] = `${column2Width + offset - HANDLE_OFFSET}px`;
} else if (column2Width !== DEFAULT_MIN_COLUMN_SIZE) {
const width =
getSubstring(widths[+columnIndex]) +
getSubstring(widths[+colIndex]) -
defaultMinColumnSize;
DEFAULT_MIN_COLUMN_SIZE;
widths[+columnIndex] = `${width}px`;
widths[colIndex] = `${defaultMinColumnSize}px`;
widths[colIndex] = `${DEFAULT_MIN_COLUMN_SIZE}px`;
} else {
if (colIndex === columns.length) return false;
this.moveToRight(widths, newWidth, colIndex + 1);
@ -229,7 +240,7 @@ class TableHeader extends React.Component<
)?.defaultSize;
const widthColumns =
containerWidth - settingsSize - (defaultSizeColumn || 0);
containerWidth - SETTINGS_SIZE - (defaultSizeColumn || 0);
const newColumnSize = defaultSize || widthColumns / allColumnsLength;
@ -247,9 +258,9 @@ class TableHeader extends React.Component<
};
if (
(indexOfMaxSize === 0 && newSizeMaxColumn < minSizeFirstColumn) ||
(indexOfMaxSize !== 0 && newSizeMaxColumn < defaultMinColumnSize) ||
newColumnSize < defaultMinColumnSize ||
(indexOfMaxSize === 0 && newSizeMaxColumn < MIN_SIZE_FIRST_COLUMN) ||
(indexOfMaxSize !== 0 && newSizeMaxColumn < DEFAULT_MIN_COLUMN_SIZE) ||
newColumnSize < DEFAULT_MIN_COLUMN_SIZE ||
enableColumnsLength === 1
)
return ResetColumnsSize();
@ -277,14 +288,14 @@ class TableHeader extends React.Component<
const minSize = column.dataset.minWidth
? column.dataset.minWidth
: defaultMinColumnSize;
: DEFAULT_MIN_COLUMN_SIZE;
if (newWidth <= +minSize - handleOffset) {
if (newWidth <= +minSize - HANDLE_OFFSET) {
const currentWidth = getSubstring(widths[+columnIndex]);
// Move left
if (currentWidth !== +minSize) {
newWidth = +minSize - handleOffset;
newWidth = +minSize - HANDLE_OFFSET;
this.moveToRight(widths, newWidth);
} else this.moveToLeft(widths, newWidth);
} else {
@ -368,7 +379,7 @@ class TableHeader extends React.Component<
if (storageSize) {
const splitStorage = storageSize.split(" ");
if (getSubstring(splitStorage[0]) <= defaultMinColumnSize) {
if (getSubstring(splitStorage[0]) <= DEFAULT_MIN_COLUMN_SIZE) {
localStorage.removeItem(columnStorageName);
this.onResize();
return;
@ -406,7 +417,7 @@ class TableHeader extends React.Component<
.map((column) => getSubstring(column))
.reduce((x, y) => x + y);
const oldWidth = defaultWidth - defaultSize - settingsSize;
const oldWidth = defaultWidth - defaultSize - SETTINGS_SIZE;
let str = "";
let gridTemplateColumnsWithoutOverfilling: string[] = [];
@ -423,7 +434,7 @@ class TableHeader extends React.Component<
? storageInfoPanelSize.split(" ")
: tableContainer;
let containerMinWidth = containerWidth - defaultSize - settingsSize;
let containerMinWidth = containerWidth - defaultSize - SETTINGS_SIZE;
tableInfoPanelContainer.forEach((item, index) => {
const column = document.getElementById(`column_${index}`);
@ -435,12 +446,12 @@ class TableHeader extends React.Component<
if (
enable &&
(item !== `${defaultSize}px` || `${defaultSize}px` === `0px`) &&
item !== `${settingsSize}px`
item !== `${SETTINGS_SIZE}px`
) {
if (column?.dataset?.minWidth) {
containerMinWidth -= +column.dataset.minWidth;
} else {
containerMinWidth -= defaultMinColumnSize;
containerMinWidth -= DEFAULT_MIN_COLUMN_SIZE;
}
}
});
@ -460,11 +471,11 @@ class TableHeader extends React.Component<
if (column?.dataset?.minWidth && column?.dataset?.default) {
gridTemplateColumns.push(
`${containerWidth - defaultSize - settingsSize}px`,
`${containerWidth - defaultSize - SETTINGS_SIZE}px`,
);
} else if (
item === `${defaultSize}px` ||
item === `${settingsSize}px`
item === `${SETTINGS_SIZE}px`
) {
gridTemplateColumns.push(item);
} else {
@ -476,7 +487,7 @@ class TableHeader extends React.Component<
let hasGridTemplateColumnsWithoutOverfilling = false;
if (infoPanelVisible) {
if (!hideColumns) {
const contentWidth = containerWidth - defaultSize - settingsSize;
const contentWidth = containerWidth - defaultSize - SETTINGS_SIZE;
let enabledColumnsCount = 0;
@ -485,7 +496,7 @@ class TableHeader extends React.Component<
index !== 0 &&
item !== "0px" &&
item !== `${defaultSize}px` &&
item !== `${settingsSize}px`
item !== `${SETTINGS_SIZE}px`
) {
enabledColumnsCount += 1;
}
@ -496,10 +507,10 @@ class TableHeader extends React.Component<
.map((column) => getSubstring(column))
.reduce((x, y) => x + y) -
defaultSize -
settingsSize;
SETTINGS_SIZE;
if (
contentWidth - enabledColumnsCount * defaultMinColumnSize >
contentWidth - enabledColumnsCount * DEFAULT_MIN_COLUMN_SIZE >
getSubstring(tableInfoPanelContainer[0])
) {
const currentContentWidth =
@ -523,7 +534,7 @@ class TableHeader extends React.Component<
if (!enable) {
gridTemplateColumns.push("0px");
} else if (item !== `${settingsSize}px`) {
} else if (item !== `${SETTINGS_SIZE}px`) {
const percent =
enabledColumnsCount === 0
? 100
@ -535,17 +546,17 @@ class TableHeader extends React.Component<
const newItemWidth = defaultColumnSize
? `${defaultColumnSize}px`
: (currentContentWidth * percent) / 100 >
defaultMinColumnSize
DEFAULT_MIN_COLUMN_SIZE
? `${(currentContentWidth * percent) / 100}px`
: `${defaultMinColumnSize}px`;
: `${DEFAULT_MIN_COLUMN_SIZE}px`;
if (
(currentContentWidth * percent) / 100 <
defaultMinColumnSize &&
DEFAULT_MIN_COLUMN_SIZE &&
!defaultColumnSize
) {
overWidth +=
defaultMinColumnSize -
DEFAULT_MIN_COLUMN_SIZE -
(currentContentWidth * percent) / 100;
}
@ -564,10 +575,10 @@ class TableHeader extends React.Component<
index !== 0 &&
column !== "0px" &&
column !== `${defaultSize}px` &&
column !== `${settingsSize}px` &&
columnWidth > defaultMinColumnSize
column !== `${SETTINGS_SIZE}px` &&
columnWidth > DEFAULT_MIN_COLUMN_SIZE
) {
const availableWidth = columnWidth - defaultMinColumnSize;
const availableWidth = columnWidth - DEFAULT_MIN_COLUMN_SIZE;
if (availableWidth < Math.abs(overWidth)) {
overWidth = Math.abs(overWidth) - availableWidth;
@ -597,15 +608,15 @@ class TableHeader extends React.Component<
if (!enable) {
gridTemplateColumns.push("0px");
} else if (item !== `${settingsSize}px`) {
} else if (item !== `${SETTINGS_SIZE}px`) {
const newItemWidth = defaultColumnSize
? `${defaultColumnSize}px`
: index === 0
? `${
contentWidth -
enabledColumnsCount * defaultMinColumnSize
enabledColumnsCount * DEFAULT_MIN_COLUMN_SIZE
}px`
: `${defaultMinColumnSize}px`;
: `${DEFAULT_MIN_COLUMN_SIZE}px`;
gridTemplateColumns.push(newItemWidth);
} else {
@ -645,7 +656,7 @@ class TableHeader extends React.Component<
getSubstring(gridTemplateColumns[+index - colIndex]) +
getSubstring(item)
}px`;
} else if (item !== `${settingsSize}px`) {
} else if (item !== `${SETTINGS_SIZE}px`) {
const percent = (getSubstring(item) / oldWidth) * 100;
if (percent === 100) {
@ -662,30 +673,31 @@ class TableHeader extends React.Component<
let newItemWidth = defaultColumnSize
? `${defaultColumnSize}px`
: percent === 0
? `${defaultMinColumnSize}px`
? `${DEFAULT_MIN_COLUMN_SIZE}px`
: `${
((containerWidth - defaultSize - settingsSize) *
((containerWidth - defaultSize - SETTINGS_SIZE) *
percent) /
100
}px`;
const minWidth = column?.dataset?.minWidth;
const minSize = minWidth ? +minWidth : minSizeFirstColumn;
const minSize = minWidth ? +minWidth : MIN_SIZE_FIRST_COLUMN;
// Checking whether the first column is less than the minimum width
if (+index === 0 && getSubstring(newItemWidth) < minSize) {
overWidth += minSizeFirstColumn - getSubstring(newItemWidth);
newItemWidth = `${minSizeFirstColumn}px`;
overWidth += MIN_SIZE_FIRST_COLUMN - getSubstring(newItemWidth);
newItemWidth = `${MIN_SIZE_FIRST_COLUMN}px`;
}
// Checking whether columns are smaller than the minimum width
if (
+index !== 0 &&
!defaultColumnSize &&
getSubstring(newItemWidth) < defaultMinColumnSize
getSubstring(newItemWidth) < DEFAULT_MIN_COLUMN_SIZE
) {
overWidth += defaultMinColumnSize - getSubstring(newItemWidth);
newItemWidth = `${defaultMinColumnSize}px`;
overWidth +=
DEFAULT_MIN_COLUMN_SIZE - getSubstring(newItemWidth);
newItemWidth = `${DEFAULT_MIN_COLUMN_SIZE}px`;
}
gridTemplateColumns.push(newItemWidth);
@ -778,9 +790,11 @@ class TableHeader extends React.Component<
const column = document.getElementById(`column_${index}`);
const minWidth = column?.dataset?.minWidth;
const minSize = minWidth ? +minWidth : minSizeFirstColumn;
const minSize = minWidth ? +minWidth : MIN_SIZE_FIRST_COLUMN;
if ((index === 0 ? minSize : defaultMinColumnSize) !== getSubstring(item))
if (
(index === 0 ? minSize : DEFAULT_MIN_COLUMN_SIZE) !== getSubstring(item)
)
countColumns += 1;
});
@ -792,21 +806,21 @@ class TableHeader extends React.Component<
const column = document.getElementById(`column_${index}`);
const minWidth = column?.dataset?.minWidth;
const minSize = minWidth ? +minWidth : minSizeFirstColumn;
const minSize = minWidth ? +minWidth : MIN_SIZE_FIRST_COLUMN;
const itemSubstring = getSubstring(item);
if ((index === 0 ? minSize : defaultMinColumnSize) === itemSubstring)
if ((index === 0 ? minSize : DEFAULT_MIN_COLUMN_SIZE) === itemSubstring)
return;
const differenceWithMinimum =
itemSubstring - (index === 0 ? minSize : defaultMinColumnSize);
itemSubstring - (index === 0 ? minSize : DEFAULT_MIN_COLUMN_SIZE);
if (differenceWithMinimum >= addWidth) {
newGridTemplateColumns[index] = `${itemSubstring - addWidth}px`;
} else {
newGridTemplateColumns[index] = `${
index === 0 ? minSize : defaultMinColumnSize
index === 0 ? minSize : DEFAULT_MIN_COLUMN_SIZE
}px`;
}
});
@ -857,7 +871,7 @@ class TableHeader extends React.Component<
columns.find((col) => col.defaultSize && col.enable)?.defaultSize || 0;
const containerWidth =
container.clientWidth - defaultColumnSize - settingsSize;
container.clientWidth - defaultColumnSize - SETTINGS_SIZE;
const firstColumnPercent = enableColumns.length > 0 ? 40 : 100;
const percent = enableColumns.length > 0 ? 60 / enableColumns.length : 0;
@ -877,7 +891,7 @@ class TableHeader extends React.Component<
}
}
str += `${settingsSize}px`;
str += `${SETTINGS_SIZE}px`;
if (container) container.style.gridTemplateColumns = str;
if (this.headerRef && this.headerRef.current) {
@ -965,4 +979,6 @@ class TableHeader extends React.Component<
}
}
export default withTheme(TableHeader);
const TableHeader = withTheme(TableHeaderComponent);
export { TableHeader };

View File

@ -24,13 +24,10 @@
// 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 TableHeader from "./TableHeader";
export { TableHeader };
export { TableContainer } from "./TableContainer";
export { TableBody } from "./TableBody";
export { TableRow } from "./TableRow";
// export { TableHeader } from "./TableHeader";
export { TableHeader } from "./TableHeader";
export { TableGroupMenu } from "./TableGroupMenu";
export { TableCell } from "./sub-components/TableCell";

View File

@ -37,12 +37,16 @@ let elem =
typeof document !== "undefined" &&
document.getElementById("ipl-progress-indicator");
const cancelProgress = () => {
if (timerId) clearTimeout(timerId);
timerId = null;
if (elem) elem.style.width = "0px";
width = 0;
};
const animatingWidth = () => {
if (width >= MAX) {
if (timerId) clearTimeout(timerId);
timerId = null;
if (elem) elem.style.width = "0px";
width = 0;
cancelProgress();
return;
}
@ -64,6 +68,10 @@ export default class TopLoaderService {
startInterval();
}
static cancel() {
cancelProgress();
}
static end() {
percentage = MAX;
}

View File

@ -53,6 +53,7 @@ export const ROOM = "room";
export const USERS = "users";
export const USERS_IN_ROOM = "usersInRoom";
export const PDF_FORM_DIALOG_KEY = "pdf_form_dialog";
export const CREATED_FORM_KEY = "created_form_key";
export const COUNT_FOR_SHOWING_BAR = 2;
export const PERCENTAGE_FOR_SHOWING_BAR = 90;

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/shared",
"version": "2.6.0",
"version": "2.6.1",
"private": true,
"scripts": {
"build": "echo 'skip it'",

View File

@ -369,7 +369,7 @@ class AuthStore {
login = async (user: TUser, hash: string, session = true) => {
try {
const response = (await api.user.login(user, hash, session)) as {
const response = (await api.user.login(user, hash, "", session)) as {
token: string;
tfa: string;
error: { message: unknown };

View File

@ -272,10 +272,15 @@ export function showLoader() {
if (isMobile) return;
hideLoader();
timer = setTimeout(() => TopLoaderService.start(), 500);
}
export function showProgress() {
if (isMobile) return;
TopLoaderService.cancel();
TopLoaderService.start();
}
export function isMe(user: TUser, userName: string) {
return (
user && user.id && (userName === "@self" || user.userName === userName)

View File

@ -25,6 +25,7 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
export const INFO_PANEL_WIDTH = 400;
export const TABLE_HEADER_HEIGHT = 40;
export function checkIsSSR() {
return typeof window === "undefined";

View File

@ -34,8 +34,8 @@
IE: 11,
Edge: 109,
Opera: 90,
Safari: 16,
SafariMobile: 16,
Safari: 15,
SafariMobile: 15,
AscDesktopEditor: 6,
SamsungBrowser: 4,
UCBrowser: 12,
@ -50,7 +50,7 @@
let temp = [];
let match =
agent.match(
/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i,
/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i
) || [];
if (/trident/i.test(match[1])) {
@ -60,7 +60,7 @@
if (match[1] === "Chrome") {
temp = agent.match(
/\b(OPR|Edge|AscDesktopEditor|SamsungBrowser|UCBrowser)\/(\d+.\d)/,
/\b(OPR|Edge|AscDesktopEditor|SamsungBrowser|UCBrowser)\/(\d+.\d)/
);
const userOS =