🐛 Fix download button (#172)
* Fix on context menu for folder * Make it works for My Drive * Fix downloading folder in the shared view --------- Co-authored-by: Anton SHEPILOV <ashepilov@linagora.com>
This commit is contained in:
-128
@@ -1,128 +0,0 @@
|
|||||||
*.DS_Store
|
|
||||||
|
|
||||||
# User-specific stuff:
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/dictionaries
|
|
||||||
|
|
||||||
# Sensitive or high-churn files:
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.xml
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
|
|
||||||
# Gradle:
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-debug/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin:
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
## File-based project format:
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
## Plugin-specific files:
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
/out/
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# *.iml
|
|
||||||
# modules.xml
|
|
||||||
# .idea/misc.xml
|
|
||||||
# *.ipr
|
|
||||||
|
|
||||||
# Sonarlint plugin
|
|
||||||
.idea/sonarlint
|
|
||||||
|
|
||||||
### Symfony ###
|
|
||||||
# Cache and logs (Symfony2)
|
|
||||||
/app/cache/*
|
|
||||||
/app/logs/*
|
|
||||||
!app/cache/.gitkeep
|
|
||||||
!app/logs/.gitkeep
|
|
||||||
|
|
||||||
# Email spool folder
|
|
||||||
/app/spool/*
|
|
||||||
|
|
||||||
# Cache, session files and logs (Symfony3)
|
|
||||||
/var/cache/*
|
|
||||||
/var/logs/*
|
|
||||||
/var/sessions/*
|
|
||||||
!var/cache/.gitkeep
|
|
||||||
!var/logs/.gitkeep
|
|
||||||
!var/sessions/.gitkeep
|
|
||||||
|
|
||||||
# Parameters
|
|
||||||
/app/config/parameters.yml
|
|
||||||
/app/config/parameters.ini
|
|
||||||
|
|
||||||
# Managed by Composer
|
|
||||||
/bin/*
|
|
||||||
!bin/console
|
|
||||||
!bin/symfony_requirements
|
|
||||||
|
|
||||||
# Assets and user uploads
|
|
||||||
/web/bundles/
|
|
||||||
/web/uploads/
|
|
||||||
/web/upload/
|
|
||||||
/web/public/
|
|
||||||
|
|
||||||
# Build data
|
|
||||||
/build/
|
|
||||||
/builds/
|
|
||||||
|
|
||||||
# Backup entities generated with doctrine:generate:entities command
|
|
||||||
**/Entity/*~
|
|
||||||
|
|
||||||
### Symfony Patch ###
|
|
||||||
/web/css/
|
|
||||||
/web/js/
|
|
||||||
docker-compose.yml
|
|
||||||
|
|
||||||
### Dev ###
|
|
||||||
/docker-data/*
|
|
||||||
/docker/data/*
|
|
||||||
/tdrive/docker-data/*
|
|
||||||
/tdrive/docker-data
|
|
||||||
/tdrive/backend/websockets_server/false
|
|
||||||
|
|
||||||
### Tdrive specific ###
|
|
||||||
/build/
|
|
||||||
/vendor/
|
|
||||||
/app/Ressources/DatabaseEncryption/.HaliteEncryptor.key
|
|
||||||
/app/Ressources/DatabaseEncryption/.Halite.key
|
|
||||||
/backend/websockets_server/false/
|
|
||||||
|
|
||||||
### Test ###
|
|
||||||
/tests/code_coverage/
|
|
||||||
/web/detached/*
|
|
||||||
/drive/*
|
|
||||||
userreport.sh
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
log-workforce.sh
|
|
||||||
.dccache
|
|
||||||
Generated
+4823
-6686
File diff suppressed because it is too large
Load Diff
@@ -290,6 +290,17 @@ export default class TestHelpers {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async getFolder(id: string | "root" | "trash" | "shared_with_me") {
|
||||||
|
return await this.platform.app.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: `${TestHelpers.DOC_URL}/companies/${this.platform.workspace.company_id}/item/download/zip?items=${id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${this.jwt}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
async getDocumentOKCheck(id: string | "root" | "trash" | "shared_with_me") {
|
async getDocumentOKCheck(id: string | "root" | "trash" | "shared_with_me") {
|
||||||
const response = await this.getDocument(id);
|
const response = await this.getDocument(id);
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
@@ -297,6 +308,13 @@ export default class TestHelpers {
|
|||||||
expect(doc.item?.id).toBe(id);
|
expect(doc.item?.id).toBe(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async getFolderOKCheck(id: string | "root" | "trash" | "shared_with_me") {
|
||||||
|
const response = await this.getFolder(id);
|
||||||
|
expect(response.statusCode).toBe(200);
|
||||||
|
const doc = deserialize<DriveItemDetailsMockClass>(DriveItemDetailsMockClass, response.body);
|
||||||
|
expect(doc.item?.id).toBe(id);
|
||||||
|
};
|
||||||
|
|
||||||
async sharedWithMeDocuments (
|
async sharedWithMeDocuments (
|
||||||
payload: Record<string, any>
|
payload: Record<string, any>
|
||||||
){
|
){
|
||||||
|
|||||||
@@ -309,4 +309,32 @@ describe("the public links feature", () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
describe("Download Folder from shared link", () => {
|
||||||
|
|
||||||
|
it("Share folder", async () => {
|
||||||
|
const user = await TestHelpers.getInstance(platform, true);
|
||||||
|
const anotherUser = await TestHelpers.getInstance(platform, true);
|
||||||
|
|
||||||
|
//create directory in "My Drive" and upload a file
|
||||||
|
const directory = await user.createDirectory("user_" + user.user.id);
|
||||||
|
const doc = await user.createRandomDocument(directory.id);
|
||||||
|
|
||||||
|
//check that another user doesn't see any file
|
||||||
|
//expect((await anotherUser.getFolder(doc.id)).statusCode).toBe(401);
|
||||||
|
|
||||||
|
//share folder with the public link
|
||||||
|
await user.shareWithPublicLink(directory, "read");
|
||||||
|
|
||||||
|
const token = await anotherUser.getPublicLinkAccessToken(directory);
|
||||||
|
|
||||||
|
anotherUser.jwt = token.value;
|
||||||
|
await anotherUser.getDocumentOKCheck(doc.id);
|
||||||
|
|
||||||
|
expect((await anotherUser.getFolder(doc.id)).statusCode).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|||||||
@@ -396,10 +396,10 @@
|
|||||||
readable-stream "^3.4.0"
|
readable-stream "^3.4.0"
|
||||||
send "^0.17.1"
|
send "^0.17.1"
|
||||||
|
|
||||||
"@ffprobe-installer/darwin-arm64@5.0.1":
|
"@ffprobe-installer/darwin-x64@5.0.0":
|
||||||
version "5.0.1"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/@ffprobe-installer/darwin-arm64/-/darwin-arm64-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/@ffprobe-installer/darwin-x64/-/darwin-x64-5.0.0.tgz"
|
||||||
integrity sha512-vwNCNjokH8hfkbl6m95zICHwkSzhEvDC3GVBcUp5HX8+4wsX10SP3B+bGur7XUzTIZ4cQpgJmEIAx6TUwRepMg==
|
integrity sha512-Zl0UkZ+wW/eyMKBPLTUCcNQch2VDnZz/cBn1DXv3YtCBVbYd9aYzGj4MImdxgWcoE0+GpbfbO6mKGwMq5HCm6A==
|
||||||
|
|
||||||
"@ffprobe-installer/ffprobe@^1.4.1":
|
"@ffprobe-installer/ffprobe@^1.4.1":
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
|
|||||||
@@ -276,6 +276,7 @@
|
|||||||
"babel-plugin-named-exports-order": "^0.0.2",
|
"babel-plugin-named-exports-order": "^0.0.2",
|
||||||
"craco-alias": "^2.1.1",
|
"craco-alias": "^2.1.1",
|
||||||
"eslint-plugin-storybook": "=0.5.12",
|
"eslint-plugin-storybook": "=0.5.12",
|
||||||
|
"jest": "^29.6.1",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"sass": "^1.49.9",
|
"sass": "^1.49.9",
|
||||||
|
|||||||
@@ -130,11 +130,10 @@ export class DriveApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async getDownloadZipUrl(companyId: string, ids: string[]) {
|
static async getDownloadZipUrl(companyId: string, ids: string[]) {
|
||||||
const { token } = await DriveApiClient.getDownloadToken(companyId, ids);
|
// const { token } = await DriveApiClient.getDownloadToken(companyId, ids);
|
||||||
return Api.route(
|
return Api.route(
|
||||||
`/internal/services/documents/v1/companies/${companyId}/item/download/zip` +
|
`/internal/services/documents/v1/companies/${companyId}/item/download/zip` +
|
||||||
`?items=${ids.join(',')}&token=${token}` +
|
`?items=${ids.join(',')}`
|
||||||
appendTdriveToken(true),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChevronDownIcon, DotsHorizontalIcon } from '@heroicons/react/outline';
|
import { ChevronDownIcon } from '@heroicons/react/outline';
|
||||||
import { Button } from '@atoms/button/button';
|
import { Button } from '@atoms/button/button';
|
||||||
import { Base, BaseSmall, Subtitle, Title } from '@atoms/text';
|
import { Base, BaseSmall, Subtitle, Title } from '@atoms/text';
|
||||||
import Menu from '@components/menus/menu';
|
import Menu from '@components/menus/menu';
|
||||||
@@ -62,7 +62,7 @@ export default memo(
|
|||||||
const companyId = useRouterCompany();
|
const companyId = useRouterCompany();
|
||||||
const role = user ? (user?.companies || []).find(company => company?.company.id === companyId)?.role : "member";
|
const role = user ? (user?.companies || []).find(company => company?.company.id === companyId)?.role : "member";
|
||||||
setTdriveTabToken(tdriveTabContextToken || null);
|
setTdriveTabToken(tdriveTabContextToken || null);
|
||||||
const [filter, setFilter] = useRecoilState(SharedWithMeFilterState);
|
const [filter, __] = useRecoilState(SharedWithMeFilterState);
|
||||||
const { viewId } = useRouteState();
|
const { viewId } = useRouteState();
|
||||||
const [parentId, _setParentId] = useRecoilState(
|
const [parentId, _setParentId] = useRecoilState(
|
||||||
DriveCurrentFolderAtom({ context: context, initialFolderId: viewId || initialParentId || 'user_'+user?.id }),
|
DriveCurrentFolderAtom({ context: context, initialFolderId: viewId || initialParentId || 'user_'+user?.id }),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { DriveItem, DriveItemDetails } from '@features/drive/types';
|
|||||||
import { ToasterService } from '@features/global/services/toaster-service';
|
import { ToasterService } from '@features/global/services/toaster-service';
|
||||||
import { copyToClipboard } from '@features/global/utils/CopyClipboard';
|
import { copyToClipboard } from '@features/global/utils/CopyClipboard';
|
||||||
import { SharedWithMeFilterState } from '@features/drive/state/shared-with-me-filter';
|
import { SharedWithMeFilterState } from '@features/drive/state/shared-with-me-filter';
|
||||||
import { getCurrentUserList, getUser } from '@features/users/hooks/use-user-list';
|
import { getCurrentUserList } from '@features/users/hooks/use-user-list';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import Languages from 'features/global/services/languages-service';
|
import Languages from 'features/global/services/languages-service';
|
||||||
|
|
||||||
@@ -43,6 +43,9 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
|||||||
const setPropertiesModalState = useSetRecoilState(PropertiesModalAtom);
|
const setPropertiesModalState = useSetRecoilState(PropertiesModalAtom);
|
||||||
const setUsersModalState = useSetRecoilState(UsersModalAtom);
|
const setUsersModalState = useSetRecoilState(UsersModalAtom);
|
||||||
const { open: preview } = useDrivePreview();
|
const { open: preview } = useDrivePreview();
|
||||||
|
function getIdsFromArray(arr: DriveItem[]): string[] {
|
||||||
|
return arr.map((obj) => obj.id);
|
||||||
|
}
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async (parent?: Partial<DriveItemDetails> | null, item?: DriveItem) => {
|
async (parent?: Partial<DriveItemDetails> | null, item?: DriveItem) => {
|
||||||
@@ -74,7 +77,14 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
|||||||
{
|
{
|
||||||
type: 'menu',
|
type: 'menu',
|
||||||
text: Languages.t('components.item_context_menu.download'),
|
text: Languages.t('components.item_context_menu.download'),
|
||||||
onClick: () => download(item.last_version_cache.file_metadata.external_id),
|
onClick: () => {
|
||||||
|
if (item.is_directory) {
|
||||||
|
downloadZip([item!.id]);
|
||||||
|
console.log(item!.id);
|
||||||
|
} else {
|
||||||
|
download(item.last_version_cache.file_metadata.external_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
@@ -253,7 +263,18 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
|||||||
type: 'menu',
|
type: 'menu',
|
||||||
text: Languages.t('components.item_context_menu.download_folder'),
|
text: Languages.t('components.item_context_menu.download_folder'),
|
||||||
hide: inTrash,
|
hide: inTrash,
|
||||||
onClick: () => downloadZip([parent.item!.id]),
|
onClick: () => {
|
||||||
|
if (parent.children && parent.children.length > 0) {
|
||||||
|
const idsFromArray = getIdsFromArray(parent.children);
|
||||||
|
console.log("Download zip file with docs: " + idsFromArray);
|
||||||
|
downloadZip(idsFromArray);
|
||||||
|
} else if (parent.item) {
|
||||||
|
console.log("Download folder itself");
|
||||||
|
download(parent.item.last_version_cache.file_metadata.external_id);
|
||||||
|
} else {
|
||||||
|
console.error("Very strange, everything is null, you are trying to download undefined");
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'menu',
|
type: 'menu',
|
||||||
@@ -310,7 +331,6 @@ export const useOnBuildContextMenu = (children: DriveItem[], initialParentId?: s
|
|||||||
setCreationModalState,
|
setCreationModalState,
|
||||||
setVersionModal,
|
setVersionModal,
|
||||||
setAccessModalState,
|
setAccessModalState,
|
||||||
setUsersModalState,
|
|
||||||
setPropertiesModalState,
|
setPropertiesModalState,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -454,7 +474,6 @@ export const useOnBuildFileContextMenu = () => {
|
|||||||
const { open: preview } = useDrivePreview();
|
const { open: preview } = useDrivePreview();
|
||||||
return useCallback(
|
return useCallback(
|
||||||
(item: DriveItem) => {
|
(item: DriveItem) => {
|
||||||
console.log(item);
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{
|
{
|
||||||
type: 'menu',
|
type: 'menu',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { ChevronDownIcon, DotsHorizontalIcon } from '@heroicons/react/outline';
|
||||||
import { ChevronDownIcon, ChevronUpIcon, DotsHorizontalIcon } from '@heroicons/react/outline';
|
|
||||||
import { Button } from '@atoms/button/button';
|
import { Button } from '@atoms/button/button';
|
||||||
import { Base, BaseSmall, Title } from '@atoms/text';
|
import { Title } from '@atoms/text';
|
||||||
import Menu from '@components/menus/menu';
|
import Menu from '@components/menus/menu';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import {
|
import {
|
||||||
@@ -17,7 +16,7 @@ import Languages from '@features/global/services/languages-service';
|
|||||||
|
|
||||||
export const SharedFilesTable = () => {
|
export const SharedFilesTable = () => {
|
||||||
const { driveItems, loading } = useSharedWithMeDriveItems();
|
const { driveItems, loading } = useSharedWithMeDriveItems();
|
||||||
const [filter, setFilter] = useRecoilState(SharedWithMeFilterState);
|
const [filter] = useRecoilState(SharedWithMeFilterState);
|
||||||
|
|
||||||
// FILTER HOOKS
|
// FILTER HOOKS
|
||||||
const buildFileTypeContextMenu = useOnBuildFileTypeContextMenu();
|
const buildFileTypeContextMenu = useOnBuildFileTypeContextMenu();
|
||||||
@@ -26,7 +25,7 @@ export const SharedFilesTable = () => {
|
|||||||
const buildDateContextMenu = useOnBuildDateContextMenu();
|
const buildDateContextMenu = useOnBuildDateContextMenu();
|
||||||
|
|
||||||
const fileAddedDate = (timestamp: number) => {
|
const fileAddedDate = (timestamp: number) => {
|
||||||
const [formattedDate, formattedTime] = new Date(timestamp).toLocaleString().split(', ');
|
const [formattedDate] = new Date(timestamp).toLocaleString().split(', ');
|
||||||
return formattedDate;
|
return formattedDate;
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|||||||
+773
-8
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user