Merge branch 'feature/files' into feature/media-viewer

This commit is contained in:
NikolayRechkin 2020-05-08 10:27:58 +03:00
commit fda955966d
27 changed files with 336 additions and 400 deletions

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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" };

View File

@ -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 });
}

View File

@ -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"

View File

@ -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
};
};

View File

@ -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
};
};

View File

@ -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>

View File

@ -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));

View File

@ -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("&");

View File

@ -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();

View File

@ -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, {

View File

@ -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>

View File

@ -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)

View File

@ -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)

View 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; }
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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",

View File

@ -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;

View File

@ -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; }