diff --git a/common/ASC.Data.Storage/ChunkedUploader/CommonChunkedUploadSession.cs b/common/ASC.Data.Storage/ChunkedUploader/CommonChunkedUploadSession.cs index ef76304537..af30f37fb2 100644 --- a/common/ASC.Data.Storage/ChunkedUploader/CommonChunkedUploadSession.cs +++ b/common/ASC.Data.Storage/ChunkedUploader/CommonChunkedUploadSession.cs @@ -96,7 +96,24 @@ namespace ASC.Core.ChunkedUploader public T GetItemOrDefault(string key) { - return Items.ContainsKey(key) && Items[key] is T t ? t : default; + if (Items.ContainsKey(key) && Items[key] != null) + { + if (Items[key] is T) + { + return (T)Items[key]; + } + + if (Items[key] is JsonElement) + { + var jToken = (JsonElement)Items[key]; + + var item = jToken.Deserialize(); + Items[key] = item; + return item; + } + } + + return default(T); } public virtual Stream Serialize() @@ -114,17 +131,21 @@ namespace ASC.Core.ChunkedUploader if (item.Value is JsonElement) { var value = (JsonElement)item.Value; - if (value.ValueKind == JsonValueKind.String) + + switch (value.ValueKind) { - newItems.Add(item.Key, item.Value.ToString()); - } - if (value.ValueKind == JsonValueKind.Number) - { - newItems.Add(item.Key, Int32.Parse(item.Value.ToString())); - } - if (value.ValueKind == JsonValueKind.Array) - { - newItems.Add(item.Key, value.EnumerateArray().Select(o => o.ToString()).ToList()); + case JsonValueKind.String: + newItems.Add(item.Key, item.Value.ToString()); + break; + case JsonValueKind.Number: + newItems.Add(item.Key, Int32.Parse(item.Value.ToString())); + break; + case JsonValueKind.Array: + newItems.Add(item.Key, value.EnumerateArray().Select(o => o.ToString()).ToList()); + break; + default: + newItems.Add(item.Key, item.Value); + break; } } else diff --git a/common/ASC.Data.Storage/GoogleCloud/GoogleCloudStorage.cs b/common/ASC.Data.Storage/GoogleCloud/GoogleCloudStorage.cs index 2859ee1b7f..a82fdad5a2 100644 --- a/common/ASC.Data.Storage/GoogleCloud/GoogleCloudStorage.cs +++ b/common/ASC.Data.Storage/GoogleCloud/GoogleCloudStorage.cs @@ -32,6 +32,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; +using System.Net.Http.Headers; using System.Security.Cryptography; using System.Text; using System.Threading; @@ -759,14 +760,14 @@ namespace ASC.Data.Storage.GoogleCloud if (chunkLength != defaultChunkSize) totalBytes = Convert.ToString((chunkNumber - 1) * defaultChunkSize + chunkLength); - - var contentRangeHeader = $"bytes {bytesRangeStart}-{bytesRangeEnd}/{totalBytes}"; - + var request = new HttpRequestMessage(); request.RequestUri = new Uri(uploadUri); request.Method = HttpMethod.Put; - request.Headers.Add("Content-Range", contentRangeHeader); request.Content = new StreamContent(stream); + request.Content.Headers.ContentRange = new ContentRangeHeaderValue(Convert.ToInt64(bytesRangeStart), + Convert.ToInt64(bytesRangeEnd), + Convert.ToInt64(totalBytes)); const int MAX_RETRIES = 100; diff --git a/products/ASC.Files/Client/public/images/clear.trash.react.svg b/products/ASC.Files/Client/public/images/clear.trash.react.svg new file mode 100644 index 0000000000..dc238e01dd --- /dev/null +++ b/products/ASC.Files/Client/public/images/clear.trash.react.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/products/ASC.Files/Client/src/components/Article/Body/Items.js b/products/ASC.Files/Client/src/components/Article/Body/Items.js index 806a76904b..684045f8e0 100644 --- a/products/ASC.Files/Client/src/components/Article/Body/Items.js +++ b/products/ASC.Files/Client/src/components/Article/Body/Items.js @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import styled from "styled-components"; import PropTypes from "prop-types"; import { inject, observer } from "mobx-react"; @@ -29,11 +29,12 @@ const Item = ({ startUpload, uploadEmptyFolders, setDragging, + showBadge, + labelBadge, + iconBadge, }) => { const [isDragActive, setIsDragActive] = React.useState(false); - const showBadge = item.newItems ? item.newItems > 0 && true : false; - const isDragging = dragging ? showDragItems(item) : false; let value = ""; @@ -109,8 +110,9 @@ const Item = ({ isDragActive={isDragActive && isDragging} value={value} showBadge={showBadge} - labelBadge={showBadge ? item.newItems : null} + labelBadge={labelBadge} onClickBadge={onBadgeClick} + iconBadge={iconBadge} /> ); @@ -138,6 +140,9 @@ const Items = ({ draggableItems, moveDragItems, + + setEmptyTrashDialogVisible, + trashIsEmpty, }) => { useEffect(() => { data.forEach((elem) => { @@ -287,9 +292,26 @@ const Items = ({ [moveDragItems, t] ); + const onEmptyTrashAction = () => { + setEmptyTrashDialogVisible(true); + }; + + const onClickBadge = (isTrash) => { + if (isTrash) { + onEmptyTrashAction(); + } else { + onBadgeClick(); + } + }; + const getItem = React.useCallback( (data) => { const items = data.map((item, index) => { + const isTrash = item.rootFolderType === FolderType.TRASH; + const showBadge = item.newItems ? item.newItems > 0 && true : false; + const labelBadge = showBadge ? item.newItems : null; + const iconBadge = isTrash ? "images/clear.trash.react.svg" : null; + return ( onClickBadge(isTrash)} showDragItems={showDragItems} + showBadge={showBadge || (isTrash && !trashIsEmpty)} + labelBadge={labelBadge} + iconBadge={iconBadge} /> ); }); @@ -326,6 +351,7 @@ const Items = ({ setDragging, startUpload, uploadEmptyFolders, + trashIsEmpty, ] ); @@ -348,8 +374,15 @@ export default inject( filesStore, filesActionsStore, uploadDataStore, + dialogsStore, }) => { - const { selection, dragging, setDragging, setStartDrag } = filesStore; + const { + selection, + dragging, + setDragging, + setStartDrag, + trashIsEmpty, + } = filesStore; const { startUpload } = uploadDataStore; @@ -363,6 +396,8 @@ export default inject( const { id } = selectedFolderStore; const { moveDragItems, uploadEmptyFolders } = filesActionsStore; + const { setEmptyTrashDialogVisible } = dialogsStore; + return { isAdmin: auth.isAdmin, myId: myFolderId, @@ -380,6 +415,8 @@ export default inject( moveDragItems, startUpload, uploadEmptyFolders, + setEmptyTrashDialogVisible, + trashIsEmpty, }; } )(withTranslation(["Home", "Common", "Translations"])(observer(Items))); diff --git a/products/ASC.Files/Client/src/store/FilesStore.js b/products/ASC.Files/Client/src/store/FilesStore.js index eb43f7e5df..971083cf28 100644 --- a/products/ASC.Files/Client/src/store/FilesStore.js +++ b/products/ASC.Files/Client/src/store/FilesStore.js @@ -72,6 +72,7 @@ class FilesStore { isLoadingFilesFind = false; pageItemsLength = null; isHidePagination = false; + trashIsEmpty = false; constructor( authStore, @@ -690,6 +691,9 @@ class FilesStore { this.setCreatedItem(null); } + + this.getIsEmptyTrash(); //TODO: + return Promise.resolve(selectedFolder); }) .catch((err) => { @@ -2096,6 +2100,16 @@ class FilesStore { setScrollToItem = (item) => { this.scrollToItem = item; }; + + getIsEmptyTrash = async () => { + const res = await api.files.getTrashFolderList(); + const items = [...res.files, ...res.folders]; + this.setTrashIsEmpty(items.length === 0 ? true : false); + }; + + setTrashIsEmpty = (isEmpty) => { + this.trashIsEmpty = isEmpty; + }; } export default FilesStore; diff --git a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs index a3267b4da4..4f53dc560e 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs @@ -31,6 +31,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Security; using System.Text; using System.Threading.Tasks; @@ -523,7 +524,7 @@ namespace ASC.Files.Thirdparty.GoogleDrive var titleData = !string.IsNullOrEmpty(driveFile.Name) ? $"\"name\":\"{driveFile.Name}\"" : ""; var parentData = !string.IsNullOrEmpty(folderId) ? $",\"parents\":[\"{folderId}\"]" : ""; - body = !string.IsNullOrEmpty(titleData + parentData) ? "{{" + titleData + parentData + "}}" : ""; + body = !string.IsNullOrEmpty(titleData + parentData) ? "{" + titleData + parentData + "}" : ""; } var request = new HttpRequestMessage(); @@ -562,14 +563,13 @@ namespace ASC.Files.Thirdparty.GoogleDrive request.RequestUri = new Uri(googleDriveSession.Location); request.Method = HttpMethod.Put; request.Headers.Add("Authorization", "Bearer " + AccessToken); - request.Headers.Add("Content-Range", string.Format("bytes {0}-{1}/{2}", - googleDriveSession.BytesTransfered, - googleDriveSession.BytesTransfered + chunkLength - 1, - googleDriveSession.BytesToTransfer)); request.Content = new StreamContent(stream); + request.Content.Headers.ContentRange = new ContentRangeHeaderValue(googleDriveSession.BytesTransfered, + googleDriveSession.BytesTransfered + chunkLength - 1, + googleDriveSession.BytesToTransfer); var httpClient = _clientFactory.CreateClient(); HttpResponseMessage response; - + try { response = await httpClient.SendAsync(request); @@ -598,10 +598,11 @@ namespace ASC.Files.Thirdparty.GoogleDrive if (response != null) { - var locationHeader = response.Headers.Location.ToString(); - if (!string.IsNullOrEmpty(locationHeader)) + var locationHeader = response.Headers.Location; + + if (locationHeader != null) { - uplSession.Location = locationHeader; + uplSession.Location = locationHeader.ToString(); } } } diff --git a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs index e7a572fa6f..bc7fbeb7d8 100644 --- a/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs +++ b/products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs @@ -276,10 +276,10 @@ namespace ASC.Files.Thirdparty.OneDrive request.RequestUri = uploadUriBuilder.Uri; request.Method = HttpMethod.Post; request.Headers.Add("Authorization", "Bearer " + AccessToken); - request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json") - { - CharSet = Encoding.UTF8.WebName - }; + //request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json") + //{ + // CharSet = Encoding.UTF8.WebName + //}; var uploadSession = new ResumableUploadSession(onedriveFile.Id, folderId, contentLength); @@ -318,11 +318,11 @@ namespace ASC.Files.Thirdparty.OneDrive request.RequestUri = new Uri(oneDriveSession.Location); request.Method = HttpMethod.Put; request.Headers.Add("Authorization", "Bearer " + AccessToken); - request.Headers.Add("Content-Range", string.Format("bytes {0}-{1}/{2}", - oneDriveSession.BytesTransfered, - oneDriveSession.BytesTransfered + chunkLength - 1, - oneDriveSession.BytesToTransfer)); request.Content = new StreamContent(stream); + + request.Content.Headers.ContentRange = new ContentRangeHeaderValue(oneDriveSession.BytesTransfered, + oneDriveSession.BytesTransfered + chunkLength - 1, + oneDriveSession.BytesToTransfer); var httpClient = ClientFactory.CreateClient(); using var response = await httpClient.SendAsync(request);