Merge branch 'release/v1.2' of https://github.com/ONLYOFFICE/AppServer into release/v1.2

This commit is contained in:
Maria Sukhova 2022-06-03 16:33:17 +03:00
commit b9c2b046aa
27 changed files with 164 additions and 63 deletions

View File

@ -483,9 +483,10 @@ export function startUploadSession(
fileName,
fileSize,
relativePath,
encrypted
encrypted,
createOn
) {
const data = { fileName, fileSize, relativePath, encrypted };
const data = { fileName, fileSize, relativePath, encrypted, createOn };
return request({
method: "post",
url: `/files/${folderId}/upload/create_session.json`,

View File

@ -1,11 +1,17 @@
import IconButton from "@appserver/components/icon-button";
import Text from "@appserver/components/text";
import { Base } from "@appserver/components/themes";
import { tablet } from "@appserver/components/utils/device";
import {
isTablet,
isMobile as isMobileUtils,
tablet,
isDesktop,
} from "@appserver/components/utils/device";
import { inject, observer } from "mobx-react";
import PropTypes from "prop-types";
import React from "react";
import styled from "styled-components";
import { isMobile } from "react-device-detect";
const StyledInfoPanelHeader = styled.div`
width: 100%;
@ -51,7 +57,7 @@ const StyledInfoPanelToggleWrapper = styled.div`
`;
StyledInfoPanelToggleWrapper.defaultProps = { theme: Base };
const SubInfoPanelHeader = ({ children, setIsVisible }) => {
const SubInfoPanelHeader = ({ children, setIsVisible, viewAs }) => {
const content = children?.props?.children;
const closeInfoPanel = () => setIsVisible(false);
@ -65,15 +71,17 @@ const SubInfoPanelHeader = ({ children, setIsVisible }) => {
isRootFolder={true}
isInfoPanelVisible={true}
>
<div className="info-panel-toggle-bg">
<IconButton
className="info-panel-toggle"
iconName="images/panel.react.svg"
size="16"
isFill={true}
onClick={closeInfoPanel}
/>
</div>
{!(isTablet() || isMobile || isMobileUtils() || !isDesktop()) && (
<div className="info-panel-toggle-bg">
<IconButton
className="info-panel-toggle"
iconName="images/panel.react.svg"
size="16"
isFill={true}
onClick={closeInfoPanel}
/>
</div>
)}
</StyledInfoPanelToggleWrapper>
</StyledInfoPanelHeader>
);

View File

@ -31,7 +31,7 @@ const StyledInfoPanelWrapper = styled.div.attrs(({ id }) => ({
right: 0;
}
${(props) =>
/* ${(props) =>
(props.isRowView || isMobile) &&
css`
z-index: 309;
@ -40,7 +40,7 @@ const StyledInfoPanelWrapper = styled.div.attrs(({ id }) => ({
bottom: 0;
left: 0;
right: 0;
`}
`} */
`;
const StyledInfoPanel = styled.div`
@ -63,7 +63,7 @@ const StyledInfoPanel = styled.div`
max-width: calc(100vw - 69px);
}
${(props) =>
/* ${(props) =>
(props.isRowView || isMobile) &&
css`
position: absolute;
@ -71,7 +71,7 @@ const StyledInfoPanel = styled.div`
right: 0;
width: 480px;
max-width: calc(100vw - 69px);
`}
`} */
@media (max-width: 428px) {
bottom: 0;
@ -103,14 +103,14 @@ const StyledControlContainer = styled.div`
left: -34px;
}
${(props) =>
/* ${(props) =>
(props.isRowView || isMobile) &&
css`
display: flex !important;
top: 18px;
left: -34px;
`}
`} */
@media (max-width: 428px) {
display: flex;

View File

@ -574,6 +574,8 @@ const Base = {
margin: " 0 auto",
minHeight: "100%",
colorDisabledFileIcons: "#f3f4f4",
content: {
backgroundColor: white,
modalPadding: "0 12px 12px",
@ -1228,6 +1230,8 @@ const Base = {
treeNode: {
background: "#f3f4f4",
disableColor: "#A3A9AE",
dragging: {
draggable: {
background: lightCumulus,

View File

@ -572,6 +572,8 @@ const Dark = {
margin: " 0 auto",
minHeight: "100%",
colorDisabledFileIcons: "#5c5c5c",
content: {
backgroundColor: black,
modalBorderRadius: "6px",
@ -1225,6 +1227,8 @@ const Dark = {
treeNode: {
background: "#3D3D3D",
disableColor: "#858585",
dragging: {
draggable: {
background: "rgba(230, 211, 138, 0.12)",

View File

@ -9,6 +9,30 @@ import Base from "../themes/base";
const StyledTree = styled(Tree)`
.rc-tree-list-holder-inner {
.disable-node {
span.rc-tree-node-content-wrapper {
pointer-events: none;
span.rc-tree-iconEle {
svg {
path {
fill: ${(props) => props.theme.treeNode.disableColor};
}
}
}
span.rc-tree-title {
color: ${(props) => props.theme.treeNode.disableColor} !important;
}
}
span.rc-tree-switcher {
pointer-events: none;
svg {
path {
fill: ${(props) => props.theme.treeNode.disableColor};
}
}
}
}
.rc-tree-treenode {
height: 36px;
display: flex;

View File

@ -196,6 +196,9 @@ const EditingWrapperComponent = (props) => {
const [OkIconIsHovered, setIsHoveredOk] = useState(false);
const [CancelIconIsHovered, setIsHoveredCancel] = useState(false);
const [isTouchOK, setIsTouchOK] = useState(false);
const [isTouchCancel, setIsTouchCancel] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const inputRef = React.useRef(null);
@ -226,7 +229,9 @@ const EditingWrapperComponent = (props) => {
if (
(e.relatedTarget && e.relatedTarget.classList.contains("edit-button")) ||
OkIconIsHovered ||
CancelIconIsHovered
CancelIconIsHovered ||
isTouchOK ||
isTouchCancel
)
return false;
@ -274,6 +279,7 @@ const EditingWrapperComponent = (props) => {
data-itemid={itemId}
onMouseEnter={setIsHoveredOkHandler}
onMouseLeave={setIsHoveredOkHandler}
onTouchStart={() => setIsTouchOK(true)}
isHovered={OkIconIsHovered}
title=""
/>
@ -287,6 +293,7 @@ const EditingWrapperComponent = (props) => {
data-action="cancel"
onMouseEnter={setIsHoveredCancelHandler}
onMouseLeave={setIsHoveredCancelHandler}
onTouchStart={() => setIsTouchCancel(true)}
isHovered={CancelIconIsHovered}
title=""
/>

View File

@ -84,10 +84,20 @@ class TreeFolders extends React.Component {
super(props);
this.state = { isExpand: false };
this.selectionFoldersId = [];
}
componentDidMount() {
const { selectionFiles } = this.props;
this.props.isLoadingNodes && this.props.setIsLoadingNodes(false);
if (selectionFiles) {
for (let item of selectionFiles) {
if (!item.fileExst) {
this.selectionFoldersId.push(item.id);
}
}
}
}
onBadgeClick = (e) => {
@ -236,15 +246,19 @@ class TreeFolders extends React.Component {
const serviceFolder = !!item.providerKey;
let value = "";
let value = "",
disableNodeValue = "";
if (dragging) value = `${item.id} dragging ${provider}`;
if (this.selectionFoldersId && this.selectionFoldersId.includes(item.id))
disableNodeValue = "disable-node";
if ((item.folders && item.folders.length > 0) || serviceFolder) {
return (
<TreeNode
id={item.id}
key={item.id}
className={`tree-drag ${item.folderClassName}`}
className={`tree-drag ${item.folderClassName} ${disableNodeValue}`}
data-value={value}
title={item.title}
icon={this.getFolderIcon(item)}
@ -275,7 +289,7 @@ class TreeFolders extends React.Component {
<TreeNode
id={item.id}
key={item.id}
className={`tree-drag ${item.folderClassName}`}
className={`tree-drag ${item.folderClassName} ${disableNodeValue}`}
data-value={value}
title={item.title}
needTopMargin={item.rootFolderType === FolderType.TRASH}

View File

@ -19,6 +19,7 @@ const FolderTreeBody = ({
parentId,
isLoadingNodes,
setIsLoadingNodes,
selectionFiles,
}) => {
const { t } = useTranslation(["SelectFolder", "Common"]);
@ -63,6 +64,7 @@ const FolderTreeBody = ({
defaultExpandAll
parentId={parentId}
firstLoadScroll={firstLoadScroll}
selectionFiles={selectionFiles}
/>
</Scrollbar>
</div>

View File

@ -158,6 +158,7 @@ const OperationsPanelComponent = (props) => {
const isVisible = intermediateHidden ? false : visible;
return (
<SelectFolderDialog
selectionFiles={selection}
isDisableTree={isLoading}
foldersType="exceptSortedByTags"
isPanelVisible={isVisible}

View File

@ -36,6 +36,7 @@ const SelectFolderDialogAsideView = ({
isDisableTree,
isDisableButton,
parentId,
selectionFiles,
}) => {
return (
<StyledModalDialog
@ -74,6 +75,7 @@ const SelectFolderDialogAsideView = ({
<div className="selection-panel_aside-tree">
{folderId && resultingFolderTree ? (
<FolderTreeBody
selectionFiles={selectionFiles}
parentId={parentId}
theme={theme}
folderTree={resultingFolderTree}

View File

@ -198,6 +198,7 @@ class SelectFolderDialog extends React.Component {
isDisableButton,
isRecycleBin,
currentFolderId,
selectionFiles,
} = this.props;
const {
displayType,
@ -215,6 +216,7 @@ class SelectFolderDialog extends React.Component {
return displayType === "aside" ? (
<SelectFolderDialogAsideView
selectionFiles={selectionFiles}
theme={theme}
t={t}
isPanelVisible={isPanelVisible}
@ -242,6 +244,7 @@ class SelectFolderDialog extends React.Component {
/>
) : (
<SelectionPanel
selectionFiles={selectionFiles}
t={t}
theme={theme}
isPanelVisible={isPanelVisible}

View File

@ -23,8 +23,11 @@ class SelectFolderInput extends React.PureComponent {
resultingFolderTree: [],
baseId: "",
};
this._isMount = false;
}
async componentDidMount() {
this._isMount = true;
const {
setFirstLoad,
treeFolders,
@ -84,6 +87,10 @@ class SelectFolderInput extends React.PureComponent {
});
}
}
componentWillUnmount() {
this._isMount = false;
}
setFolderPath = async (folderId) => {
const foldersArray = await getFolderPath(folderId);
@ -117,11 +124,12 @@ class SelectFolderInput extends React.PureComponent {
clearTimeout(timerId);
timerId = null;
this.setState({
newFolderPath: convertFoldersArray,
isLoading: false,
newId: folderId,
});
this._isMount &&
this.setState({
newFolderPath: convertFoldersArray,
isLoading: false,
newId: folderId,
});
} catch (e) {
toastr.error(e);
clearTimeout(timerId);
@ -137,10 +145,11 @@ class SelectFolderInput extends React.PureComponent {
try {
const convertFoldersArray = await this.setFolderPath(folderId);
this.setState({
baseFolderPath: convertFoldersArray,
isLoading: false,
});
this._isMount &&
this.setState({
baseFolderPath: convertFoldersArray,
isLoading: false,
});
} catch (e) {
toastr.error(e);
this.setState({

View File

@ -18,6 +18,11 @@ class FilesListWrapper extends React.Component {
hasNextPage: true,
files: [],
};
this._isMount = false;
}
componentDidMount() {
this._isMount = true;
}
componentDidUpdate(prevProps) {
@ -41,6 +46,9 @@ class FilesListWrapper extends React.Component {
}
}
componentWillUnmount() {
this._isMount = false;
}
_loadNextPage = () => {
const { files, page } = this.state;
const {
@ -88,12 +96,14 @@ class FilesListWrapper extends React.Component {
const newFilesList = [...files].concat(finalData);
const hasNextPage = newFilesList.length < data.total - 1;
this._isLoadNextPage = false;
this.setState((state) => ({
hasNextPage: hasNextPage,
isNextPageLoading: false,
page: state.page + 1,
files: newFilesList,
}));
this._isMount &&
this.setState((state) => ({
hasNextPage: hasNextPage,
isNextPageLoading: false,
page: state.page + 1,
files: newFilesList,
}));
} catch (e) {
toastr.error(e);
}

View File

@ -46,6 +46,7 @@ const SelectionPanelBody = ({
newFilter,
isDisableButton,
parentId,
selectionFiles,
}) => {
return (
<StyledModalDialog
@ -72,6 +73,7 @@ const SelectionPanelBody = ({
{folderId && resultingFolderTree ? (
<FolderTreeBody
selectionFiles={selectionFiles}
theme={theme}
folderTree={resultingFolderTree}
onSelect={onSelectFolder}

View File

@ -146,8 +146,10 @@ const StyledRow = styled.div`
::after {
position: absolute;
display: block;
background-color: #f3f4f4;
border-top-right-radius: 50%;
background-color: ${(props) =>
props.theme.modalDialog.colorDisabledFileIcons};
border-top-right-radius: 45%;
left: 18px;
top: 6px;
width: 27px;
@ -159,6 +161,7 @@ const StyledRow = styled.div`
.selection-panel_text p {
color: ${(props) => props.theme.text.disableColor};
}
cursor: default;
`}
`;

View File

@ -351,7 +351,7 @@ export default inject(
const exst = item?.fileInfo?.fileExst;
splitted = item.file.name.split(".");
ext = exst ? fileExst : splitted.length > 1 ? "." + splitted.pop() : "";
ext = exst ? exst : splitted.length > 1 ? "." + splitted.pop() : "";
name = splitted[0];
} else {
ext = item.fileInfo.fileExst;

View File

@ -56,8 +56,12 @@ const StyledTableRow = styled(TableRow)`
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
margin-top: -1px;
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
${(props) =>
!props.showHotkeyBorder &&
css`
border-top: ${(props) =>
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
`}
}
.table-container_file-name-cell {
margin-left: -24px;

View File

@ -148,7 +148,7 @@ const SectionPagingContent = ({
}, [files, folders, filter, pageItems]);
return !tReady ||
(filter.total < filter.pageCount && filter.total < 26) ||
(filter.total <= filter.pageCount && filter.total < 26) ||
isHidePagination ? (
<></>
) : (

View File

@ -856,7 +856,8 @@ class UploadDataStore {
fileName,
fileSize,
relativePath,
file.encrypted
file.encrypted,
file.lastModifiedDate
)
.then((res) => {
const location = res.data.location;

View File

@ -1103,6 +1103,7 @@ namespace ASC.Files.Core.Data
result.ContentLength = uploadSession.BytesTotal;
result.Comment = FilesCommonResource.CommentUpload;
result.Encrypted = uploadSession.Encrypted;
result.CreateOn = uploadSession.File.CreateOn;
return result;
}

View File

@ -7,7 +7,7 @@ namespace ASC.Files.Model
public string FileName { get; set; }
public long FileSize { get; set; }
public string RelativePath { get; set; }
public ApiDateTime LastModified { get; set; }
public ApiDateTime CreateOn { get; set; }
public bool Encrypted { get; set; }
}
}

View File

@ -242,7 +242,7 @@ namespace ASC.Web.Files.Utils
#region chunked upload
public async Task<File<T>> VerifyChunkedUploadAsync<T>(T folderId, string fileName, long fileSize, bool updateIfExists, ApiDateTime lastModified, string relativePath = null)
public async Task<File<T>> VerifyChunkedUploadAsync<T>(T folderId, string fileName, long fileSize, bool updateIfExists, string relativePath = null)
{
var maxUploadSize = await GetMaxFileSizeAsync(folderId, true);
@ -252,21 +252,17 @@ namespace ASC.Web.Files.Utils
var file = await VerifyFileUploadAsync(folderId, fileName, updateIfExists, relativePath);
file.ContentLength = fileSize;
if(lastModified != null)
{
file.ModifiedOn = lastModified;
}
return file;
}
public async Task<ChunkedUploadSession<T>> InitiateUploadAsync<T>(T folderId, T fileId, string fileName, long contentLength, bool encrypted)
public async Task<ChunkedUploadSession<T>> InitiateUploadAsync<T>(T folderId, T fileId, string fileName, long contentLength, bool encrypted, ApiDateTime createOn = null)
{
var file = ServiceProvider.GetService<File<T>>();
file.ID = fileId;
file.FolderID = folderId;
file.Title = fileName;
file.ContentLength = contentLength;
file.ContentLength = contentLength;
file.CreateOn = createOn;
var dao = DaoFactory.GetFileDao<T>();
var uploadSession = await dao.CreateUploadSessionAsync(file, contentLength);

View File

@ -754,27 +754,27 @@ namespace ASC.Api.Documents
[Create("{folderId}/upload/create_session")]
public Task<object> CreateUploadSessionFromBodyAsync(string folderId, [FromBody] SessionModel sessionModel)
{
return FilesControllerHelperString.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.LastModified, sessionModel.Encrypted);
return FilesControllerHelperString.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.Encrypted, sessionModel.CreateOn);
}
[Create("{folderId}/upload/create_session")]
[Consumes("application/x-www-form-urlencoded")]
public Task<object> CreateUploadSessionFromFormAsync(string folderId, [FromForm] SessionModel sessionModel)
{
return FilesControllerHelperString.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.LastModified, sessionModel.Encrypted);
return FilesControllerHelperString.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.Encrypted, sessionModel.CreateOn);
}
[Create("{folderId:int}/upload/create_session")]
public Task<object> CreateUploadSessionFromBodyAsync(int folderId, [FromBody] SessionModel sessionModel)
{
return FilesControllerHelperInt.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.LastModified, sessionModel.Encrypted);
return FilesControllerHelperInt.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.Encrypted, sessionModel.CreateOn);
}
[Create("{folderId:int}/upload/create_session")]
[Consumes("application/x-www-form-urlencoded")]
public Task<object> CreateUploadSessionFromFormAsync(int folderId, [FromForm] SessionModel sessionModel)
{
return FilesControllerHelperInt.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.LastModified, sessionModel.Encrypted);
return FilesControllerHelperInt.CreateUploadSessionAsync(folderId, sessionModel.FileName, sessionModel.FileSize, sessionModel.RelativePath, sessionModel.Encrypted, sessionModel.CreateOn);
}
/// <summary>

View File

@ -278,13 +278,13 @@ namespace ASC.Files.Helpers
return configuration;
}
public async Task<object> CreateUploadSessionAsync(T folderId, string fileName, long fileSize, string relativePath, ApiDateTime lastModified, bool encrypted)
public async Task<object> CreateUploadSessionAsync(T folderId, string fileName, long fileSize, string relativePath, bool encrypted, ApiDateTime createOn)
{
var file = await FileUploader.VerifyChunkedUploadAsync(folderId, fileName, fileSize, FilesSettingsHelper.UpdateIfExist, lastModified, relativePath);
var file = await FileUploader.VerifyChunkedUploadAsync(folderId, fileName, fileSize, FilesSettingsHelper.UpdateIfExist, relativePath);
if (FilesLinkUtility.IsLocalFileUploader)
{
var session = await FileUploader.InitiateUploadAsync(file.FolderID, file.ID ?? default, file.Title, file.ContentLength, encrypted);
var session = await FileUploader.InitiateUploadAsync(file.FolderID, file.ID ?? default, file.Title, file.ContentLength, encrypted, createOn);
var responseObject = await ChunkedUploadSessionHelper.ToResponseObjectAsync(session, true);
return new

View File

@ -55,7 +55,12 @@ const ReactSmartBanner = (props) => {
kindle: "kindle-fire-app",
};
return isMobile && isBannerVisible && ready ? (
const isTouchDevice =
"ontouchstart" in window ||
navigator.maxTouchPoints > 0 ||
navigator.msMaxTouchPoints > 0;
return isMobile && isBannerVisible && ready && isTouchDevice ? (
<Wrapper>
<SmartBanner
title={t("SmartBanner:AppName")}

View File

@ -471,7 +471,7 @@ const Editor = () => {
onRequestSharingSettings = onSDKRequestSharingSettings;
}
if (fileInfo && fileInfo.canEdit) {
if (fileInfo && fileInfo.canEdit && !fileInfo.providerKey) {
onRequestRename = onSDKRequestRename;
}