Merge branch 'develop' into feature/custom-theme

This commit is contained in:
Alexey Safronov 2022-11-22 17:03:12 +03:00
commit ff53dc882e
13 changed files with 233 additions and 108 deletions

View File

@ -12,6 +12,12 @@ import config from "PACKAGE_FILE";
export default function withBadges(WrappedComponent) {
class WithBadges extends React.Component {
constructor(props) {
super(props);
this.state = { disableBadgeClick: false, disableUnpinClick: false };
}
onShowVersionHistory = () => {
const {
homepage,
@ -28,22 +34,42 @@ export default function withBadges(WrappedComponent) {
};
onBadgeClick = () => {
if (this.state.disableBadgeClick) return;
const { item, markAsRead, setNewFilesPanelVisible } = this.props;
this.setState(() => ({
disableBadgeClick: true,
}));
const enableBadgeClick = () => {
this.setState({ disableBadgeClick: false });
};
if (item.fileExst) {
markAsRead([], [item.id], item);
markAsRead([], [item.id], item).then(() => {
enableBadgeClick();
});
} else {
setNewFilesPanelVisible(true, null, item);
setNewFilesPanelVisible(true, null, item).then(() => {
enableBadgeClick();
});
}
};
onUnpinClick = (e) => {
if (this.state.disableUnpinClick) return;
this.setState({ disableUnpinClick: true });
const { t, setPinAction } = this.props;
const { action, id } = e.target.closest(".is-pinned").dataset;
if (!action && !id) return;
setPinAction(action, id, t);
setPinAction(action, id, t).then(() => {
this.setState({ disableUnpinClick: false });
});
};
setConvertDialogVisible = () => {

View File

@ -49,6 +49,8 @@ const ArticleBodyContent = (props) => {
archiveFolderId,
} = props;
const [disableBadgeClick, setDisableBadgeClick] = React.useState(false);
const campaigns = (localStorage.getItem("campaigns") || "")
.split(",")
.filter((campaign) => campaign.length > 0);
@ -148,9 +150,18 @@ const ArticleBodyContent = (props) => {
[categoryType, roomsFolderId, archiveFolderId]
);
const onShowNewFilesPanel = React.useCallback((folderId) => {
props.setNewFilesPanelVisible(true, [`${folderId}`]);
}, []);
const onShowNewFilesPanel = React.useCallback(
async (folderId) => {
if (disableBadgeClick) return;
setDisableBadgeClick(true);
await props.setNewFilesPanelVisible(true, [`${folderId}`]);
setDisableBadgeClick(false);
},
[disableBadgeClick]
);
return (
<>

View File

@ -14,8 +14,9 @@ const StyledLink = styled(Link)`
color: #316daa;
`;
const ConfirmEmailBar = ({ t, onClick, onClose, onLoad }) => {
const ConfirmEmailBar = ({ t, tReady, onClick, onClose, onLoad }) => {
return (
tReady && (
<SnackBar
headerText={t("ConfirmEmailHeader")}
text={
@ -29,6 +30,7 @@ const ConfirmEmailBar = ({ t, onClick, onClose, onLoad }) => {
onLoad={onLoad}
clickAction={onClose}
/>
)
);
};

View File

@ -16,6 +16,7 @@ const StyledLink = styled(Link)`
const QuotasBar = ({
t,
tReady,
isRoomQuota,
currentValue,
maxValue,
@ -57,7 +58,8 @@ const QuotasBar = ({
),
};
return isRoomQuota ? (
return tReady ? (
isRoomQuota ? (
<SnackBar
headerText={roomQuota.header}
text={roomQuota.description}
@ -75,6 +77,9 @@ const QuotasBar = ({
onLoad={onLoad}
clickAction={onCloseAction}
/>
)
) : (
<></>
);
};

View File

@ -11,8 +11,8 @@ const StyledContainer = styled.div`
${isMobileOnly &&
css`
width: calc(100% + 8px);
max-width: calc(100% + 8px);
width: calc(100% + 16px);
max-width: calc(100% + 16px);
margin-right: -16px;
margin-top: 48px;

View File

@ -33,6 +33,7 @@ class NewFilesPanel extends React.Component {
state = { readingFiles: [], inProgress: false };
onClose = () => {
if (this.state.inProgress) return;
this.props.setNewFilesPanelVisible(false);
};
@ -52,16 +53,27 @@ class NewFilesPanel extends React.Component {
};
onMarkAsRead = () => {
const fileIds = [];
const folderIds = [];
for (let item of this.props.newFiles) {
if (item.fileExst) fileIds.push(item.id);
else folderIds.push(item.id);
}
const { inProgress, readingFiles } = this.state;
if (inProgress) return;
this.setState({ inProgress: true });
const files = [];
const folders = [];
for (let item of this.props.newFiles) {
if (item.fileExst) files.push(item);
else folders.push(item);
}
const fileIds = files
.filter((f) => !readingFiles.includes(f.id.toString()))
.map((f) => f.id);
const folderIds = folders
.filter((f) => !readingFiles.includes(f.id.toString()))
.map((f) => f.id);
this.props
.markAsRead(folderIds, fileIds)
.then(() => this.setNewBadgeCount())
@ -78,6 +90,10 @@ class NewFilesPanel extends React.Component {
};
onNewFileClick = (e) => {
if (this.state.inProgress) return;
this.setState({ inProgress: true });
const { id, extension: fileExst } = e.target.dataset;
const {
@ -92,16 +108,23 @@ class NewFilesPanel extends React.Component {
const item = newFiles.find((file) => file.id.toString() === id);
if (readingFiles.includes(id)) return this.onFileClick(item);
if (readingFiles.includes(id)) {
this.setState({ inProgress: false });
return this.onFileClick(item);
}
markAsRead(folderIds, fileIds, item)
.then(() => {
//updateFolderBadge(folderId, 1);
readingFiles.push(id);
this.setState({ readingFiles });
this.setState({ readingFiles, inProgress: false });
this.onFileClick(item);
})
.then(() => refreshFiles())
.then(() => {
refreshFiles();
})
.catch((err) => toastr.error(err));
};
@ -159,7 +182,11 @@ class NewFilesPanel extends React.Component {
newFiles,
} = this.props;
const filesCount = newFiles.length;
const { readingFiles } = this.state;
const filesCount = newFiles.filter(
(f) => !readingFiles.includes(f.id.toString())
).length;
updateRootBadge(+newFilesIds[0], filesCount);
if (newFilesIds.length <= 1) {
@ -175,6 +202,7 @@ class NewFilesPanel extends React.Component {
render() {
//console.log("NewFiles panel render");
const { t, visible, isLoading, newFiles, theme } = this.props;
const { inProgress } = this.state;
const zIndex = 310;
return (
@ -244,12 +272,13 @@ class NewFilesPanel extends React.Component {
size="normal"
primary
onClick={this.onMarkAsRead}
isLoading={this.state.inProgress}
isLoading={inProgress}
/>
<Button
className="new_files_panel-button"
label={t("Common:CloseButton")}
size="normal"
isDisabled={inProgress}
onClick={this.onClose}
/>
</StyledFooter>

View File

@ -13,7 +13,11 @@ const DialogAsideLoader = ({
const renderClearDialogAsideLoader = () => {
return (
<StyledDialogAsideLoader withFooterBorder={withFooterBorder} visible>
<StyledDialogAsideLoader
withFooterBorder={withFooterBorder}
isPanel={isPanel}
visible
>
<div className="dialog-loader-header">
<Loaders.Rectangle height="29px" />
</div>
@ -23,6 +27,7 @@ const DialogAsideLoader = ({
<div className="dialog-loader-footer">
<Loaders.Rectangle height="40px" />
<Loaders.Rectangle height="40px" />
</div>
</StyledDialogAsideLoader>
);
@ -32,7 +37,7 @@ const DialogAsideLoader = ({
renderClearDialogAsideLoader()
) : (
<>
<Backdrop visible isAside />
<Backdrop visible isAside zIndex={zIndex} />
<StyledDialogAsideLoader visible isPanel={isPanel}>
<Aside className="dialog-aside-loader" visible zIndex={zIndex}>
{renderClearDialogAsideLoader()}

View File

@ -1,41 +1,43 @@
import styled, { css } from "styled-components";
const StyledDialogAsideLoader = styled.div`
${(props) =>
props.isPanel &&
css`
.dialog-aside-loader {
padding: 0;
transform: translateX(${(props) => (props.visible ? "0" : "500px")});
width: 500px;
@media (max-width: 550px) {
width: 320px;
transform: translateX(${(props) => (props.visible ? "0" : "320px")});
}
}
`}
${(props) =>
props.isPanel
? css`
.dialog-loader-header {
padding: 12px 16px;
height: 53px;
border-bottom: ${(props) =>
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
box-sizing: border-box;
margin-right: -16px;
}
.dialog-loader-body {
padding: 16px;
margin-right: -16px;
}
.dialog-loader-footer {
padding: 12px 16px;
position: fixed;
bottom: 0;
width: 468px;
@media (max-width: 550px) {
width: 288px;
}
height: 71px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
box-sizing: border-box;
border-top: ${(props) =>
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
}
`
: css`

View File

@ -2,38 +2,37 @@ import React from "react";
import PropTypes from "prop-types";
import styled, { keyframes } from "styled-components";
export const keyFrameBlue = keyframes`
0% { top:120px; background: #de7a59; }
10% { top:120px; background: #F2CBBF; }
14% { background: #fff; top: 120px; }
15% { background: #fff; top: 0; }
20% { background: #E6E4E4; }
30% { background: #D2D2D2; }
export const keyFrameBlue = (props) => keyframes`
0% { background: #de7a59; top: 120px; }
10% { background: ${props.colorStep_1}; top: 120px; }
14% { background: ${props.colorStep_2}; top: 120px; }
15% { background: ${props.colorStep_2}; top: 0; }
20% { background: ${props.colorStep_3}; }
30% { background: ${props.colorStep_4}; }
40% { top: 120px; }
100% { top: 120px; background: #de7a59; }
100% { background: #de7a59; top: 120px; }
`;
export const keyFrameRed = keyframes`
0% { top:100px; background: #55bce6; opacity: 1; }
10% { top:100px; background: #BFE8F8; opacity: 1; }
14% { background: #fff; top: 100px; opacity: 1; }
15% { background: #fff; top: 0; opacity: 1; }
20% { background: #ffffff; top: 0; opacity: 0; }
25% { background: #ffffff; top: 0; opacity: 0; }
45% { background: #EFEFEF; top: 0; opacity: 0,2; }
100% { top: 100px; background: #55bce6; }
export const keyFrameRed = (props) => keyframes`
0% { background: #55bce6; top: 100px; opacity: 1; }
10% { background: ${props.colorStep_1}; top: 100px; opacity: 1; }
14% { background: ${props.colorStep_2}; top: 100px; opacity: 1; }
15% { background: ${props.colorStep_2}; top: 0; opacity: 1; }
20% { background: ${props.colorStep_2}; top: 0; opacity: 0; }
45% { background: ${props.colorStep_3}; top: 0; }
100% { background: #55bce6; top: 100px; }
`;
export const keyFrameGreen = keyframes`
0% { top:110px; background: #a1cb5c; opacity: 1; }
10% { top:110px; background: #CBE0AC; opacity: 1; }
14% { background: #fff; top: 110px; opacity: 1; }
15% { background: #fff; top: 0; opacity: 1; }
20% { background: #ffffff; top: 0; opacity: 0; }
25% { background: #EFEFEF; top: 0; opacity: 1; }
30% { background: #E6E4E4; }
export const keyFrameGreen = (props) => keyframes`
0% { background: #a1cb5c; top: 110px; opacity: 1; }
10% { background: ${props.colorStep_1}; top: 110px; opacity: 1; }
14% { background: ${props.colorStep_2}; top: 110px; opacity: 1; }
15% { background: ${props.colorStep_2}; top: 0; opacity: 1; }
20% { background: ${props.colorStep_2}; top: 0; opacity: 0; }
25% { background: ${props.colorStep_3}; top: 0; opacity: 1; }
30% { background: ${props.colorStep_4}; }
70% { top: 110px; }
100% { top: 110px; background: #a1cb5c; }
100% { background: #a1cb5c; top: 110px; }
`;
const Romb = styled.div`
@ -63,9 +62,9 @@ const Romb = styled.div`
(props.color === "green" && "2")};
animation: ${(props) =>
(props.color === "blue" && keyFrameBlue) ||
(props.color === "red" && keyFrameRed) ||
(props.color === "green" && keyFrameGreen)}
(props.color === "blue" && keyFrameBlue(props.theme.rombsLoader.blue)) ||
(props.color === "red" && keyFrameRed(props.theme.rombsLoader.red)) ||
(props.color === "green" && keyFrameGreen(props.theme.rombsLoader.green))}
2s ease-in-out 0s infinite;
`;

View File

@ -1497,6 +1497,26 @@ const Base = {
borderRadius: "50%",
},
rombsLoader: {
blue: {
colorStep_1: "#F2CBBF",
colorStep_2: "#fff",
colorStep_3: "#E6E4E4",
colorStep_4: "#D2D2D2",
},
red: {
colorStep_1: "#BFE8F8",
colorStep_2: "#fff",
colorStep_3: "#EFEFEF",
},
green: {
colorStep_1: "#CBE0AC",
colorStep_2: "#fff",
colorStep_3: "#EFEFEF",
colorStep_4: "#E6E4E4",
},
},
dialogLoader: {
borderBottom: "1px solid rgb(222, 226, 230)",
},

View File

@ -1487,7 +1487,26 @@ const Dark = {
marginRight: "2px",
borderRadius: "50%",
},
rombsLoader: {
blue: {
colorStep_1: "#333",
colorStep_2: "#333",
colorStep_3: "#323032",
colorStep_4: "#323032",
},
red: {
colorStep_1: "#333",
colorStep_2: "#333",
colorStep_3: "#323032",
colorStep_4: "#323032",
},
green: {
colorStep_1: "#333",
colorStep_2: "#333",
colorStep_3: "#323032",
colorStep_4: "#323032",
},
},
dialogLoader: {
borderBottom: "1px solid #292929",
},

View File

@ -73,6 +73,8 @@ internal class FileMoveCopyOperationData<T> : FileOperationData<T>
class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
{
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
private readonly int _daoFolderId;
private readonly string _thirdpartyFolderId;
private readonly bool _copy;
@ -382,10 +384,15 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
{
if (isRoom && toFolder.FolderType == FolderType.VirtualRooms)
{
await _semaphore.WaitAsync();
await countRoomChecker.CheckAppend();
}
newFolderId = await FolderDao.MoveFolderAsync(folder.Id, toFolderId, CancellationToken);
_semaphore.Release();
}
else
{
newFolderId = await FolderDao.MoveFolderAsync(folder.Id, toFolderId, CancellationToken);
}
}
newFolder = await folderDao.GetFolderAsync(newFolderId);

View File

@ -50,13 +50,12 @@ public abstract class FileOperation : DistributedTaskProgress
_culture = Thread.CurrentThread.CurrentCulture.Name;
this[Owner] = ((IAccount)(_principal ?? Thread.CurrentPrincipal).Identity).ID.ToString();
this[Src] = "";
this[Src] = _props.ContainsValue(Src) ? this[Src] : "";
this[Progress] = 0;
this[Res] = "";
this[Err] = "";
this[Process] = 0;
this[Finish] = false;
this[Hold] = false;
}
protected void IncrementProgress()
@ -84,6 +83,7 @@ internal class ComposeFileOperation<T1, T2> : FileOperation
{
ThirdPartyOperation = thirdPartyOperation;
DaoOperation = daoOperation;
this[Hold] = ThirdPartyOperation[Hold] || DaoOperation[Hold];
}
public override async Task RunJob(DistributedTask _, CancellationToken cancellationToken)