Merge branch 'feature/files' into feature/media-viewer
This commit is contained in:
commit
fda955966d
@ -26,14 +26,13 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ASC.Data.Storage;
|
||||
|
||||
public static class StreamExtension
|
||||
{
|
||||
public const int BufferSize = 2048; //NOTE: set to 2048 to fit in minimum tcp window
|
||||
|
||||
{
|
||||
// public const int BufferSize = 2048; //NOTE: set to 2048 to fit in minimum tcp window
|
||||
|
||||
public static Stream GetBuffered(this Stream srcStream)
|
||||
{
|
||||
if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
|
||||
@ -41,7 +40,7 @@ public static class StreamExtension
|
||||
{
|
||||
//Buffer it
|
||||
var memStream = TempStream.Create();
|
||||
srcStream.StreamCopyTo(memStream);
|
||||
srcStream.CopyTo(memStream);
|
||||
memStream.Position = 0;
|
||||
return memStream;
|
||||
}
|
||||
@ -61,44 +60,4 @@ public static class StreamExtension
|
||||
mem.Read(buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static void StreamCopyTo(this Stream srcStream, Stream dstStream)
|
||||
{
|
||||
if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
|
||||
if (dstStream == null) throw new ArgumentNullException(nameof(dstStream));
|
||||
|
||||
var buffer = new byte[BufferSize];
|
||||
int readed;
|
||||
while ((readed = srcStream.Read(buffer, 0, BufferSize)) > 0)
|
||||
{
|
||||
dstStream.Write(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
public static async Task StreamCopyToAsync(this Stream srcStream, Stream dstStream)
|
||||
{
|
||||
if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
|
||||
if (dstStream == null) throw new ArgumentNullException(nameof(dstStream));
|
||||
|
||||
var buffer = new byte[BufferSize];
|
||||
int readed;
|
||||
while ((readed = await srcStream.ReadAsync(buffer, 0, BufferSize)) > 0)
|
||||
{
|
||||
await dstStream.WriteAsync(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
|
||||
public static void StreamCopyTo(this Stream srcStream, Stream dstStream, int length)
|
||||
{
|
||||
if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
|
||||
if (dstStream == null) throw new ArgumentNullException(nameof(dstStream));
|
||||
|
||||
var buffer = new byte[BufferSize];
|
||||
var totalRead = 0;
|
||||
int readed;
|
||||
while ((readed = srcStream.Read(buffer, 0, length - totalRead > BufferSize ? BufferSize : length - totalRead)) > 0 && totalRead < length)
|
||||
{
|
||||
dstStream.Write(buffer, 0, readed);
|
||||
totalRead += readed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,14 +143,16 @@ namespace ASC.Core.Data
|
||||
WebstudioDbContext = dbContextManager.Value;
|
||||
}
|
||||
|
||||
private int tenantID;
|
||||
private int TenantID
|
||||
{
|
||||
get { return TenantManager.GetCurrentTenant().TenantId; }
|
||||
get { return tenantID != 0 ? tenantID : (tenantID = TenantManager.GetCurrentTenant().TenantId); }
|
||||
}
|
||||
//
|
||||
private Guid? currentUserID;
|
||||
private Guid CurrentUserID
|
||||
{
|
||||
get { return AuthContext.CurrentAccount.ID; }
|
||||
get { return (currentUserID ?? (currentUserID = AuthContext.CurrentAccount.ID)).Value; }
|
||||
}
|
||||
|
||||
public bool SaveSettings<T>(T settings, int tenantId) where T : ISettings
|
||||
|
@ -74,10 +74,17 @@ namespace ASC.Core.Tenants
|
||||
TimeZoneConverter = timeZoneConverter;
|
||||
}
|
||||
|
||||
|
||||
private TimeZoneInfo timeZoneInfo;
|
||||
private TimeZoneInfo TimeZoneInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return timeZoneInfo ?? (timeZoneInfo = TimeZoneConverter.GetTimeZone(TenantManager.GetCurrentTenant().TimeZone));
|
||||
}
|
||||
}
|
||||
public DateTime DateTimeFromUtc(DateTime utc)
|
||||
{
|
||||
return DateTimeFromUtc(TimeZoneConverter.GetTimeZone(TenantManager.GetCurrentTenant().TimeZone), utc);
|
||||
return DateTimeFromUtc(TimeZoneInfo, utc);
|
||||
}
|
||||
|
||||
public DateTime DateTimeFromUtc(string timeZone, DateTime utc)
|
||||
@ -103,7 +110,7 @@ namespace ASC.Core.Tenants
|
||||
|
||||
public DateTime DateTimeToUtc(DateTime local)
|
||||
{
|
||||
return DateTimeToUtc(TimeZoneConverter.GetTimeZone(TenantManager.GetCurrentTenant().TimeZone), local);
|
||||
return DateTimeToUtc(TimeZoneInfo, local);
|
||||
}
|
||||
|
||||
public static DateTime DateTimeToUtc(TimeZoneInfo timeZone, DateTime local)
|
||||
@ -126,7 +133,7 @@ namespace ASC.Core.Tenants
|
||||
|
||||
public DateTime DateTimeNow()
|
||||
{
|
||||
return DateTimeNow(TimeZoneConverter.GetTimeZone(TenantManager.GetCurrentTenant().TimeZone));
|
||||
return DateTimeNow(TimeZoneInfo);
|
||||
}
|
||||
|
||||
public static DateTime DateTimeNow(TimeZoneInfo timeZone)
|
||||
|
@ -28,8 +28,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Data.Storage;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Core.ChunkedUploader
|
||||
@ -158,14 +160,14 @@ namespace ASC.Core.ChunkedUploader
|
||||
|
||||
using (var bufferStream = new FileStream(uploadSession.ChunksBuffer, FileMode.Append))
|
||||
{
|
||||
stream.StreamCopyTo(bufferStream);
|
||||
stream.CopyTo(bufferStream);
|
||||
}
|
||||
|
||||
uploadSession.BytesUploaded += chunkLength;
|
||||
|
||||
if (uploadSession.BytesTotal == uploadSession.BytesUploaded)
|
||||
{
|
||||
return new FileStream(uploadSession.ChunksBuffer, FileMode.Open, FileAccess.Read, FileShare.None,
|
||||
return new FileStream(uploadSession.ChunksBuffer, FileMode.Open, FileAccess.Read, FileShare.ReadWrite,
|
||||
4096, FileOptions.DeleteOnClose);
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Data.Storage.Configuration;
|
||||
using ASC.Security.Cryptography;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@ -39,7 +41,6 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
{
|
||||
public class DiscDataStore : BaseStorage
|
||||
{
|
||||
private const int BufferSize = 8192;
|
||||
private readonly Dictionary<string, MappedPath> _mappedPaths = new Dictionary<string, MappedPath>();
|
||||
|
||||
public override IDataStore Configure(string tenant, Handler handlerConfig, Module moduleConfig, IDictionary<string, string> props)
|
||||
@ -158,7 +159,7 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
|
||||
//optimaze disk file copy
|
||||
long fslen;
|
||||
if (buffered is FileStream fileStream && WorkContext.IsMono)
|
||||
if (buffered is FileStream fileStream)
|
||||
{
|
||||
File.Copy(fileStream.Name, target, true);
|
||||
fslen = fileStream.Length;
|
||||
@ -166,12 +167,7 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
else
|
||||
{
|
||||
using var fs = File.Open(target, FileMode.Create);
|
||||
var buffer = new byte[BufferSize];
|
||||
int readed;
|
||||
while ((readed = buffered.Read(buffer, 0, BufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
buffered.CopyTo(fs);
|
||||
fslen = fs.Length;
|
||||
}
|
||||
|
||||
@ -208,12 +204,7 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
var mode = chunkNumber == 0 ? FileMode.Create : FileMode.Append;
|
||||
using (var fs = new FileStream(target, mode))
|
||||
{
|
||||
var buffer = new byte[BufferSize];
|
||||
int readed;
|
||||
while ((readed = stream.Read(buffer, 0, BufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
return string.Format("{0}_{1}", chunkNumber, uploadId);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ namespace ASC.Data.Storage.DiscStorage
|
||||
}
|
||||
using (var stream = storage.GetReadStream(_domain, path))
|
||||
{
|
||||
await stream.StreamCopyToAsync(context.Response.Body);
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
|
||||
var headersToCopy = new List<string> { "Content-Disposition", "Cache-Control", "Content-Encoding", "Content-Language", "Content-Type", "Expires" };
|
||||
|
@ -172,7 +172,7 @@ class TreeFolders extends React.Component {
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { expandedKeys, data, onLoading } = this.props;
|
||||
const { expandedKeys, data } = this.props;
|
||||
if (this.state.expandedKeys.length !== expandedKeys.length) {
|
||||
this.setState({ expandedKeys });
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import styled from "styled-components";
|
||||
import { RowContent, Link, Text, Icons, Badge, toastr } from "asc-web-components";
|
||||
import { constants } from 'asc-web-common';
|
||||
import { createFile, createFolder, renameFolder, updateFile, setFilter, fetchFiles } from '../../../../../store/files/actions';
|
||||
import { canWebEdit, canConvert, getTitleWithoutExst } from '../../../../../store/files/selectors';
|
||||
import { canWebEdit, isImage, isSound, isVideo, canConvert, getTitleWithoutExst } from '../../../../../store/files/selectors';
|
||||
import store from "../../../../../store/store";
|
||||
import EditingWrapperComponent from "./EditingWrapperComponent";
|
||||
|
||||
@ -32,12 +32,12 @@ class FilesRowContent extends React.PureComponent {
|
||||
|
||||
completeAction = () => {
|
||||
//this.setState({ loading: false }, () =>)
|
||||
this.props.onEditComplete();
|
||||
this.props.onEditComplete();
|
||||
}
|
||||
|
||||
updateItem = () => {
|
||||
const { fileAction, updateFile, renameFolder, item, onLoading } = this.props;
|
||||
|
||||
|
||||
const { itemTitle } = this.state;
|
||||
const originalTitle = getTitleWithoutExst(item);
|
||||
|
||||
@ -104,7 +104,7 @@ class FilesRowContent extends React.PureComponent {
|
||||
}
|
||||
|
||||
onFilesClick = () => {
|
||||
const { id, fileExst } = this.props.item;
|
||||
const { id, fileExst, viewUrl } = this.props.item;
|
||||
const { filter, parentFolder, onLoading } = this.props;
|
||||
if (!fileExst) {
|
||||
onLoading(true);
|
||||
@ -119,6 +119,18 @@ class FilesRowContent extends React.PureComponent {
|
||||
onLoading(false);
|
||||
})
|
||||
.finally(() => onLoading(false));
|
||||
} else {
|
||||
if (canWebEdit(fileExst)) {
|
||||
return window.open(`./doceditor?fileId=${id}`, "_blank");
|
||||
}
|
||||
|
||||
const isOpenMedia = isImage(fileExst) || isSound(fileExst) || isVideo(fileExst);
|
||||
|
||||
if (isOpenMedia) {
|
||||
return window.open(viewUrl, "_blank"); //TODO: insert media viewer
|
||||
}
|
||||
|
||||
return window.open(viewUrl, "_blank");
|
||||
}
|
||||
};
|
||||
|
||||
@ -221,15 +233,15 @@ class FilesRowContent extends React.PureComponent {
|
||||
|
||||
return isEdit
|
||||
? <EditingWrapperComponent
|
||||
isLoading={isLoading}
|
||||
itemTitle={itemTitle}
|
||||
okIcon={okIcon}
|
||||
cancelIcon={cancelIcon}
|
||||
renameTitle={this.renameTitle}
|
||||
onKeyUpUpdateItem={this.onKeyUpUpdateItem}
|
||||
onClickUpdateItem={this.onClickUpdateItem}
|
||||
cancelUpdateItem={this.cancelUpdateItem}
|
||||
/>
|
||||
isLoading={isLoading}
|
||||
itemTitle={itemTitle}
|
||||
okIcon={okIcon}
|
||||
cancelIcon={cancelIcon}
|
||||
renameTitle={this.renameTitle}
|
||||
onKeyUpUpdateItem={this.onKeyUpUpdateItem}
|
||||
onClickUpdateItem={this.onClickUpdateItem}
|
||||
cancelUpdateItem={this.cancelUpdateItem}
|
||||
/>
|
||||
: (
|
||||
<SimpleFilesRowContent
|
||||
sideColor="#333"
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
} from '../../../../../store/files/actions';
|
||||
import { isFileSelected, getFileIcon, getFolderIcon, getFolderType, loopTreeFolders, isImage, isSound, isVideo } from '../../../../../store/files/selectors';
|
||||
import store from "../../../../../store/store";
|
||||
import { SharingPanel } from "../../../../panels";
|
||||
//import { getFilterByLocation } from "../../../../../helpers/converters";
|
||||
//import config from "../../../../../../package.json";
|
||||
|
||||
@ -36,12 +37,14 @@ const { FileAction } = constants;
|
||||
|
||||
const linkStyles = { isHovered: true, type: "action", fontSize: "14px", className: "empty-folder_link", display: "flex" };
|
||||
|
||||
class SectionBodyContent extends React.PureComponent {
|
||||
class SectionBodyContent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
editingId: null,
|
||||
showSharingPanel: false,
|
||||
currentItem: null,
|
||||
currentMediaFileId: 0,
|
||||
mediaViewerVisible: false
|
||||
};
|
||||
@ -69,6 +72,21 @@ class SectionBodyContent extends React.PureComponent {
|
||||
// }
|
||||
}
|
||||
|
||||
/* componentDidUpdate(prevProps, prevState) {
|
||||
Object.entries(this.props).forEach(([key, val]) =>
|
||||
prevProps[key] !== val && console.log(`Prop '${key}' changed`)
|
||||
);
|
||||
if (this.state) {
|
||||
Object.entries(this.state).forEach(([key, val]) =>
|
||||
prevState[key] !== val && console.log(`State '${key}' changed`)
|
||||
);
|
||||
}
|
||||
} */
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !isEqual(this.props, nextProps);
|
||||
}
|
||||
|
||||
onClickRename = (item) => {
|
||||
const { id, fileExst } = item;
|
||||
|
||||
@ -89,7 +107,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
if (fileAction.type === FileAction.Create || fileAction.type === FileAction.Rename) {
|
||||
onLoading(true);
|
||||
fetchFiles(folderId, filter, store.dispatch).then(data => {
|
||||
const newItem = item.id === -1 ? null : item;
|
||||
const newItem = item.id === -1 ? null : item;
|
||||
if (!item.fileExst) {
|
||||
const path = data.selectedFolder.pathParts;
|
||||
const newTreeFolders = treeFolders;
|
||||
@ -131,7 +149,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
.catch(err => toastr.error(err))
|
||||
.then(() =>
|
||||
fetchFiles(currentFolderId, filter, store.dispatch).then(data => {
|
||||
if(currentFolderType !== "Trash") {
|
||||
if (currentFolderType !== "Trash") {
|
||||
const path = data.selectedFolder.pathParts;
|
||||
const newTreeFolders = treeFolders;
|
||||
const folders = data.selectedFolder.folders;
|
||||
@ -146,7 +164,14 @@ class SectionBodyContent extends React.PureComponent {
|
||||
}
|
||||
|
||||
onClickShare = item => {
|
||||
return false;
|
||||
let currentItem = item;
|
||||
if (this.state.showSharingPanel) {
|
||||
currentItem = null;
|
||||
}
|
||||
this.setState({
|
||||
currentItem,
|
||||
showSharingPanel: !this.state.showSharingPanel,
|
||||
});
|
||||
}
|
||||
|
||||
onClickLinkForPortal = item => {
|
||||
@ -175,7 +200,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
key: "sharing-settings",
|
||||
label: "Sharing settings",
|
||||
onClick: this.onClickShare.bind(this, item),
|
||||
disabled: true
|
||||
disabled: item.access !== 1
|
||||
},
|
||||
isFile
|
||||
? {
|
||||
@ -252,12 +277,13 @@ class SectionBodyContent extends React.PureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
svgLoader = () => <div style={{ width: '24px' }}></div>;
|
||||
|
||||
getItemIcon = (item, isEdit) => {
|
||||
const extension = item.fileExst;
|
||||
const icon = extension
|
||||
? getFileIcon(extension, 24)
|
||||
: getFolderIcon(item.providerKey, 24);
|
||||
const loader = <div style={{width: '24px'}}></div>
|
||||
|
||||
return <ReactSVG
|
||||
beforeInjection={svg => {
|
||||
@ -265,7 +291,7 @@ class SectionBodyContent extends React.PureComponent {
|
||||
isEdit && svg.setAttribute('style', 'margin-left: 24px');
|
||||
}}
|
||||
src={icon}
|
||||
loading={() => loader}
|
||||
loading={this.svgLoader}
|
||||
/>;
|
||||
};
|
||||
|
||||
@ -524,9 +550,10 @@ class SectionBodyContent extends React.PureComponent {
|
||||
fileAction,
|
||||
onLoading,
|
||||
isLoading,
|
||||
currentFolderCount,
|
||||
currentFolderCount
|
||||
} = this.props;
|
||||
const { editingId } = this.state;
|
||||
|
||||
const { editingId, showSharingPanel, currentItem } = this.state;
|
||||
|
||||
let items = [...folders, ...files];
|
||||
|
||||
@ -633,7 +660,7 @@ SectionBodyContent.defaultProps = {
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { selectedFolder, treeFolders } = state.files;
|
||||
const { selectedFolder, treeFolders, selection, shareDataItems } = state.files;
|
||||
const { id, title, foldersCount, filesCount } = selectedFolder;
|
||||
const currentFolderType = getFolderType(id, treeFolders);
|
||||
|
||||
@ -648,7 +675,7 @@ const mapStateToProps = state => {
|
||||
folders: state.files.folders,
|
||||
parentId: state.files.selectedFolder.parentId,
|
||||
selected: state.files.selected,
|
||||
selection: state.files.selection,
|
||||
selection,
|
||||
settings: state.auth.settings,
|
||||
viewer: state.auth.user,
|
||||
treeFolders: state.files.treeFolders,
|
||||
@ -656,7 +683,8 @@ const mapStateToProps = state => {
|
||||
title,
|
||||
myDocumentsId: treeFolders[myFolderIndex].id,
|
||||
currentFolderCount,
|
||||
selectedFolderId: id
|
||||
selectedFolderId: id,
|
||||
shareDataItems
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -15,11 +15,7 @@ import { fetchFiles, setAction } from "../../../../../store/files/actions";
|
||||
import { default as filesStore } from "../../../../../store/store";
|
||||
import { EmptyTrashDialog, DeleteDialog } from "../../../../dialogs";
|
||||
import { SharingPanel } from "../../../../panels";
|
||||
import {
|
||||
isCanBeDeleted,
|
||||
getAccessOption,
|
||||
checkFolderType
|
||||
} from "../../../../../store/files/selectors";
|
||||
import { isCanBeDeleted, checkFolderType } from "../../../../../store/files/selectors";
|
||||
|
||||
const { isAdmin } = store.auth.selectors;
|
||||
const { FilterType, FileAction } = constants;
|
||||
@ -259,20 +255,23 @@ class SectionHeaderContent extends React.Component {
|
||||
folder,
|
||||
onCheck,
|
||||
title,
|
||||
accessOptions,
|
||||
shareDataItems,
|
||||
currentFolderId
|
||||
currentFolderId,
|
||||
onLoading
|
||||
} = this.props;
|
||||
const {
|
||||
showDeleteDialog,
|
||||
showSharingPanel,
|
||||
showEmptyTrashDialog
|
||||
showEmptyTrashDialog,
|
||||
showDownloadDialog
|
||||
} = this.state;
|
||||
const isItemsSelected = selection.length;
|
||||
const isOnlyFolderSelected = selection.every(
|
||||
selected => !selected.fileType
|
||||
);
|
||||
|
||||
const accessItem = selection.find(x => x.access === 1 || x.access === 0);
|
||||
const shareDisable = !accessItem;
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
label: t("LblSelect"),
|
||||
@ -304,7 +303,7 @@ class SectionHeaderContent extends React.Component {
|
||||
},
|
||||
{
|
||||
label: t("Share"),
|
||||
disabled: !isItemsSelected || shareDataItems.length === 0,
|
||||
disabled: shareDisable,
|
||||
onClick: this.onOpenSharingPanel
|
||||
},
|
||||
{
|
||||
@ -428,11 +427,14 @@ class SectionHeaderContent extends React.Component {
|
||||
/>
|
||||
)}
|
||||
|
||||
<SharingPanel
|
||||
onClose={this.onOpenSharingPanel}
|
||||
visible={showSharingPanel}
|
||||
accessOptions={accessOptions}
|
||||
/>
|
||||
{showSharingPanel && (
|
||||
<SharingPanel
|
||||
onLoading={onLoading}
|
||||
selectedItems={selection}
|
||||
onClose={this.onOpenSharingPanel}
|
||||
visible={showSharingPanel}
|
||||
/>
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
@ -444,7 +446,6 @@ const mapStateToProps = state => {
|
||||
selection,
|
||||
treeFolders,
|
||||
filter,
|
||||
shareDataItems
|
||||
} = state.files;
|
||||
const { parentId, title, id } = selectedFolder;
|
||||
const { user } = state.auth;
|
||||
@ -461,8 +462,6 @@ const mapStateToProps = state => {
|
||||
title,
|
||||
filter,
|
||||
deleteDialogVisible: isCanBeDeleted(selectedFolder, user),
|
||||
accessOptions: getAccessOption(selection),
|
||||
shareDataItems,
|
||||
currentFolderId: id
|
||||
};
|
||||
};
|
||||
|
@ -100,12 +100,12 @@ class AddUsersPanelComponent extends React.Component {
|
||||
>
|
||||
{t("LinkText")}
|
||||
</Heading>
|
||||
<IconButton
|
||||
{/*<IconButton
|
||||
size="16"
|
||||
iconName="PlusIcon"
|
||||
className="header_aside-panel-plus-icon"
|
||||
onClick={() => console.log("onPlusClick")}
|
||||
/>
|
||||
/>*/}
|
||||
</StyledHeaderContent>
|
||||
|
||||
<StyledBody>
|
||||
|
@ -21,13 +21,11 @@ import { withTranslation } from "react-i18next";
|
||||
import { utils as commonUtils, constants, api } from "asc-web-common";
|
||||
import i18n from "./i18n";
|
||||
import {
|
||||
getShareUsersAndGroups,
|
||||
setShareDataItems,
|
||||
setSharedFolders,
|
||||
setSharedFiles,
|
||||
setShareData,
|
||||
getShareUsers
|
||||
} from "../../../store/files/actions";
|
||||
import { checkFolderType } from "../../../store/files/selectors";
|
||||
import { getAccessOption } from '../../../store/files/selectors';
|
||||
import {
|
||||
StyledSharingPanel,
|
||||
StyledContent,
|
||||
@ -51,8 +49,8 @@ class SharingPanelComponent extends React.Component {
|
||||
this.state = {
|
||||
showActionPanel: false,
|
||||
isNotifyUsers: false,
|
||||
shareDataItems: props.shareDataItems,
|
||||
baseShareData: null,
|
||||
shareDataItems: [],
|
||||
baseShareData: [],
|
||||
message: "",
|
||||
showAddUsersPanel: false,
|
||||
showEmbeddingPanel: false,
|
||||
@ -63,6 +61,9 @@ class SharingPanelComponent extends React.Component {
|
||||
accessNumber: ShareAccessRights.ReadOnly,
|
||||
},
|
||||
shareLink: "",
|
||||
isLoadedShareData: false,
|
||||
showPanel: false,
|
||||
accessOptions: []
|
||||
};
|
||||
|
||||
this.ref = React.createRef();
|
||||
@ -81,8 +82,8 @@ class SharingPanelComponent extends React.Component {
|
||||
onSaveClick = () => {
|
||||
toastr.success("onSaveClick");
|
||||
|
||||
const { baseShareData, isNotifyUsers } = this.state;
|
||||
const { shareDataItems, selection } = this.props;
|
||||
const { baseShareData, isNotifyUsers, message } = this.state;
|
||||
const { shareDataItems, selectedItems, onClose } = this.props;
|
||||
|
||||
const folderIds = [];
|
||||
const fileIds = [];
|
||||
@ -102,7 +103,7 @@ class SharingPanelComponent extends React.Component {
|
||||
|
||||
const notify = isNotifyUsers;
|
||||
|
||||
for (let item of selection) {
|
||||
for (let item of selectedItems) {
|
||||
if (item.fileExst) {
|
||||
fileIds.push(item.id);
|
||||
} else {
|
||||
@ -115,7 +116,7 @@ class SharingPanelComponent extends React.Component {
|
||||
fileIds.length > 0 &&
|
||||
setSharedFiles(fileIds, shareTo, access, notify, message);*/
|
||||
|
||||
this.onClose();
|
||||
onClose();
|
||||
};
|
||||
|
||||
onFullAccessClick = () => {
|
||||
@ -269,7 +270,7 @@ class SharingPanelComponent extends React.Component {
|
||||
const index = shareDataItems.findIndex((x) => x.id === item.id);
|
||||
if (index !== -1) {
|
||||
shareDataItems.splice(index, 1);
|
||||
this.props.setShareDataItems(shareDataItems.slice(0));
|
||||
this.setState({ shareDataItems });
|
||||
}
|
||||
};
|
||||
|
||||
@ -326,48 +327,32 @@ class SharingPanelComponent extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
getShareDataItems = (items, shareDataItems, foldersIds, filesIds) => {
|
||||
const storeShareData = [];
|
||||
const arrayItems = [];
|
||||
for (let item of items) {
|
||||
const rights = this.getItemAccess(item);
|
||||
getShareDataItems = (items) => {
|
||||
let arrayItems = [];
|
||||
const newItems = [];
|
||||
let stash = [];
|
||||
|
||||
if (rights) {
|
||||
item.sharedTo = { ...item.sharedTo, ...{ rights } };
|
||||
arrayItems.push(item.sharedTo);
|
||||
}
|
||||
}
|
||||
if (foldersIds) {
|
||||
storeShareData.push({
|
||||
folderId: foldersIds[0],
|
||||
shareDataItems: arrayItems,
|
||||
});
|
||||
} else {
|
||||
storeShareData.push({ fileId: filesIds[0], shareDataItems: arrayItems });
|
||||
}
|
||||
this.props.setShareData([...storeShareData, ...this.props.shareData]);
|
||||
|
||||
let listOfArrays = [...shareDataItems.slice(0), ...[arrayItems.slice(0)]];
|
||||
|
||||
listOfArrays = listOfArrays.filter((x) => x.length !== 0);
|
||||
|
||||
let allItems = [];
|
||||
for (let array of listOfArrays) {
|
||||
for (let array of items) {
|
||||
for (let item of array) {
|
||||
allItems.push(item);
|
||||
const rights = this.getItemAccess(item);
|
||||
|
||||
if (rights) {
|
||||
item.sharedTo = { ...item.sharedTo, ...{ rights } };
|
||||
arrayItems.push(item.sharedTo);
|
||||
stash.push(item.sharedTo);
|
||||
}
|
||||
}
|
||||
newItems.push(stash);
|
||||
stash = [];
|
||||
}
|
||||
|
||||
allItems = this.removeDuplicateShareData(allItems);
|
||||
allItems = JSON.parse(JSON.stringify(allItems));
|
||||
|
||||
let stash = 0;
|
||||
for (let item of allItems) {
|
||||
let length = listOfArrays.length;
|
||||
stash = null;
|
||||
for (let item of arrayItems) {
|
||||
let length = newItems.length;
|
||||
if (!item.shareLink) {
|
||||
while (length !== 0) {
|
||||
if (listOfArrays[length - 1].length !== 0) {
|
||||
stash = listOfArrays[length - 1].find((x) => x.id === item.id);
|
||||
if (newItems[length - 1].length !== 0) {
|
||||
stash = newItems[length - 1].find((x) => x.id === item.id);
|
||||
if (stash === this.props.isMyId) {
|
||||
const adminRights = {
|
||||
icon: "AccessEditIcon",
|
||||
@ -394,7 +379,15 @@ class SharingPanelComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
this.setShareDataItemsFunction(allItems);
|
||||
arrayItems = this.removeDuplicateShareData(arrayItems);
|
||||
const baseShareData = JSON.parse(JSON.stringify(arrayItems));
|
||||
|
||||
const accessOptions = !this.props.selectedItems.length ? getAccessOption([this.props.selectedItems]) : getAccessOption(this.props.selectedItems);
|
||||
|
||||
this.setState(
|
||||
{ baseShareData, shareDataItems: arrayItems, showPanel: true, accessOptions },
|
||||
this.props.onLoading(false)
|
||||
);
|
||||
};
|
||||
|
||||
removeDuplicateShareData = (shareDataItems) => {
|
||||
@ -406,105 +399,42 @@ class SharingPanelComponent extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
setShareDataItemsFunction = (shareDataItems) => {
|
||||
shareDataItems = shareDataItems.filter(
|
||||
(x) => x !== undefined && x.length !== 0
|
||||
);
|
||||
|
||||
const clearShareData = JSON.parse(JSON.stringify(shareDataItems));
|
||||
this.props.setShareDataItems(shareDataItems.slice(0));
|
||||
this.setState({ baseShareData: clearShareData });
|
||||
};
|
||||
|
||||
getData = () => {
|
||||
const { selection, shareData } = this.props;
|
||||
const shareDataItems = [];
|
||||
const { selectedItems } = this.props;
|
||||
const folderId = [];
|
||||
const fileId = [];
|
||||
|
||||
for (let item of selection) {
|
||||
if (item.fileExst) {
|
||||
const itemShareData = shareData.find((x) => x.fileId === item.id);
|
||||
|
||||
if (itemShareData) {
|
||||
shareDataItems.push(itemShareData.shareDataItems);
|
||||
} else {
|
||||
fileId.push(item.id);
|
||||
}
|
||||
if (!selectedItems.length) {
|
||||
if (selectedItems.fileExst) {
|
||||
fileId.push(selectedItems.id);
|
||||
} else {
|
||||
const itemShareData = shareData.find((x) => x.folderId === item.id);
|
||||
if (itemShareData) {
|
||||
shareDataItems.push(itemShareData.shareDataItems);
|
||||
} else {
|
||||
folderId.push(item.id);
|
||||
folderId.push(selectedItems.id);
|
||||
}
|
||||
} else {
|
||||
for (let item of selectedItems) {
|
||||
if (item.access === 1 || item.access === 0) {
|
||||
if (item.fileExst) {
|
||||
fileId.push(item.id);
|
||||
} else {
|
||||
folderId.push(item.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [shareDataItems, folderId, fileId];
|
||||
return [folderId, fileId];
|
||||
};
|
||||
|
||||
getShareData() {
|
||||
getShareData = () => {
|
||||
const returnValue = this.getData();
|
||||
let shareDataItems = returnValue[0];
|
||||
const folderId = returnValue[1];
|
||||
const fileId = returnValue[2];
|
||||
const folderId = returnValue[0];
|
||||
const fileId = returnValue[1];
|
||||
|
||||
if (this.props.isRecycleBinFolder) {
|
||||
return;
|
||||
if (folderId.length !== 0 || fileId.length !== 0) {
|
||||
getShareUsers(folderId, fileId).then((res) => {
|
||||
this.getShareDataItems(res);
|
||||
});
|
||||
}
|
||||
|
||||
if (folderId.length !== 0) {
|
||||
files
|
||||
.getShareFolders(folderId)
|
||||
.then((res) => {
|
||||
shareDataItems = this.getShareDataItems(
|
||||
res,
|
||||
shareDataItems,
|
||||
folderId,
|
||||
null
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
const newShareDataItem = [
|
||||
{ folderId: folderId[0], shareDataItems: [] },
|
||||
];
|
||||
this.props.setShareData([
|
||||
...newShareDataItem,
|
||||
...this.props.shareData,
|
||||
]);
|
||||
console.log("getShareFolders", err);
|
||||
return;
|
||||
});
|
||||
} else if (fileId.length !== 0) {
|
||||
files
|
||||
.getShareFiles(fileId)
|
||||
.then((res) => {
|
||||
shareDataItems = this.getShareDataItems(
|
||||
res,
|
||||
shareDataItems,
|
||||
null,
|
||||
fileId
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
const newShareDataItem = [{ fileId: fileId[0], shareDataItems: [] }];
|
||||
this.props.setShareData([
|
||||
...newShareDataItem,
|
||||
...this.props.shareData,
|
||||
]);
|
||||
console.log("getShareFiles", err);
|
||||
return;
|
||||
});
|
||||
} else {
|
||||
shareDataItems = this.getShareDataItems([], shareDataItems, null, fileId);
|
||||
}
|
||||
}
|
||||
|
||||
onClose = () => {
|
||||
this.props.setShareDataItems(this.state.baseShareData.slice(0));
|
||||
this.setState({ message: "", isNotifyUsers: false });
|
||||
this.props.onClose();
|
||||
};
|
||||
|
||||
onShowEmbeddingPanel = (link) =>
|
||||
@ -518,29 +448,24 @@ class SharingPanelComponent extends React.Component {
|
||||
|
||||
onChangeMessage = (e) => this.setState({ message: e.target.value });
|
||||
|
||||
setShareDataItems = (shareDataItems) => this.setState({ shareDataItems });
|
||||
|
||||
onClose = () => this.setState({ showPanel: false });
|
||||
|
||||
componentDidMount() {
|
||||
this.props.onLoading(true);
|
||||
this.getShareData();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { selection, shareDataItems } = this.props;
|
||||
|
||||
if (selection.length !== 0) {
|
||||
if (
|
||||
!utils.array.isArrayEqual(prevProps.selection, selection) ||
|
||||
selection.length !== prevProps.selection.length
|
||||
) {
|
||||
this.getShareData();
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!utils.array.isArrayEqual(this.state.shareDataItems, shareDataItems) ||
|
||||
this.state.shareDataItems.length !== shareDataItems.length
|
||||
) {
|
||||
this.setState({ shareDataItems });
|
||||
if(this.state.showPanel !== prevState.showPanel && this.state.showPanel === false) {
|
||||
setTimeout(() => this.props.onClose(), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
//console.log("Sharing panel render");
|
||||
const { visible, t, accessOptions, isMyId, selection } = this.props;
|
||||
const { t, isMyId, selectedItems } = this.props;
|
||||
const {
|
||||
showActionPanel,
|
||||
isNotifyUsers,
|
||||
@ -551,8 +476,11 @@ class SharingPanelComponent extends React.Component {
|
||||
showEmbeddingPanel,
|
||||
accessRight,
|
||||
shareLink,
|
||||
showPanel,
|
||||
accessOptions
|
||||
} = this.state;
|
||||
|
||||
const visible = showPanel;
|
||||
const zIndex = 310;
|
||||
|
||||
const advancedOptions = (
|
||||
@ -673,7 +601,7 @@ class SharingPanelComponent extends React.Component {
|
||||
<SharingRow
|
||||
key={index}
|
||||
t={t}
|
||||
selection={selection}
|
||||
selection={selectedItems}
|
||||
item={item}
|
||||
index={index}
|
||||
isMyId={isMyId}
|
||||
@ -720,9 +648,9 @@ class SharingPanelComponent extends React.Component {
|
||||
onClose={this.onShowUsersPanel}
|
||||
visible={showAddUsersPanel}
|
||||
embeddedComponent={accessOptionsComboBox}
|
||||
setShareDataItems={setShareDataItems}
|
||||
accessRight={accessRight}
|
||||
shareDataItems={shareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
/>
|
||||
|
||||
<AddGroupsPanel
|
||||
@ -730,9 +658,9 @@ class SharingPanelComponent extends React.Component {
|
||||
onClose={this.onShowGroupsPanel}
|
||||
visible={showAddGroupsPanel}
|
||||
embeddedComponent={accessOptionsComboBox}
|
||||
setShareDataItems={setShareDataItems}
|
||||
accessRight={accessRight}
|
||||
shareDataItems={shareDataItems}
|
||||
setShareDataItems={this.setShareDataItems}
|
||||
/>
|
||||
|
||||
<EmbeddingPanel
|
||||
@ -760,28 +688,7 @@ const SharingPanel = (props) => (
|
||||
);
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const {
|
||||
shareDataItems,
|
||||
shareData,
|
||||
selection,
|
||||
selectedFolder,
|
||||
treeFolders,
|
||||
} = state.files;
|
||||
const indexOfTrash = 3;
|
||||
|
||||
return {
|
||||
shareDataItems,
|
||||
shareData,
|
||||
selection,
|
||||
isMyId: state.auth.user.id,
|
||||
isRecycleBinFolder: checkFolderType(
|
||||
selectedFolder.id,
|
||||
indexOfTrash,
|
||||
treeFolders
|
||||
),
|
||||
};
|
||||
return { isMyId: state.auth.user.id };
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, { setShareDataItems, setShareData })(
|
||||
withRouter(SharingPanel)
|
||||
);
|
||||
export default connect(mapStateToProps)(withRouter(SharingPanel));
|
||||
|
@ -29,7 +29,7 @@ const SharingRow = (props) => {
|
||||
onShowEmbeddingPanel,
|
||||
} = props;
|
||||
|
||||
const linkVisible = selection.length === 1 && item.shareLink;
|
||||
const linkVisible = selection && selection.length === 1 && item.shareLink;
|
||||
|
||||
const onCopyInternalLink = () => {
|
||||
const internalLink = item.shareLink.split("&");
|
||||
|
@ -29,8 +29,6 @@ export const SET_FILTER = "SET_FILTER";
|
||||
export const SELECT_FILE = "SELECT_FILE";
|
||||
export const DESELECT_FILE = "DESELECT_FILE";
|
||||
export const SET_ACTION = "SET_ACTION";
|
||||
export const SET_SHARE_DATA_ITEMS = "SET_SHARE_DATA_ITEMS";
|
||||
export const SET_SHARE_DATA = "SET_SHARE_DATA";
|
||||
|
||||
export function setFile(file) {
|
||||
return {
|
||||
@ -81,20 +79,6 @@ export function setAction(fileAction) {
|
||||
};
|
||||
}
|
||||
|
||||
export function setShareDataItems(shareDataItems) {
|
||||
return {
|
||||
type: SET_SHARE_DATA_ITEMS,
|
||||
shareDataItems
|
||||
};
|
||||
}
|
||||
|
||||
export function setShareData(shareData) {
|
||||
return {
|
||||
type: SET_SHARE_DATA,
|
||||
shareData
|
||||
};
|
||||
}
|
||||
|
||||
export function setSelectedFolder(selectedFolder) {
|
||||
return {
|
||||
type: SET_SELECTED_FOLDER,
|
||||
@ -338,6 +322,14 @@ export function setSharedFiles(fileId, shareTo, access, notify, sharingMessage)
|
||||
return axios.all(requests).then((res) => res);
|
||||
}
|
||||
|
||||
export function getShareUsers(folderIds, fileIds) {
|
||||
const foldersRequests = folderIds.map(folderId => files.getShareFolders(folderId));
|
||||
const filesRequests = fileIds.map(fileId => files.getShareFiles(fileId));
|
||||
const requests = [...foldersRequests, ...filesRequests];
|
||||
|
||||
return axios.all(requests).then(res => res);
|
||||
}
|
||||
|
||||
/*export function deleteGroup(id) {
|
||||
return (dispatch, getState) => {
|
||||
const { people } = getState();
|
||||
|
@ -11,9 +11,7 @@ import {
|
||||
SET_SELECTED,
|
||||
SET_SELECTION,
|
||||
SELECT_FILE,
|
||||
DESELECT_FILE,
|
||||
SET_SHARE_DATA,
|
||||
SET_SHARE_DATA_ITEMS
|
||||
DESELECT_FILE
|
||||
} from "./actions";
|
||||
import { api } from "asc-web-common";
|
||||
import { isFileSelected, skipFile, getFilesBySelected } from "./selectors";
|
||||
@ -29,9 +27,7 @@ const initialState = {
|
||||
treeFolders: [],
|
||||
selected: "none",
|
||||
selectedFolder: null,
|
||||
selection: [],
|
||||
shareData: [],
|
||||
shareDataItems: []
|
||||
selection: []
|
||||
};
|
||||
|
||||
const filesReducer = (state = initialState, action) => {
|
||||
@ -81,14 +77,6 @@ const filesReducer = (state = initialState, action) => {
|
||||
return Object.assign({}, state, {
|
||||
filter: action.filter
|
||||
});
|
||||
case SET_SHARE_DATA_ITEMS:
|
||||
return Object.assign({}, state, {
|
||||
shareDataItems: action.shareDataItems
|
||||
})
|
||||
case SET_SHARE_DATA:
|
||||
return Object.assign({}, state, {
|
||||
shareData: action.shareData
|
||||
})
|
||||
case SELECT_FILE:
|
||||
if (!isFileSelected(state.selection, action.file.id, action.file.parentId)) {
|
||||
return Object.assign({}, state, {
|
||||
|
@ -1112,15 +1112,15 @@ namespace ASC.Api.Documents
|
||||
/// </remarks>
|
||||
/// <returns>Shared file information</returns>
|
||||
[Update("file/{fileId}/share", DisableFormat = true)]
|
||||
public IEnumerable<FileShareWrapper> SetFileSecurityInfo(string fileId, IEnumerable<FileShareParams> share, bool notify, string sharingMessage)
|
||||
public IEnumerable<FileShareWrapper> SetFileSecurityInfo(string fileId, SecurityInfoModel model)
|
||||
{
|
||||
return FilesControllerHelperString.SetFileSecurityInfo(fileId, share, notify, sharingMessage);
|
||||
return FilesControllerHelperString.SetFileSecurityInfo(fileId, model.Share, model.Notify, model.SharingMessage);
|
||||
}
|
||||
|
||||
[Update("file/{fileId:int}/share")]
|
||||
public IEnumerable<FileShareWrapper> SetFileSecurityInfo(int fileId, IEnumerable<FileShareParams> share, bool notify, string sharingMessage)
|
||||
public IEnumerable<FileShareWrapper> SetFileSecurityInfo(int fileId, SecurityInfoModel model)
|
||||
{
|
||||
return FilesControllerHelperInt.SetFileSecurityInfo(fileId, share, notify, sharingMessage);
|
||||
return FilesControllerHelperInt.SetFileSecurityInfo(fileId, model.Share, model.Notify, model.SharingMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1137,14 +1137,14 @@ namespace ASC.Api.Documents
|
||||
/// <category>Sharing</category>
|
||||
/// <returns>Shared folder information</returns>
|
||||
[Update("folder/{folderId}/share", DisableFormat = true)]
|
||||
public IEnumerable<FileShareWrapper> SetFolderSecurityInfo(string folderId, IEnumerable<FileShareParams> share, bool notify, string sharingMessage)
|
||||
public IEnumerable<FileShareWrapper> SetFolderSecurityInfo(string folderId, SecurityInfoModel model)
|
||||
{
|
||||
return FilesControllerHelperString.SetFolderSecurityInfo(folderId, share, notify, sharingMessage);
|
||||
return FilesControllerHelperString.SetFolderSecurityInfo(folderId, model.Share, model.Notify, model.SharingMessage);
|
||||
}
|
||||
[Update("folder/{folderId:int}/share")]
|
||||
public IEnumerable<FileShareWrapper> SetFolderSecurityInfo(int folderId, IEnumerable<FileShareParams> share, bool notify, string sharingMessage)
|
||||
public IEnumerable<FileShareWrapper> SetFolderSecurityInfo(int folderId, SecurityInfoModel model)
|
||||
{
|
||||
return FilesControllerHelperInt.SetFolderSecurityInfo(folderId, share, notify, sharingMessage);
|
||||
return FilesControllerHelperInt.SetFolderSecurityInfo(folderId, model.Share, model.Notify, model.SharingMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -282,12 +282,12 @@ namespace ASC.Files.Core.Security
|
||||
|
||||
public IEnumerable<File<T>> FilterRead<T>(IEnumerable<File<T>> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<File<T>>();
|
||||
return Filter(entries, FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<File<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<T>> FilterRead<T>(IEnumerable<Folder<T>> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<Folder<T>>();
|
||||
return Filter(entries, FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<Folder<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<T>> FilterEdit<T>(IEnumerable<File<T>> entries)
|
||||
|
@ -694,7 +694,7 @@ namespace ASC.Web.Files
|
||||
stream.CanSeek
|
||||
? stream.Length.ToString(CultureInfo.InvariantCulture)
|
||||
: file.ContentLength.ToString(CultureInfo.InvariantCulture));
|
||||
await stream.CopyToAsync(context.Response.Body, StreamExtension.BufferSize);
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -787,7 +787,7 @@ namespace ASC.Web.Files
|
||||
stream.CanSeek
|
||||
? stream.Length.ToString(CultureInfo.InvariantCulture)
|
||||
: storeTemplate.GetFileSize("", path).ToString(CultureInfo.InvariantCulture));
|
||||
stream.StreamCopyTo(context.Response.Body);
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -844,7 +844,7 @@ namespace ASC.Web.Files
|
||||
using (var readStream = store.GetReadStream(FileConstant.StorageDomainTmp, path))
|
||||
{
|
||||
context.Response.Headers.Add("Content-Length", readStream.Length.ToString(CultureInfo.InvariantCulture));
|
||||
await readStream.CopyToAsync(context.Response.Body, StreamExtension.BufferSize);
|
||||
await readStream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
|
||||
store.Delete(FileConstant.StorageDomainTmp, path);
|
||||
@ -935,7 +935,7 @@ namespace ASC.Web.Files
|
||||
using (var stream = fileDao.GetDifferenceStream(file))
|
||||
{
|
||||
context.Response.Headers.Add("Content-Length", stream.Length.ToString(CultureInfo.InvariantCulture));
|
||||
await stream.CopyToAsync(context.Response.Body, StreamExtension.BufferSize);
|
||||
await stream.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
13
products/ASC.Files/Server/Model/SecurityInfoModel.cs
Normal file
13
products/ASC.Files/Server/Model/SecurityInfoModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ASC.Api.Documents;
|
||||
|
||||
namespace ASC.Files.Model
|
||||
{
|
||||
public class SecurityInfoModel
|
||||
{
|
||||
public IEnumerable<FileShareParams> Share { get; set; }
|
||||
public bool Notify { get; set; }
|
||||
public string SharingMessage { get; set; }
|
||||
}
|
||||
}
|
@ -108,6 +108,9 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
"attachment; filename=\"" + fileName + "\"");
|
||||
Status = string.Format("{0}?{1}=bulk", filesLinkUtility.FileHandlerPath, FilesLinkUtility.Action);
|
||||
}
|
||||
|
||||
FillDistributedTask();
|
||||
TaskInfo.PublishChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,6 +263,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
|
||||
internal void CompressToZip(ZipOutputStream zip, Stream stream, IServiceScope scope)
|
||||
{
|
||||
if (entriesPathId == null) return;
|
||||
var setupInfo = scope.ServiceProvider.GetService<SetupInfo>();
|
||||
var fileConverter = scope.ServiceProvider.GetService<FileConverter>();
|
||||
var filesMessageService = scope.ServiceProvider.GetService<FilesMessageService>();
|
||||
@ -333,7 +337,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
{
|
||||
//Take from converter
|
||||
using var readStream = fileConverter.Exec(file, convertToExt);
|
||||
readStream.StreamCopyTo(zip);
|
||||
readStream.CopyTo(zip);
|
||||
if (!string.IsNullOrEmpty(convertToExt))
|
||||
{
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloadedAs, file.Title, convertToExt);
|
||||
@ -346,7 +350,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
|
||||
else
|
||||
{
|
||||
using var readStream = FileDao.GetFileStream(file);
|
||||
readStream.StreamCopyTo(zip);
|
||||
readStream.CopyTo(zip);
|
||||
filesMessageService.Send(file, headers, MessageAction.FileDownloaded, file.Title);
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ namespace ASC.Web.Files.ThirdPartyApp
|
||||
|
||||
using (var stream = new ResponseStream(request.GetResponse()))
|
||||
{
|
||||
stream.CopyTo(context.Response.Body, StreamExtension.BufferSize);
|
||||
stream.CopyTo(context.Response.Body);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -535,7 +535,7 @@ namespace ASC.Web.Files.ThirdPartyApp
|
||||
using (var response = request.GetResponse())
|
||||
using (var stream = new ResponseStream(response))
|
||||
{
|
||||
stream.CopyTo(context.Response.Body, StreamExtension.BufferSize);
|
||||
stream.CopyTo(context.Response.Body);
|
||||
|
||||
var contentLength = jsonFile.Value<string>("size");
|
||||
Logger.Debug("GoogleDriveApp: get file stream contentLength - " + contentLength);
|
||||
|
@ -375,9 +375,10 @@ namespace ASC.Web.Files.Utils
|
||||
folders = fileSecurity.FilterRead(folders).ToList();
|
||||
entries = entries.Concat(folders);
|
||||
|
||||
var files = DaoFactory.GetFileDao<T>().GetFiles(parent.ID, orderBy, filter, subjectGroup, subjectId, searchText, searchInContent, withSubfolders);
|
||||
files = fileSecurity.FilterRead(files).ToList();
|
||||
entries = entries.Concat(files);
|
||||
|
||||
var files = DaoFactory.GetFileDao<T>()
|
||||
.GetFiles(parent.ID, orderBy, filter, subjectGroup, subjectId, searchText, searchInContent, withSubfolders);
|
||||
entries = entries.Concat(fileSecurity.FilterRead(files));
|
||||
|
||||
if (filter == FilterType.None || filter == FilterType.FoldersOnly)
|
||||
{
|
||||
@ -397,7 +398,7 @@ namespace ASC.Web.Files.Utils
|
||||
if (0 < count) entries = entries.Take(count);
|
||||
}
|
||||
|
||||
entries = FileMarker.SetTagsNew<T>(parent, entries);
|
||||
entries = FileMarker.SetTagsNew(parent, entries);
|
||||
|
||||
//sorting after marking
|
||||
if (orderBy.SortedBy == SortedByType.New)
|
||||
@ -409,8 +410,7 @@ namespace ASC.Web.Files.Utils
|
||||
if (0 < count) entries = entries.Take(count);
|
||||
}
|
||||
|
||||
SetFileStatus(entries.OfType<File<T>>().Where(r => r != null && r.ID != null && r.FileEntryType == FileEntryType.File).Select(r => r as File<T>).ToList());
|
||||
|
||||
SetFileStatus(entries.OfType<File<T>>().Where(r => r != null && r.ID != null && r.FileEntryType == FileEntryType.File).ToList());
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
@ -56,14 +56,14 @@ namespace ASC.Web.Files.Utils
|
||||
}
|
||||
|
||||
|
||||
public static Guid Add(Guid userId, object fileId)
|
||||
public static Guid Add<T>(Guid userId, T fileId)
|
||||
{
|
||||
var tabId = Guid.NewGuid();
|
||||
ProlongEditing(fileId, tabId, userId);
|
||||
return tabId;
|
||||
}
|
||||
|
||||
public static bool ProlongEditing(object fileId, Guid tabId, Guid userId, bool editingAlone = false)
|
||||
public static bool ProlongEditing<T>(T fileId, Guid tabId, Guid userId, bool editingAlone = false)
|
||||
{
|
||||
var checkRight = true;
|
||||
var tracker = GetTracker(fileId);
|
||||
@ -89,7 +89,7 @@ namespace ASC.Web.Files.Utils
|
||||
return checkRight;
|
||||
}
|
||||
|
||||
public static void Remove(object fileId, Guid tabId = default, Guid userId = default)
|
||||
public static void Remove<T>(T fileId, Guid tabId = default, Guid userId = default)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
if (tracker != null)
|
||||
@ -117,7 +117,7 @@ namespace ASC.Web.Files.Utils
|
||||
SetTracker(fileId, null);
|
||||
}
|
||||
|
||||
public static void RemoveAllOther(Guid userId, object fileId)
|
||||
public static void RemoveAllOther<T>(Guid userId, T fileId)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
if (tracker != null)
|
||||
@ -138,32 +138,6 @@ namespace ASC.Web.Files.Utils
|
||||
SetTracker(fileId, null);
|
||||
}
|
||||
|
||||
public static bool IsEditing(object fileId)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
if (tracker != null)
|
||||
{
|
||||
var listForRemove = tracker._editingBy
|
||||
.Where(e => !e.Value.NewScheme && (DateTime.UtcNow - e.Value.TrackTime).Duration() > TrackTimeout)
|
||||
.ToList();
|
||||
foreach (var editTab in listForRemove)
|
||||
{
|
||||
tracker._editingBy.Remove(editTab.Key);
|
||||
}
|
||||
|
||||
if (tracker._editingBy.Count == 0)
|
||||
{
|
||||
SetTracker(fileId, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetTracker(fileId, tracker);
|
||||
return true;
|
||||
}
|
||||
SetTracker(fileId, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsEditing<T>(T fileId)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
@ -189,13 +163,13 @@ namespace ASC.Web.Files.Utils
|
||||
SetTracker(fileId, null);
|
||||
return false;
|
||||
}
|
||||
public static bool IsEditingAlone(object fileId)
|
||||
public static bool IsEditingAlone<T>(T fileId)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
return tracker != null && tracker._editingBy.Count == 1 && tracker._editingBy.FirstOrDefault().Value.EditingAlone;
|
||||
}
|
||||
|
||||
public static void ChangeRight(object fileId, Guid userId, bool check)
|
||||
public static void ChangeRight<T>(T fileId, Guid userId, bool check)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
if (tracker != null)
|
||||
@ -218,24 +192,24 @@ namespace ASC.Web.Files.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Guid> GetEditingBy(object fileId)
|
||||
public static List<Guid> GetEditingBy<T>(T fileId)
|
||||
{
|
||||
var tracker = GetTracker(fileId);
|
||||
return tracker != null && IsEditing(fileId) ? tracker._editingBy.Values.Select(i => i.UserId).Distinct().ToList() : new List<Guid>();
|
||||
}
|
||||
|
||||
private static FileTracker GetTracker(object fileId)
|
||||
private static FileTracker GetTracker<T>(T fileId)
|
||||
{
|
||||
if (fileId != null)
|
||||
if (!fileId.Equals(default(T)))
|
||||
{
|
||||
return cache.Get<FileTracker>(TRACKER + fileId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SetTracker(object fileId, FileTracker tracker)
|
||||
private static void SetTracker<T>(T fileId, FileTracker tracker)
|
||||
{
|
||||
if (fileId != null)
|
||||
if (!fileId.Equals(default(T)))
|
||||
{
|
||||
if (tracker != null)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-components",
|
||||
"version": "1.0.381",
|
||||
"version": "1.0.382",
|
||||
"description": "Ascensio System SIA component library",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/asc-web-components.js",
|
||||
|
@ -10,6 +10,7 @@ const StyledProgressBar = styled.div`
|
||||
background-color: #f8f9f9;
|
||||
|
||||
.progress-bar_full-text {
|
||||
display: block;
|
||||
padding: 0px 6px;
|
||||
position: absolute;
|
||||
font-weight: 600;
|
||||
|
@ -154,7 +154,7 @@ namespace ASC.Web.Core.Files
|
||||
|
||||
public bool CanIndex(string fileName)
|
||||
{
|
||||
return extsIndexing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
|
||||
return ExtsIndexing.Contains(GetFileExtension(fileName), StringComparer.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -213,51 +213,108 @@ namespace ASC.Web.Core.Files
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsWebPreviewed { get => (Configuration.GetSection("files:docservice:viewed-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsWebEdited { get => (Configuration.GetSection("files:docservice:edited-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsWebReviewed { get => (Configuration.GetSection("files:docservice:reviewed-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsWebRestrictedEditing { get => (Configuration.GetSection("files:docservice:formfilling-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsWebCommented { get => (Configuration.GetSection("files:docservice:commented-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsMustConvert { get => (Configuration.GetSection("files:docservice:convert-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsIndexing { get => (Configuration.GetSection("files:index").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsIndexing;
|
||||
private List<string> ExtsIndexing { get => extsIndexing ?? (extsIndexing = (Configuration.GetSection("files:index").Get<string[]>() ?? new string[] { }).ToList()); }
|
||||
|
||||
public List<string> ExtsImagePreviewed { get => (Configuration.GetSection("files:viewed-images").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsImagePreviewed;
|
||||
public List<string> ExtsImagePreviewed { get => extsImagePreviewed ?? (extsImagePreviewed = (Configuration.GetSection("files:viewed-images").Get<string[]>() ?? new string[] { }).ToList()); }
|
||||
|
||||
public List<string> ExtsMediaPreviewed { get => (Configuration.GetSection("files:viewed-media").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
private List<string> extsMediaPreviewed;
|
||||
public List<string> ExtsMediaPreviewed { get => extsMediaPreviewed ?? (extsMediaPreviewed = (Configuration.GetSection("files:viewed-media").Get<string[]>() ?? new string[] { }).ToList()); }
|
||||
|
||||
private List<string> extsWebPreviewed;
|
||||
public List<string> ExtsWebPreviewed
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl) ? new List<string>() : extsWebPreviewed; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsWebPreviewed ?? (extsWebPreviewed = (Configuration.GetSection("files:docservice:viewed-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsWebEdited;
|
||||
public List<string> ExtsWebEdited
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl) ? new List<string>() : extsWebEdited; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsWebEdited ?? (extsWebEdited = (Configuration.GetSection("files:docservice:edited-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> ExtsWebEncrypt { get => (Configuration.GetSection("files:docservice:encrypted-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
public List<string> extsWebEncrypt;
|
||||
public List<string> ExtsWebEncrypt { get => extsWebEncrypt ?? (extsWebEncrypt = (Configuration.GetSection("files:docservice:encrypted-docs").Get<string[]>() ?? new string[] { }).ToList()); }
|
||||
|
||||
private List<string> extsWebReviewed;
|
||||
public List<string> ExtsWebReviewed
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl) ? new List<string>() : extsWebReviewed; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsWebReviewed ?? (extsWebReviewed = (Configuration.GetSection("files:docservice:reviewed-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsWebRestrictedEditing;
|
||||
public List<string> ExtsWebRestrictedEditing
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl) ? new List<string>() : extsWebRestrictedEditing; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsWebRestrictedEditing ?? (extsWebRestrictedEditing = (Configuration.GetSection("files:docservice:formfilling-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsWebCommented;
|
||||
public List<string> ExtsWebCommented
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl) ? new List<string>() : extsWebCommented; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceApiUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsWebCommented ?? (extsWebCommented = (Configuration.GetSection("files:docservice:commented-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsMustConvert;
|
||||
public List<string> ExtsMustConvert
|
||||
{
|
||||
get { return string.IsNullOrEmpty(FilesLinkUtility.DocServiceConverterUrl) ? new List<string>() : extsMustConvert; }
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilesLinkUtility.DocServiceConverterUrl))
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return extsMustConvert ?? (extsMustConvert = (Configuration.GetSection("files:docservice:convert-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> extsCoAuthoring;
|
||||
public List<string> ExtsCoAuthoring
|
||||
{
|
||||
get => extsCoAuthoring ?? (extsCoAuthoring = (Configuration.GetSection("files:docservice:coauthor-docs").Get<string[]>() ?? new string[] { }).ToList());
|
||||
}
|
||||
|
||||
public List<string> ExtsCoAuthoring { get => (Configuration.GetSection("files:docservice:coauthor-docs").Get<string[]>() ?? new string[] { }).ToList(); }
|
||||
public IConfiguration Configuration { get; }
|
||||
public FilesLinkUtility FilesLinkUtility { get; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user