From 36226366d34f254b1d80403ce51d1fe53e3c72c5 Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Tue, 13 Aug 2024 17:26:44 +0300 Subject: [PATCH 01/26] Fixed Bug 68537: JS-SDK: Restored missing value for viewTableColumns option --- .../categories/developer-tools/JavascriptSDK/presets/Manager.js | 1 + public/scripts/sdk/1.0.1/api.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js index 7c7e509520..a3c1c572bb 100644 --- a/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js +++ b/packages/client/src/pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager.js @@ -130,6 +130,7 @@ const Manager = (props) => { ); const [selectedColumns, setSelectedColumns] = useState([ { key: "Name", label: t("Common:Name") }, + { key: "Size", label: t("Common:Size") }, { key: "Type", label: t("Common:Type") }, { key: "Tags", label: t("Common:Tags") }, ]); diff --git a/public/scripts/sdk/1.0.1/api.js b/public/scripts/sdk/1.0.1/api.js index ae265191e0..f006b3753f 100644 --- a/public/scripts/sdk/1.0.1/api.js +++ b/public/scripts/sdk/1.0.1/api.js @@ -53,7 +53,7 @@ showSignOut: true, destroyText: "", viewAs: "row", //TODO: ["row", "table", "tile"] - viewTableColumns: "Name,Type,Tags", + viewTableColumns: "Name,Size,Type,Tags", checkCSP: true, disableActionButton: false, showSettings: false, From 625a7aa5a64bab61c038f6552c8a49944b5167f1 Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Tue, 13 Aug 2024 18:10:38 +0300 Subject: [PATCH 02/26] JS-SDK: Added onNoAccess event --- .../src/components/EmptyContainer/RoomNoAccessContainer.js | 3 +++ packages/shared/types/Frame.ts | 2 ++ public/scripts/sdk/1.0.1/api.js | 1 + 3 files changed, 6 insertions(+) diff --git a/packages/client/src/components/EmptyContainer/RoomNoAccessContainer.js b/packages/client/src/components/EmptyContainer/RoomNoAccessContainer.js index e02dc9a77f..61df1e840f 100644 --- a/packages/client/src/components/EmptyContainer/RoomNoAccessContainer.js +++ b/packages/client/src/components/EmptyContainer/RoomNoAccessContainer.js @@ -38,6 +38,7 @@ import { IconButton } from "@docspace/shared/components/icon-button"; import RoomsFilter from "@docspace/shared/api/rooms/filter"; import { RoomSearchArea } from "@docspace/shared/enums"; +import { frameCallEvent } from "@docspace/shared/utils/common"; import { getCategoryUrl } from "SRC_DIR/helpers/utils"; import { CategoryType } from "SRC_DIR/helpers/constants"; @@ -60,6 +61,8 @@ const RoomNoAccessContainer = (props) => { const navigate = useNavigate(); React.useEffect(() => { + frameCallEvent({ event: "onNoAccess" }); + const timer = setTimeout(onGoToShared, 5000); return () => clearTimeout(timer); }, []); diff --git a/packages/shared/types/Frame.ts b/packages/shared/types/Frame.ts index 1dd42178ad..469ff145df 100644 --- a/packages/shared/types/Frame.ts +++ b/packages/shared/types/Frame.ts @@ -75,6 +75,7 @@ export type TFrameEvents = { onAuthSuccess: null | ((e: Event) => void); onSignOut: null | ((e: Event) => void); onDownload: null | ((e: Event) => void); + onNoAccess: null | ((e: Event) => void); }; export type TFrameConfig = { @@ -96,6 +97,7 @@ export type TFrameConfig = { showSelectorCancel: boolean; showSelectorHeader: boolean; showHeader: boolean; + showHeaderBanner: string; showTitle: boolean; showMenu: boolean; showFilter: boolean; diff --git a/public/scripts/sdk/1.0.1/api.js b/public/scripts/sdk/1.0.1/api.js index f006b3753f..cb263c3245 100644 --- a/public/scripts/sdk/1.0.1/api.js +++ b/public/scripts/sdk/1.0.1/api.js @@ -97,6 +97,7 @@ onAuthSuccess: null, onSignOut: null, onDownload: null, + onNoAccess: null, }, }; From 097adc82d529e9cc177bed6aa232356b3a489345 Mon Sep 17 00:00:00 2001 From: Aleksandr Lushkin Date: Tue, 13 Aug 2024 17:45:19 +0200 Subject: [PATCH 03/26] Client: EditGroupStore: Fix moving manager to members without setting new manager --- packages/client/src/store/EditGroupStore.ts | 11 +++++++++++ packages/shared/api/groups/index.ts | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/packages/client/src/store/EditGroupStore.ts b/packages/client/src/store/EditGroupStore.ts index 541ace92c8..570113fd75 100644 --- a/packages/client/src/store/EditGroupStore.ts +++ b/packages/client/src/store/EditGroupStore.ts @@ -125,6 +125,17 @@ class EditGroupStore { const addedIds = Array.from(this.addedMembersMap.keys()); const removedIds = Array.from(this.removedMembersMap.keys()); + const oldManager = this.group.manager; + const oldManagerRemovedButRemainsAsMember = + oldManager && + oldManager.id !== this.manager?.id && + !this.removedMembersMap.has(oldManager.id); + + // Requires when new group is without manager and old manager moved to members. updateGroup api method doesn't provide possibility to do it without setting new manager + if (this.manager === null && oldManagerRemovedButRemainsAsMember) { + await api.groups.removeGroupMembers(this.group.id, [oldManager.id]); + addedIds.push(oldManager.id); + } await updateGroup( this.group?.id, diff --git a/packages/shared/api/groups/index.ts b/packages/shared/api/groups/index.ts index 3b54cba3b1..36b1987c68 100644 --- a/packages/shared/api/groups/index.ts +++ b/packages/shared/api/groups/index.ts @@ -146,6 +146,14 @@ export const addGroupMembers = (groupId: string, members: string) => { }); }; +export const removeGroupMembers = (groupId: string, membersIds: string[]) => { + return request({ + method: "delete", + url: `/group/${groupId}/members`, + data: { id: groupId, members: membersIds }, + }) as Promise; +}; + // * Delete export const deleteGroup = (groupId: string) => { From ca7157a5b12699ef8292cf5cf83ddcc9c98c4123 Mon Sep 17 00:00:00 2001 From: Viktor Fomin Date: Tue, 13 Aug 2024 19:02:30 +0300 Subject: [PATCH 04/26] Fix Bug 69568 Backlighting of available dates not active --- packages/shared/components/calendar/utils/getCalendarYears.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/components/calendar/utils/getCalendarYears.ts b/packages/shared/components/calendar/utils/getCalendarYears.ts index 8e0630cf57..82a2538044 100644 --- a/packages/shared/components/calendar/utils/getCalendarYears.ts +++ b/packages/shared/components/calendar/utils/getCalendarYears.ts @@ -29,7 +29,7 @@ import moment from "moment"; export const getCalendarYears = (observedDate: moment.Moment) => { const years = []; const selectedYear = observedDate.year(); - const firstYear = selectedYear - (selectedYear % 10) - 1; + const firstYear = selectedYear - 1; for (let i = firstYear; i <= firstYear + 15; i += 1) { years.push(moment(i, "YYYY").format("YYYY")); From da127707afbfa6adc0e40b14191cc73e1ee5efa7 Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Tue, 13 Aug 2024 20:42:44 +0400 Subject: [PATCH 05/26] LDAP: Remove error logging duplicate --- packages/client/src/store/LdapFormStore.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/client/src/store/LdapFormStore.js b/packages/client/src/store/LdapFormStore.js index c725630f72..ba929c76e1 100644 --- a/packages/client/src/store/LdapFormStore.js +++ b/packages/client/src/store/LdapFormStore.js @@ -518,7 +518,6 @@ class LdapFormStore { toastr.success(t("Common:SuccessfullyCompletedOperation")); } } catch (error) { - console.error(error); toastr.error(error); this.endProcess(); } From 7247363b02adc76762e5a208d63ee61c95b2283b Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Wed, 14 Aug 2024 11:17:01 +0300 Subject: [PATCH 06/26] Shared: Navigation: Disabled tariff bar inside sdk frame --- .../shared/components/navigation/sub-components/ControlBtn.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/shared/components/navigation/sub-components/ControlBtn.tsx b/packages/shared/components/navigation/sub-components/ControlBtn.tsx index ed362e6498..00f697c032 100644 --- a/packages/shared/components/navigation/sub-components/ControlBtn.tsx +++ b/packages/shared/components/navigation/sub-components/ControlBtn.tsx @@ -79,7 +79,8 @@ const ControlButtons = ({ onClick={onNavigationButtonClick} /> ) : null; - const children = tariffBar ? React.cloneElement(tariffBar, { title }) : null; + const children = + tariffBar && !isFrame ? React.cloneElement(tariffBar, { title }) : null; const isTabletView = isTablet(); const contextOptionsFolder = getContextOptionsFolder(); From 01a8d48354673a771853b0669febf7b9139fe097 Mon Sep 17 00:00:00 2001 From: Akmal Isomadinov Date: Wed, 14 Aug 2024 16:07:10 +0500 Subject: [PATCH 07/26] Shared:MediaViewer Disabled context menu in viewer --- .../media-viewer/sub-components/ImageViewer/index.tsx | 1 + .../media-viewer/sub-components/PlayerBigPlayButton/index.tsx | 4 +++- .../media-viewer/sub-components/ViewerPlayer/index.tsx | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx b/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx index 1bbd458427..9f33ad2172 100644 --- a/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx +++ b/packages/shared/components/media-viewer/sub-components/ImageViewer/index.tsx @@ -996,6 +996,7 @@ export const ImageViewer = ({ onDoubleClick={handleDoubleTapOrClick} onLoad={imageLoaded} onError={onError} + onContextMenu={(event) => event.preventDefault()} /> diff --git a/packages/shared/components/media-viewer/sub-components/PlayerBigPlayButton/index.tsx b/packages/shared/components/media-viewer/sub-components/PlayerBigPlayButton/index.tsx index 67c79059f9..8876178cc4 100644 --- a/packages/shared/components/media-viewer/sub-components/PlayerBigPlayButton/index.tsx +++ b/packages/shared/components/media-viewer/sub-components/PlayerBigPlayButton/index.tsx @@ -36,7 +36,9 @@ export const PlayerBigPlayButton = ({ if (!visible) return; return ( - + event.preventDefault()} + > ); diff --git a/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx b/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx index e908d44628..3be4de5d14 100644 --- a/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx +++ b/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx @@ -653,6 +653,7 @@ export const ViewerPlayer = ({ onDurationChange={handleDurationChange} onLoadedMetadata={handleLoadedMetaDataVideo} onPlay={() => setIsPlaying(true)} + onContextMenu={(event) => event.preventDefault()} /> Date: Wed, 14 Aug 2024 17:47:20 +0500 Subject: [PATCH 08/26] Shared:MediaViewer Fixed: player rewind functionality --- .../media-viewer/sub-components/ViewerPlayer/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx b/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx index 3be4de5d14..2845b7db6d 100644 --- a/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx +++ b/packages/shared/components/media-viewer/sub-components/ViewerPlayer/index.tsx @@ -406,6 +406,10 @@ export const ViewerPlayer = ({ const percent = Number(event.target.value); const newCurrentTime = (percent / 100) * videoRef.current.duration; + const videoCurrentTime = videoRef.current.currentTime; + + if (Math.abs(newCurrentTime - videoCurrentTime) <= 0.1) return; + handleProgress(); setTimeline(percent); setCurrentTime(newCurrentTime); From 645adf6050cfb110c4361cdfb52d210758f8e312 Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Wed, 14 Aug 2024 17:40:33 +0300 Subject: [PATCH 09/26] Shared: ErrorContainer: Fixed vertical scroll on clouds animation --- .../shared/components/error-container/ErrorContainer.styled.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/components/error-container/ErrorContainer.styled.ts b/packages/shared/components/error-container/ErrorContainer.styled.ts index b0b3556f97..8a987d39a2 100644 --- a/packages/shared/components/error-container/ErrorContainer.styled.ts +++ b/packages/shared/components/error-container/ErrorContainer.styled.ts @@ -40,7 +40,7 @@ const StyledErrorContainer = styled.div<{ isEditor: boolean }>` css` position: absolute; `} - overflow-x: hidden; + overflow: hidden; display: flex; flex-direction: column; align-items: center; From 1b250eaac01c3536b4ff3e7ac4d4e5c9468e6d44 Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Wed, 14 Aug 2024 20:15:45 +0400 Subject: [PATCH 10/26] Bug 69700 - [LDAP] Checking for incorrect LDAP server settings ends with a "successful" save --- packages/client/src/store/LdapFormStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/store/LdapFormStore.js b/packages/client/src/store/LdapFormStore.js index ba929c76e1..17a374eb53 100644 --- a/packages/client/src/store/LdapFormStore.js +++ b/packages/client/src/store/LdapFormStore.js @@ -489,7 +489,7 @@ class LdapFormStore { completed: true, percents: 100, certificateConfirmRequest: null, - error: "", + error: t("Common:UnexpectedError"), }; } From bc3728aabfec0e00668d49c61d18f7cbc200493f Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Thu, 15 Aug 2024 12:46:55 +0300 Subject: [PATCH 11/26] Client: Store: ProfileActionsStore: Fixed isTeamTrainingAlertAvailable usage --- packages/client/src/store/ProfileActionsStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/store/ProfileActionsStore.js b/packages/client/src/store/ProfileActionsStore.js index ef6ed373b4..6c620bed1d 100644 --- a/packages/client/src/store/ProfileActionsStore.js +++ b/packages/client/src/store/ProfileActionsStore.js @@ -347,7 +347,7 @@ class ProfileActionsStore { let bookTraining = null; - if (!isMobile && this.isTeamTrainingAlertAvailable) { + if (!isMobile && this.authStore.isTeamTrainingAlertAvailable) { bookTraining = { key: "user-menu-book-training", icon: BookTrainingReactSvgUrl, From 6678fbd711f8cb125380809651592378246ea10a Mon Sep 17 00:00:00 2001 From: Vlada Gazizova <94864088+gazizova-vlada@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:56:28 +0300 Subject: [PATCH 12/26] Fixed Bug 69669:Settings:Branding. A custom logo will be stretched when inviting a user to the portal. --- .../src/pages/Confirm/sub-components/StyledCreateUser.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js b/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js index a8d6aa98bf..461ebb1614 100644 --- a/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js +++ b/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js @@ -65,15 +65,13 @@ export const GreetingContainer = styled.div` .portal-logo { width: 100%; + max-width: 386px; + height: 44px; + margin: 0 auto; padding-bottom: 16px; - height: 26.56px; display: flex; align-items: center; justify-content: center; - - .injected-svg { - height: 26.56px; - } } `; From b45c92b209f3a999e5b990fbc5ac98acba2b6dd0 Mon Sep 17 00:00:00 2001 From: Vlada Gazizova <94864088+gazizova-vlada@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:32:28 +0300 Subject: [PATCH 13/26] Fixed Bug 69668:Settings:Branding. Part of the custom logo is hidden behind a QR code when activating 2FA for the first time --- .../src/pages/Confirm/sub-components/tfaActivation.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/client/src/pages/Confirm/sub-components/tfaActivation.js b/packages/client/src/pages/Confirm/sub-components/tfaActivation.js index 46ebbd7aee..6ae97dc143 100644 --- a/packages/client/src/pages/Confirm/sub-components/tfaActivation.js +++ b/packages/client/src/pages/Confirm/sub-components/tfaActivation.js @@ -97,6 +97,12 @@ const StyledForm = styled(Box)` .set-app-description { width: 100%; max-width: 500px; + + .portal-logo { + margin: 0 auto; + max-width: 386px; + height: 44px; + } } .set-app-title { From 01ff3610d0e15bf294cfd922d116b8fc3f4e103a Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Thu, 15 Aug 2024 14:19:50 +0300 Subject: [PATCH 14/26] Fix Bug 61899 - Files.Uploads. Added saving of uploaded folder after renaming --- packages/client/src/HOCs/withFileActions.js | 13 ++--- .../src/components/Article/Body/Items.js | 12 ++--- .../components/Article/MainButton/index.js | 16 ++++-- .../client/src/pages/Home/Hooks/useFiles.js | 13 ++--- .../src/pages/Home/Section/Header/index.js | 12 ++++- .../client/src/store/FilesActionsStore.js | 49 +++++++++++++------ packages/client/src/store/HotkeyStore.js | 14 ++---- packages/client/src/store/UploadDataStore.js | 5 +- 8 files changed, 71 insertions(+), 63 deletions(-) diff --git a/packages/client/src/HOCs/withFileActions.js b/packages/client/src/HOCs/withFileActions.js index a6aea017c0..730e08923a 100644 --- a/packages/client/src/HOCs/withFileActions.js +++ b/packages/client/src/HOCs/withFileActions.js @@ -67,16 +67,9 @@ export default function withFileActions(WrappedFileItem) { dragging && setDragging(false); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + uploadEmptyFolders(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; onDrop = (items) => { diff --git a/packages/client/src/components/Article/Body/Items.js b/packages/client/src/components/Article/Body/Items.js index f4b212e4fa..0de7f2ed67 100644 --- a/packages/client/src/components/Article/Body/Items.js +++ b/packages/client/src/components/Article/Body/Items.js @@ -86,16 +86,10 @@ const Item = ({ const onDropZoneUpload = React.useCallback( (files, uploadToFolder) => { dragging && setDragging(false); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + uploadEmptyFolders(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, [t, dragging, setDragging, startUpload, uploadEmptyFolders], ); diff --git a/packages/client/src/components/Article/MainButton/index.js b/packages/client/src/components/Article/MainButton/index.js index 6f1f4e0afb..10a03ddb20 100644 --- a/packages/client/src/components/Article/MainButton/index.js +++ b/packages/client/src/components/Article/MainButton/index.js @@ -70,6 +70,7 @@ import { resendInvitesAgain } from "@docspace/shared/api/people"; import { getCorrectFourValuesStyle } from "@docspace/shared/utils"; import { ArticleButtonLoader } from "@docspace/shared/skeletons/article"; import { isMobile, isTablet } from "react-device-detect"; +import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event"; const StyledButton = styled(Button)` font-weight: 700; @@ -180,6 +181,7 @@ const ArticleMainButtonContent = (props) => { parentRoomType, isFolder, + uploadEmptyFolders, } = props; const navigate = useNavigate(); @@ -239,8 +241,12 @@ const ArticleMainButtonContent = (props) => { ); const onFileChange = React.useCallback( - (e) => { - startUpload(e.target.files, null, t); + async (e) => { + const files = await getFilesFromEvent(e); + + uploadEmptyFolders(files).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, [startUpload, t], ); @@ -249,7 +255,7 @@ const ArticleMainButtonContent = (props) => { if (isPrivacy) { encryptionUploadDialog((encryptedFile, encrypted) => { encryptedFile.encrypted = encrypted; - startUpload([encryptedFile], null, t); + startUpload([encryptedFile], null, t); // TODO: uploadEmptyFolders }); } else { inputFilesElement.current.click(); @@ -901,6 +907,7 @@ export default inject( versionHistoryStore, userStore, currentTariffStatusStore, + filesActionsStore, }) => { const { showArticleLoader } = clientLoadingStore; const { mainButtonMobileVisible } = filesStore; @@ -945,6 +952,8 @@ export default inject( const { frameConfig, isFrame } = settingsStore; + const { uploadEmptyFolders } = filesActionsStore; + return { isGracePeriod, setInviteUsersWarningDialogVisible, @@ -997,6 +1006,7 @@ export default inject( isFolder, selectFileFormRoomDialogVisible, setSelectFileFormRoomDialogVisible, + uploadEmptyFolders, }; }, )( diff --git a/packages/client/src/pages/Home/Hooks/useFiles.js b/packages/client/src/pages/Home/Hooks/useFiles.js index 2f7ac09b6e..ab2a7560c7 100644 --- a/packages/client/src/pages/Home/Hooks/useFiles.js +++ b/packages/client/src/pages/Home/Hooks/useFiles.js @@ -118,16 +118,9 @@ const useFiles = ({ if (disableDrag) return; - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t); - }); - } else { - startUpload(files, uploadToFolder, t); - } + uploadEmptyFolders(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; React.useEffect(() => { diff --git a/packages/client/src/pages/Home/Section/Header/index.js b/packages/client/src/pages/Home/Section/Header/index.js index 02426716ab..82e596b32d 100644 --- a/packages/client/src/pages/Home/Section/Header/index.js +++ b/packages/client/src/pages/Home/Section/Header/index.js @@ -50,6 +50,7 @@ import { getCategoryUrl, } from "SRC_DIR/helpers/utils"; import TariffBar from "SRC_DIR/components/TariffBar"; +import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event"; const StyledContainer = styled.div` width: 100%; @@ -225,6 +226,7 @@ const SectionHeaderContent = (props) => { getHeaderOptions, setBufferSelection, setGroupsBufferSelection, + uploadEmptyFolders, } = props; const location = useLocation(); @@ -239,8 +241,12 @@ const SectionHeaderContent = (props) => { const isSettingsPage = location.pathname.includes("/settings"); const onFileChange = React.useCallback( - (e) => { - startUpload(e.target.files, null, t); + async (e) => { + const files = await getFilesFromEvent(e); + + uploadEmptyFolders(files).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }, [startUpload, t], ); @@ -639,6 +645,7 @@ export default inject( moveToRoomsPage, onClickBack, moveToPublicRoom, + uploadEmptyFolders, } = filesActionsStore; const { setIsVisible, isVisible } = infoPanelStore; @@ -802,6 +809,7 @@ export default inject( getHeaderOptions, setBufferSelection, setGroupsBufferSelection, + uploadEmptyFolders, }; }, )( diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 1349a9ec62..9727fe35ae 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -229,17 +229,21 @@ class FilesActionStore { let level = { result }; try { folders.forEach((folder) => { - folder.path - .split("/") - .filter((name) => name !== "") - .reduce((r, name, i, a) => { - if (!r[name]) { - r[name] = { result: [] }; - r.result.push({ name, children: r[name].result }); - } + const folderPath = folder.path.split("/").filter((name) => name !== ""); - return r[name]; - }, level); + folderPath.reduce((r, name, i, a) => { + if (!r[name]) { + r[name] = { result: [] }; + r.result.push({ + name, + children: r[name].result, + isFile: folderPath.length - 1 === i && !folder.isEmptyDirectory, + file: folder, + }); + } + + return r[name]; + }, level); }); } catch (e) { console.error("convertToTree", e); @@ -247,28 +251,37 @@ class FilesActionStore { return result; }; - createFolderTree = async (treeList, parentFolderId) => { + createFolderTree = async (treeList, parentFolderId, filesList) => { if (!treeList || !treeList.length) return; for (let i = 0; i < treeList.length; i++) { const treeNode = treeList[i]; + const isFile = treeList[i].isFile; // console.log( // `createFolderTree parent id = ${parentFolderId} name '${treeNode.name}': `, // treeNode.children // ); + if (isFile) { + treeList[i].file.parentFolderId = parentFolderId; + filesList.push(treeList[i].file); + continue; + } + const folder = await createFolder(parentFolderId, treeNode.name); const parentId = folder.id; if (treeNode.children.length == 0) continue; - await this.createFolderTree(treeNode.children, parentId); + await this.createFolderTree(treeNode.children, parentId, filesList); } + + return treeList; }; - uploadEmptyFolders = async (emptyFolders, folderId) => { - //console.log("uploadEmptyFolders", emptyFolders, folderId); + uploadEmptyFolders = async (files, folderId) => { + //console.log("uploadEmptyFolders", files, folderId); const { secondaryProgressDataStore } = this.uploadDataStore; const { setSecondaryProgressBarData, clearSecondaryProgressData } = @@ -287,12 +300,16 @@ class FilesActionStore { operationId, }); - const tree = this.convertToTree(emptyFolders); - await this.createFolderTree(tree, toFolderId); + const tree = this.convertToTree(files); + + const filesList = []; + await this.createFolderTree(tree, toFolderId, filesList); this.updateCurrentFolder(null, [folderId], null, operationId); setTimeout(() => clearSecondaryProgressData(operationId), TIMEOUT); + + return filesList; }; updateFilesAfterDelete = (operationId) => { diff --git a/packages/client/src/store/HotkeyStore.js b/packages/client/src/store/HotkeyStore.js index 46ed343cdb..1d5dc2fc74 100644 --- a/packages/client/src/store/HotkeyStore.js +++ b/packages/client/src/store/HotkeyStore.js @@ -685,7 +685,6 @@ class HotkeyStore { uploadClipboardFiles = async (t, event) => { const { uploadEmptyFolders } = this.filesActionsStore; const { startUpload } = this.uploadDataStore; - const currentFolderId = this.selectedFolderStore.id; if (this.filesStore.hotkeysClipboard.length) { return this.moveFilesFromClipboard(t); @@ -693,16 +692,9 @@ class HotkeyStore { const files = await getFilesFromEvent(event); - const emptyFolders = files.filter((f) => f.isEmptyDirectory); - - if (emptyFolders.length > 0) { - uploadEmptyFolders(emptyFolders, currentFolderId).then(() => { - const onlyFiles = files.filter((f) => !f.isEmptyDirectory); - if (onlyFiles.length > 0) startUpload(onlyFiles, currentFolderId, t); - }); - } else { - startUpload(files, currentFolderId, t); - } + uploadEmptyFolders(files, uploadToFolder).then((f) => { + if (f.length > 0) startUpload(f, null, t); + }); }; get countTilesInRow() { diff --git a/packages/client/src/store/UploadDataStore.js b/packages/client/src/store/UploadDataStore.js index 34f3cdb11b..711e0e6aa7 100644 --- a/packages/client/src/store/UploadDataStore.js +++ b/packages/client/src/store/UploadDataStore.js @@ -773,7 +773,8 @@ class UploadDataStore { file: file, uniqueId: uniqueid("download_row-key_"), fileId: null, - toFolderId, + // toFolderId, + toFolderId: file.parentFolderId, action: "upload", error: file.size ? null : t("Files:EmptyFile"), fileInfo: null, @@ -1372,7 +1373,7 @@ class UploadDataStore { toFolderId, fileName, fileSize, - relativePath, + "", // relativePath, file.encrypted, file.lastModifiedDate, createNewIfExist, From 86f116e62fad3bca1fa14895144b8fb99130f582 Mon Sep 17 00:00:00 2001 From: Viktor Fomin Date: Thu, 15 Aug 2024 14:44:33 +0300 Subject: [PATCH 15/26] Fix Bug 69670 No name centering --- .../src/pages/Confirm/sub-components/StyledCreateUser.js | 5 ++++- .../client/src/pages/Confirm/sub-components/createUser.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js b/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js index 461ebb1614..8ff8d3adf4 100644 --- a/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js +++ b/packages/client/src/pages/Confirm/sub-components/StyledCreateUser.js @@ -54,7 +54,10 @@ export const GreetingContainer = styled.div` } .tooltip { - p { + .invitation-text { + display: flex; + flex-direction: column; + align-items: center; text-align: center; } diff --git a/packages/client/src/pages/Confirm/sub-components/createUser.js b/packages/client/src/pages/Confirm/sub-components/createUser.js index 99eb5e95f6..fcd1292fea 100644 --- a/packages/client/src/pages/Confirm/sub-components/createUser.js +++ b/packages/client/src/pages/Confirm/sub-components/createUser.js @@ -485,7 +485,7 @@ const CreateUserForm = (props) => { {linkData.type === "LinkInvite" && (
- + {roomName ? ( Date: Thu, 15 Aug 2024 14:54:54 +0300 Subject: [PATCH 16/26] Shared: Utils: Fixed force redirect inside frame on 401 response --- packages/shared/utils/axiosClient.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/shared/utils/axiosClient.ts b/packages/shared/utils/axiosClient.ts index c035f9e298..cec4503331 100644 --- a/packages/shared/utils/axiosClient.ts +++ b/packages/shared/utils/axiosClient.ts @@ -220,10 +220,12 @@ class AxiosClient { } const loginURL = combineUrl(proxyURL, "/login"); + if (!this.isSSR) { switch (error.response?.status) { case 401: { - if (options.skipUnauthorized) return Promise.resolve(); + if (options.skipUnauthorized || window?.ClientConfig?.isFrame) + return Promise.resolve(); if (options.skipLogout) return Promise.reject(error); const opt: AxiosRequestConfig = { @@ -244,14 +246,13 @@ class AxiosClient { break; case 403: { const pathname = window.location.pathname; - const isFrame = window?.ClientConfig?.isFrame; const isArchived = pathname.indexOf("/rooms/archived") !== -1; const isRooms = pathname.indexOf("/rooms/shared") !== -1 || isArchived; - if (isRooms && !skipRedirect && !isFrame) { + if (isRooms && !skipRedirect && !window?.ClientConfig?.isFrame) { setTimeout(() => { window.DocSpace.navigate(isArchived ? "/archived" : "/"); }, 1000); From 70b0942dfb82517e50d133a786b16187322dc119 Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Thu, 15 Aug 2024 16:13:18 +0400 Subject: [PATCH 17/26] Bug 69519 - Accounts. Sorting by Last name field does not work --- .../client/src/pages/Home/Section/Filter/index.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/client/src/pages/Home/Section/Filter/index.js b/packages/client/src/pages/Home/Section/Filter/index.js index ca0e12ffb4..035cf37d16 100644 --- a/packages/client/src/pages/Home/Section/Filter/index.js +++ b/packages/client/src/pages/Home/Section/Filter/index.js @@ -1963,14 +1963,7 @@ const SectionFilterContent = ({ const firstName = { id: "sort-by_first-name", key: "firstname", - label: t("Common:FirstName"), - default: true, - }; - - const lastName = { - id: "sort-by_last-name", - key: "lastname", - label: t("Common:LastName"), + label: t("Common:Name"), default: true, }; @@ -2012,7 +2005,7 @@ const SectionFilterContent = ({ hideableColumns.Storage = storage; } - options.push(firstName, lastName, type, department, email); + options.push(firstName, type, department, email); if (showStorageInfo) options.push(storage); return options; From d2fec0391db7a93c891a3c8e07e50ac81d8c347c Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Thu, 15 Aug 2024 15:37:15 +0300 Subject: [PATCH 18/26] Web: Files: renamed uploadEmptyFolders to createFoldersTree --- packages/client/src/HOCs/withFileActions.js | 8 ++++---- .../client/src/components/Article/Body/Items.js | 16 ++++++++-------- .../src/components/Article/MainButton/index.js | 10 +++++----- packages/client/src/pages/Home/Hooks/useFiles.js | 4 ++-- .../src/pages/Home/Section/Header/index.js | 8 ++++---- packages/client/src/pages/Home/index.js | 8 ++++---- packages/client/src/store/FilesActionsStore.js | 4 ++-- packages/client/src/store/HotkeyStore.js | 4 ++-- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/client/src/HOCs/withFileActions.js b/packages/client/src/HOCs/withFileActions.js index 730e08923a..105767bbaa 100644 --- a/packages/client/src/HOCs/withFileActions.js +++ b/packages/client/src/HOCs/withFileActions.js @@ -62,12 +62,12 @@ export default function withFileActions(WrappedFileItem) { }; onDropZoneUpload = (files, uploadToFolder) => { - const { t, dragging, setDragging, startUpload, uploadEmptyFolders } = + const { t, dragging, setDragging, startUpload, createFoldersTree } = this.props; dragging && setDragging(false); - uploadEmptyFolders(files, uploadToFolder).then((f) => { + createFoldersTree(files, uploadToFolder).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }; @@ -364,7 +364,7 @@ export default function withFileActions(WrappedFileItem) { onSelectItem, //setNewBadgeCount, openFileAction, - uploadEmptyFolders, + createFoldersTree, } = filesActionsStore; const { setSharingPanelVisible } = dialogsStore; const { @@ -468,7 +468,7 @@ export default function withFileActions(WrappedFileItem) { dragging, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, draggable, setTooltipPosition, setStartDrag, diff --git a/packages/client/src/components/Article/Body/Items.js b/packages/client/src/components/Article/Body/Items.js index 0de7f2ed67..e06439b783 100644 --- a/packages/client/src/components/Article/Body/Items.js +++ b/packages/client/src/components/Article/Body/Items.js @@ -68,7 +68,7 @@ const Item = ({ onBadgeClick, showDragItems, startUpload, - uploadEmptyFolders, + createFoldersTree, setDragging, showBadge, labelBadge, @@ -87,11 +87,11 @@ const Item = ({ (files, uploadToFolder) => { dragging && setDragging(false); - uploadEmptyFolders(files, uploadToFolder).then((f) => { + createFoldersTree(files, uploadToFolder).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }, - [t, dragging, setDragging, startUpload, uploadEmptyFolders], + [t, dragging, setDragging, startUpload, createFoldersTree], ); const onDrop = React.useCallback( @@ -187,7 +187,7 @@ const Items = ({ dragging, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, isVisitor, isCollaborator, isAdmin, @@ -320,7 +320,7 @@ const Items = ({ t={t} setDragging={setDragging} startUpload={startUpload} - uploadEmptyFolders={uploadEmptyFolders} + createFoldersTree={createFoldersTree} item={item} setBufferSelection={setBufferSelection} dragging={dragging} @@ -382,7 +382,7 @@ const Items = ({ showText, setDragging, startUpload, - uploadEmptyFolders, + createFoldersTree, trashIsEmpty, isAdmin, isVisitor, @@ -443,7 +443,7 @@ export default inject( const { id, access: folderAccess } = selectedFolderStore; const { moveDragItems, - uploadEmptyFolders, + createFoldersTree, deleteAction, emptyTrashInProgress, } = filesActionsStore; @@ -472,7 +472,7 @@ export default inject( setBufferSelection, deleteAction, startUpload, - uploadEmptyFolders, + createFoldersTree, setEmptyTrashDialogVisible, trashIsEmpty, diff --git a/packages/client/src/components/Article/MainButton/index.js b/packages/client/src/components/Article/MainButton/index.js index 10a03ddb20..a92377d711 100644 --- a/packages/client/src/components/Article/MainButton/index.js +++ b/packages/client/src/components/Article/MainButton/index.js @@ -181,7 +181,7 @@ const ArticleMainButtonContent = (props) => { parentRoomType, isFolder, - uploadEmptyFolders, + createFoldersTree, } = props; const navigate = useNavigate(); @@ -244,7 +244,7 @@ const ArticleMainButtonContent = (props) => { async (e) => { const files = await getFilesFromEvent(e); - uploadEmptyFolders(files).then((f) => { + createFoldersTree(files).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }, @@ -255,7 +255,7 @@ const ArticleMainButtonContent = (props) => { if (isPrivacy) { encryptionUploadDialog((encryptedFile, encrypted) => { encryptedFile.encrypted = encrypted; - startUpload([encryptedFile], null, t); // TODO: uploadEmptyFolders + startUpload([encryptedFile], null, t); // TODO: createFoldersTree }); } else { inputFilesElement.current.click(); @@ -952,7 +952,7 @@ export default inject( const { frameConfig, isFrame } = settingsStore; - const { uploadEmptyFolders } = filesActionsStore; + const { createFoldersTree } = filesActionsStore; return { isGracePeriod, @@ -1006,7 +1006,7 @@ export default inject( isFolder, selectFileFormRoomDialogVisible, setSelectFileFormRoomDialogVisible, - uploadEmptyFolders, + createFoldersTree, }; }, )( diff --git a/packages/client/src/pages/Home/Hooks/useFiles.js b/packages/client/src/pages/Home/Hooks/useFiles.js index ab2a7560c7..f4e4a4baae 100644 --- a/packages/client/src/pages/Home/Hooks/useFiles.js +++ b/packages/client/src/pages/Home/Hooks/useFiles.js @@ -52,7 +52,7 @@ const useFiles = ({ dragging, setDragging, disableDrag, - uploadEmptyFolders, + createFoldersTree, startUpload, fetchFiles, @@ -118,7 +118,7 @@ const useFiles = ({ if (disableDrag) return; - uploadEmptyFolders(files, uploadToFolder).then((f) => { + createFoldersTree(files, uploadToFolder).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }; diff --git a/packages/client/src/pages/Home/Section/Header/index.js b/packages/client/src/pages/Home/Section/Header/index.js index 82e596b32d..9dcf561add 100644 --- a/packages/client/src/pages/Home/Section/Header/index.js +++ b/packages/client/src/pages/Home/Section/Header/index.js @@ -226,7 +226,7 @@ const SectionHeaderContent = (props) => { getHeaderOptions, setBufferSelection, setGroupsBufferSelection, - uploadEmptyFolders, + createFoldersTree, } = props; const location = useLocation(); @@ -244,7 +244,7 @@ const SectionHeaderContent = (props) => { async (e) => { const files = await getFilesFromEvent(e); - uploadEmptyFolders(files).then((f) => { + createFoldersTree(files).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }, @@ -645,7 +645,7 @@ export default inject( moveToRoomsPage, onClickBack, moveToPublicRoom, - uploadEmptyFolders, + createFoldersTree, } = filesActionsStore; const { setIsVisible, isVisible } = infoPanelStore; @@ -809,7 +809,7 @@ export default inject( getHeaderOptions, setBufferSelection, setGroupsBufferSelection, - uploadEmptyFolders, + createFoldersTree, }; }, )( diff --git a/packages/client/src/pages/Home/index.js b/packages/client/src/pages/Home/index.js index 197ad6b00a..d9015a5320 100644 --- a/packages/client/src/pages/Home/index.js +++ b/packages/client/src/pages/Home/index.js @@ -82,7 +82,7 @@ const PureHome = (props) => { startUpload, setDragging, dragging, - uploadEmptyFolders, + createFoldersTree, disableDrag, uploaded, converted, @@ -182,7 +182,7 @@ const PureHome = (props) => { dragging, setDragging, disableDrag, - uploadEmptyFolders, + createFoldersTree, startUpload, fetchFiles, fetchRooms, @@ -543,7 +543,7 @@ export default inject( const { setUploadPanelVisible, startUpload, uploaded, converted } = uploadDataStore; - const { uploadEmptyFolders, onClickBack } = filesActionsStore; + const { createFoldersTree, onClickBack } = filesActionsStore; const selectionLength = isProgressFinished ? selection.length : null; const selectionTitle = isProgressFinished @@ -635,7 +635,7 @@ export default inject( setUploadPanelVisible, startUpload, - uploadEmptyFolders, + createFoldersTree, setToPreviewFile, setIsPreview, diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 9727fe35ae..2626d5a08b 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -280,8 +280,8 @@ class FilesActionStore { return treeList; }; - uploadEmptyFolders = async (files, folderId) => { - //console.log("uploadEmptyFolders", files, folderId); + createFoldersTree = async (files, folderId) => { + //console.log("createFoldersTree", files, folderId); const { secondaryProgressDataStore } = this.uploadDataStore; const { setSecondaryProgressBarData, clearSecondaryProgressData } = diff --git a/packages/client/src/store/HotkeyStore.js b/packages/client/src/store/HotkeyStore.js index 1d5dc2fc74..559ed6d98d 100644 --- a/packages/client/src/store/HotkeyStore.js +++ b/packages/client/src/store/HotkeyStore.js @@ -683,7 +683,7 @@ class HotkeyStore { }; uploadClipboardFiles = async (t, event) => { - const { uploadEmptyFolders } = this.filesActionsStore; + const { createFoldersTree } = this.filesActionsStore; const { startUpload } = this.uploadDataStore; if (this.filesStore.hotkeysClipboard.length) { @@ -692,7 +692,7 @@ class HotkeyStore { const files = await getFilesFromEvent(event); - uploadEmptyFolders(files, uploadToFolder).then((f) => { + createFoldersTree(files, uploadToFolder).then((f) => { if (f.length > 0) startUpload(f, null, t); }); }; From 706380fcbf382abe37aada9372a95adeb7244f01 Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Thu, 15 Aug 2024 16:55:39 +0400 Subject: [PATCH 19/26] Fix Bug 69519 - Accounts. Sorting by Last name field does not work --- .../InsideGroup/TableView/TableHeader.js | 16 +++------------- .../AccountsBody/People/TableView/TableHeader.js | 9 +++------ .../src/pages/Home/Section/Filter/index.js | 4 ++-- packages/shared/api/people/filter.js | 2 +- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/packages/client/src/pages/Home/Section/AccountsBody/InsideGroup/TableView/TableHeader.js b/packages/client/src/pages/Home/Section/AccountsBody/InsideGroup/TableView/TableHeader.js index 94df06e920..5783767e86 100644 --- a/packages/client/src/pages/Home/Section/AccountsBody/InsideGroup/TableView/TableHeader.js +++ b/packages/client/src/pages/Home/Section/AccountsBody/InsideGroup/TableView/TableHeader.js @@ -138,15 +138,8 @@ class InsideGroupTableHeader extends React.Component { newFilter.sortBy = sortBy; if (sortBy === "AZ") { - if ( - newFilter.sortBy !== "lastname" && - newFilter.sortBy !== "firstname" - ) { - newFilter.sortBy = "firstname"; - } else if (newFilter.sortBy === "lastname") { - newFilter.sortBy = "firstname"; - } else { - newFilter.sortBy = "lastname"; + if (newFilter.sortBy !== "displayname") { + newFilter.sortBy = "displayname"; } newFilter.sortOrder = newFilter.sortOrder === "ascending" ? "descending" : "ascending"; @@ -176,10 +169,7 @@ class InsideGroupTableHeader extends React.Component { } = this.props; const { sortOrder } = filter; - const sortBy = - filter.sortBy === "firstname" || filter.sortBy === "lastname" - ? "AZ" - : filter.sortBy; + const sortBy = filter.sortBy === "displayname" ? "AZ" : filter.sortBy; return ( Date: Thu, 15 Aug 2024 16:07:20 +0300 Subject: [PATCH 20/26] JS-SDK: Added onContentReady event --- public/scripts/sdk/1.0.1/api.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/scripts/sdk/1.0.1/api.js b/public/scripts/sdk/1.0.1/api.js index cb263c3245..a5247f8a0f 100644 --- a/public/scripts/sdk/1.0.1/api.js +++ b/public/scripts/sdk/1.0.1/api.js @@ -98,6 +98,7 @@ onSignOut: null, onDownload: null, onNoAccess: null, + onContentReady: null, }, }; @@ -814,7 +815,10 @@ targetFrame.style.height = this.config.height; targetFrame.parentNode.style.height = "inherit"; - if (loader) loader.remove(); + if (loader) { + loader.remove(); + this.config.events.onContentReady(); + } } } From 514680958b699a8afbf6099e553e1a142d88511f Mon Sep 17 00:00:00 2001 From: Ilya Oleshko Date: Thu, 15 Aug 2024 17:02:48 +0300 Subject: [PATCH 21/26] Client: InfoPanel: Body: Fixed align items to baseline --- .../client/src/pages/Home/InfoPanel/Body/styles/common.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/Home/InfoPanel/Body/styles/common.js b/packages/client/src/pages/Home/InfoPanel/Body/styles/common.js index 2332db4d55..fb45cf0d15 100644 --- a/packages/client/src/pages/Home/InfoPanel/Body/styles/common.js +++ b/packages/client/src/pages/Home/InfoPanel/Body/styles/common.js @@ -264,8 +264,8 @@ const StyledProperties = styled.div` grid-template-columns: 120px 1fr; grid-column-gap: 24px; - -webkit-box-align: center; - align-items: center; + -webkit-box-align: baseline; + align-items: baseline; .property-title { font-size: 13px; From 5b415b588bc81bbf0ebeefe5d9f480eedb04c9de Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Thu, 15 Aug 2024 18:05:53 +0300 Subject: [PATCH 22/26] Web: Files: removed secondary loader if only files are uploaded --- .../client/src/store/FilesActionsStore.js | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 2626d5a08b..346cc3e20a 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -251,7 +251,12 @@ class FilesActionStore { return result; }; - createFolderTree = async (treeList, parentFolderId, filesList) => { + createFolderTree = async ( + treeList, + parentFolderId, + filesList, + operationId, + ) => { if (!treeList || !treeList.length) return; for (let i = 0; i < treeList.length; i++) { @@ -269,12 +274,28 @@ class FilesActionStore { continue; } + this.uploadDataStore.secondaryProgressDataStore.setSecondaryProgressBarData( + { + icon: "file", + visible: true, + percent: 0, + label: "", + alert: false, + operationId, + }, + ); + const folder = await createFolder(parentFolderId, treeNode.name); const parentId = folder.id; if (treeNode.children.length == 0) continue; - await this.createFolderTree(treeNode.children, parentId, filesList); + await this.createFolderTree( + treeNode.children, + parentId, + filesList, + operationId, + ); } return treeList; @@ -284,26 +305,16 @@ class FilesActionStore { //console.log("createFoldersTree", files, folderId); const { secondaryProgressDataStore } = this.uploadDataStore; - const { setSecondaryProgressBarData, clearSecondaryProgressData } = - secondaryProgressDataStore; + const { clearSecondaryProgressData } = secondaryProgressDataStore; const operationId = uniqueid("operation_"); const toFolderId = folderId ? folderId : this.selectedFolderStore.id; - setSecondaryProgressBarData({ - icon: "file", - visible: true, - percent: 0, - label: "", - alert: false, - operationId, - }); - const tree = this.convertToTree(files); const filesList = []; - await this.createFolderTree(tree, toFolderId, filesList); + await this.createFolderTree(tree, toFolderId, filesList, operationId); this.updateCurrentFolder(null, [folderId], null, operationId); From b4840a28071c5b55347d5c6f0c4d3921fed470ac Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Thu, 15 Aug 2024 19:17:14 +0400 Subject: [PATCH 23/26] Fix Bug 66831 - Rooms: Invite via link. Console error 500 (Internal Server Error) when regenerating the invitation link. --- .../InvitePanel/sub-components/ExternalLinks.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/panels/InvitePanel/sub-components/ExternalLinks.js b/packages/client/src/components/panels/InvitePanel/sub-components/ExternalLinks.js index a247277c03..93c53609fe 100644 --- a/packages/client/src/components/panels/InvitePanel/sub-components/ExternalLinks.js +++ b/packages/client/src/components/panels/InvitePanel/sub-components/ExternalLinks.js @@ -88,7 +88,7 @@ const ExternalLinks = ({ copyLink(link.shareLink); } } else { - !externalLinksVisible ? editLink() : disableLink(); + !externalLinksVisible ? await editLink() : await disableLink(); } onChangeExternalLinksVisible(!externalLinksVisible); } catch (error) { @@ -98,9 +98,10 @@ const ExternalLinks = ({ } }; - const disableLink = () => { - setInvitationLinks(roomId, "Invite", 0, shareLinks[0].id); - setShareLinks([]); + const disableLink = async () => { + shareLinks?.length && + (await setInvitationLinks(roomId, "Invite", 0, shareLinks[0].id)); + return setShareLinks([]); }; const editLink = async () => { @@ -120,7 +121,7 @@ const ExternalLinks = ({ copyLink(shareLink); setShareLinks([activeLink]); - setActiveLink(activeLink); + return setActiveLink(activeLink); }; const onSelectAccess = async (access) => { From 6d5c567da4e369a3336f0acc45da5a839709ca0a Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Thu, 15 Aug 2024 18:22:03 +0300 Subject: [PATCH 24/26] Web: Components: Section: fixed closing the context menu when uploading files --- .../components/section/Section.types.ts | 4 + .../section/sub-components/SectionBody.tsx | 67 +--------------- .../sub-components/SectionContextMenu.tsx | 80 +++++++++++++++++++ 3 files changed, 88 insertions(+), 63 deletions(-) create mode 100644 packages/shared/components/section/sub-components/SectionContextMenu.tsx diff --git a/packages/shared/components/section/Section.types.ts b/packages/shared/components/section/Section.types.ts index 061b602129..90ad52348f 100644 --- a/packages/shared/components/section/Section.types.ts +++ b/packages/shared/components/section/Section.types.ts @@ -145,3 +145,7 @@ export interface SectionProps { isDesktop?: boolean; getContextModel?: () => ContextMenuModel[]; } + +export interface SectionContextMenuProps { + getContextModel: () => ContextMenuModel[]; +} diff --git a/packages/shared/components/section/sub-components/SectionBody.tsx b/packages/shared/components/section/sub-components/SectionBody.tsx index 914a2e92c6..eba713e65f 100644 --- a/packages/shared/components/section/sub-components/SectionBody.tsx +++ b/packages/shared/components/section/sub-components/SectionBody.tsx @@ -29,14 +29,13 @@ import { useLocation } from "react-router-dom"; // import { inject, observer } from "mobx-react"; -import { ContextMenu } from "@docspace/shared/components/context-menu"; - import { StyledDropZoneBody, StyledSpacer, StyledSectionBody, } from "../Section.styled"; import { SectionBodyProps } from "../Section.types"; +import SectionContextMenu from "./SectionContextMenu"; const SectionBody = React.memo( ({ @@ -53,49 +52,9 @@ const SectionBody = React.memo( getContextModel, }: SectionBodyProps) => { const focusRef = React.useRef(null); - const cmRef = React.useRef void; - hide: (e: React.MouseEvent | MouseEvent) => void; - toggle: (e: React.MouseEvent | MouseEvent) => boolean; - getVisible: () => boolean; - }>(null); + const location = useLocation(); - const [isOpen, setIsOpen] = React.useState(false); - - const onContextMenu = React.useCallback( - (e: MouseEvent | React.MouseEvent) => { - const bodyElem = document.getElementsByClassName( - "section-body", - )[0] as HTMLDivElement; - - const target = e.target as Node; - - if ( - !getContextModel || - !getContextModel() || - !bodyElem || - !bodyElem.contains(target) - ) - return; - - e.stopPropagation(); - e.preventDefault(); - - // if (cmRef.current) cmRef.current.toggle(e); - if (cmRef.current) { - if (!isOpen) cmRef?.current?.show(e); - else cmRef?.current?.hide(e); - setIsOpen(!isOpen); - } - }, - [getContextModel, isOpen], - ); - - const onHide = () => { - setIsOpen(false); - }; - const focusSectionBody = React.useCallback(() => { if (focusRef.current) focusRef.current.focus({ preventScroll: true }); }, []); @@ -108,14 +67,6 @@ const SectionBody = React.memo( [focusSectionBody], ); - React.useEffect(() => { - document.addEventListener("contextmenu", onContextMenu); - - return () => { - document.removeEventListener("contextmenu", onContextMenu); - }; - }, [onContextMenu]); - React.useEffect(() => { if (!autoFocus) return; @@ -145,16 +96,6 @@ const SectionBody = React.memo( } : {}; - const contextBlock = ( - - ); - return uploadFiles ? ( )} - {contextBlock} + ) : ( {children}
)} - {contextBlock} + ); }, diff --git a/packages/shared/components/section/sub-components/SectionContextMenu.tsx b/packages/shared/components/section/sub-components/SectionContextMenu.tsx new file mode 100644 index 0000000000..7dafb4b03a --- /dev/null +++ b/packages/shared/components/section/sub-components/SectionContextMenu.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import { ContextMenu } from "@docspace/shared/components/context-menu"; +import isEqual from "lodash/isEqual"; +import { SectionContextMenuProps } from "../Section.types"; + +const areEqual = ( + prevProps: SectionContextMenuProps, + nextProps: SectionContextMenuProps, +) => { + if (!isEqual(prevProps, nextProps)) return true; + return false; +}; + +const SectionContextMenu = React.memo( + ({ getContextModel }: SectionContextMenuProps) => { + const [isOpen, setIsOpen] = React.useState(false); + + const cmRef = React.useRef void; + hide: (e: React.MouseEvent | MouseEvent) => void; + toggle: (e: React.MouseEvent | MouseEvent) => boolean; + getVisible: () => boolean; + }>(null); + + const onHide = () => { + setIsOpen(false); + }; + + const onContextMenu = React.useCallback( + (e: MouseEvent | React.MouseEvent) => { + const bodyElem = document.getElementsByClassName( + "section-body", + )[0] as HTMLDivElement; + + const target = e.target as Node; + + if ( + !getContextModel || + !getContextModel() || + !bodyElem || + !bodyElem.contains(target) + ) + return; + + e.stopPropagation(); + e.preventDefault(); + + // if (cmRef.current) cmRef.current.toggle(e); + if (cmRef.current) { + if (!isOpen) cmRef?.current?.show(e); + else cmRef?.current?.hide(e); + setIsOpen(!isOpen); + } + }, + [getContextModel, isOpen], + ); + + React.useEffect(() => { + document.addEventListener("contextmenu", onContextMenu); + + return () => { + document.removeEventListener("contextmenu", onContextMenu); + }; + }, [onContextMenu]); + + return ( + + ); + }, + areEqual, +); +SectionContextMenu.displayName = "SectionContextMenu"; + +export default SectionContextMenu; From 9886bda17a699c2a0fc2fc33df2119dbc2f466a1 Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Thu, 15 Aug 2024 18:32:41 +0300 Subject: [PATCH 25/26] Web: Files: fixed loader for createFolderTree function --- .../client/src/store/FilesActionsStore.js | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/client/src/store/FilesActionsStore.js b/packages/client/src/store/FilesActionsStore.js index 346cc3e20a..0cb008057d 100644 --- a/packages/client/src/store/FilesActionsStore.js +++ b/packages/client/src/store/FilesActionsStore.js @@ -251,12 +251,7 @@ class FilesActionStore { return result; }; - createFolderTree = async ( - treeList, - parentFolderId, - filesList, - operationId, - ) => { + createFolderTree = async (treeList, parentFolderId, filesList) => { if (!treeList || !treeList.length) return; for (let i = 0; i < treeList.length; i++) { @@ -274,28 +269,12 @@ class FilesActionStore { continue; } - this.uploadDataStore.secondaryProgressDataStore.setSecondaryProgressBarData( - { - icon: "file", - visible: true, - percent: 0, - label: "", - alert: false, - operationId, - }, - ); - const folder = await createFolder(parentFolderId, treeNode.name); const parentId = folder.id; if (treeNode.children.length == 0) continue; - await this.createFolderTree( - treeNode.children, - parentId, - filesList, - operationId, - ); + await this.createFolderTree(treeNode.children, parentId, filesList); } return treeList; @@ -304,21 +283,33 @@ class FilesActionStore { createFoldersTree = async (files, folderId) => { //console.log("createFoldersTree", files, folderId); - const { secondaryProgressDataStore } = this.uploadDataStore; - const { clearSecondaryProgressData } = secondaryProgressDataStore; + const { primaryProgressDataStore } = this.uploadDataStore; + + const { setPrimaryProgressBarData, clearPrimaryProgressData } = + primaryProgressDataStore; const operationId = uniqueid("operation_"); const toFolderId = folderId ? folderId : this.selectedFolderStore.id; + setPrimaryProgressBarData({ + icon: "upload", + visible: true, + percent: 0, + label: "", + alert: false, + }); + const tree = this.convertToTree(files); const filesList = []; - await this.createFolderTree(tree, toFolderId, filesList, operationId); + await this.createFolderTree(tree, toFolderId, filesList); this.updateCurrentFolder(null, [folderId], null, operationId); - setTimeout(() => clearSecondaryProgressData(operationId), TIMEOUT); + if (!filesList.length) { + setTimeout(() => clearPrimaryProgressData(), TIMEOUT); + } return filesList; }; From cf4795c2782f61bebf9237056a4cd7be16e90e0b Mon Sep 17 00:00:00 2001 From: Alexey Safronov Date: Fri, 16 Aug 2024 01:23:22 +0400 Subject: [PATCH 26/26] Client: Upload files: styling password error + remove display duplicated toasts --- packages/client/public/locales/en/Files.json | 1 + packages/client/src/store/UploadDataStore.js | 48 ++++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/packages/client/public/locales/en/Files.json b/packages/client/public/locales/en/Files.json index 1597d2ab33..3d8601db58 100644 --- a/packages/client/public/locales/en/Files.json +++ b/packages/client/public/locales/en/Files.json @@ -117,6 +117,7 @@ "OpenLocation": "Open location", "PasswordAccess": "Password access", "PasswordLink": "Add a password to protect your link.", + "PasswordProtectedFiles": "Please <0>enter a password for the protected files to continue", "PasswordSuccessfullyCopied": "Password successfully copied", "Pin": "Pin", "PinToTop": "Pin to top", diff --git a/packages/client/src/store/UploadDataStore.js b/packages/client/src/store/UploadDataStore.js index 711e0e6aa7..50c4ed7f0e 100644 --- a/packages/client/src/store/UploadDataStore.js +++ b/packages/client/src/store/UploadDataStore.js @@ -25,9 +25,11 @@ // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode import { makeAutoObservable, runInAction } from "mobx"; +import { Trans } from "react-i18next"; import { TIMEOUT } from "@docspace/client/src/helpers/filesConstants"; import uniqueid from "lodash/uniqueId"; import sumBy from "lodash/sumBy"; +import uniqBy from "lodash/uniqBy"; import { ConflictResolveType } from "@docspace/shared/enums"; import { getFileInfo, @@ -57,6 +59,8 @@ import { getCategoryTypeByFolderType, getCategoryUrl, } from "SRC_DIR/helpers/utils"; +import { Link } from "@docspace/shared/components/link"; +import { globalColors } from "@docspace/shared/themes"; class UploadDataStore { settingsStore; @@ -636,7 +640,7 @@ class UploadDataStore { if (this.uploaded || (this.isParallel && allFilesIsUploaded)) { this.setConversionPercent(100); - this.finishUploadFiles(); + this.finishUploadFiles(t); } else { runInAction(() => { this.converted = true; @@ -1264,7 +1268,7 @@ class UploadDataStore { let files = this.files; if (files.length === 0 || this.filesSize === 0) { - return this.finishUploadFiles(); + return this.finishUploadFiles(t); } const progressData = { @@ -1311,7 +1315,7 @@ class UploadDataStore { } if (!this.filesToConversion.length) { - this.finishUploadFiles(); + this.finishUploadFiles(t); } else { runInAction(() => { this.uploaded = true; @@ -1513,7 +1517,7 @@ class UploadDataStore { if (allFilesIsUploaded) { if (!this.filesToConversion.length) { - this.finishUploadFiles(); + this.finishUploadFiles(t); } else { runInAction(() => { this.uploaded = true; @@ -1543,7 +1547,7 @@ class UploadDataStore { }); }; - finishUploadFiles = () => { + finishUploadFiles = (t) => { const { fetchFiles, filter } = this.filesStore; const { withPaging } = this.settingsStore; @@ -1555,7 +1559,7 @@ class UploadDataStore { this.asyncUploadObj = {}; for (let item of this.tempFiles) { - const { uploadFiles, folderId, t } = item; + const { uploadFiles, folderId } = item; this.startUpload(uploadFiles, folderId, t); } this.tempFiles = []; @@ -1563,12 +1567,36 @@ class UploadDataStore { return; } - const totalErrorsCount = sumBy(this.files, (f) => { - f.error && toastr.error(f.error); - return f.error ? 1 : 0; - }); + const filesWithErrors = this.files.filter((f) => f.error); + + const totalErrorsCount = filesWithErrors.length; if (totalErrorsCount > 0) { + const uniqErrors = uniqBy(filesWithErrors, "error"); + uniqErrors.forEach((f) => + f.error.indexOf("password") > -1 + ? toastr.warning( + { + toastr.clear(); + this.setUploadPanelVisible(true); + }} + />, + ]} + />, + null, + 60000, + true, + ) + : toastr.error(f.error), + ); + this.primaryProgressDataStore.setPrimaryProgressBarShowError(true); // for empty file this.primaryProgressDataStore.setPrimaryProgressBarErrors( totalErrorsCount,