Web: Files: created download panel

This commit is contained in:
Viktor Fomin 2021-01-19 13:38:15 +03:00
parent a82ade029d
commit 2b2b195954
6 changed files with 591 additions and 0 deletions

View File

@ -0,0 +1,243 @@
import React from "react";
import styled from "styled-components";
import {
IconButton,
Row,
Text,
Icons,
Tooltip,
Link,
} from "asc-web-components";
import LoadingButton from "./LoadingButton";
import { connect } from "react-redux";
import {
getLoadingFile,
getFileByFileId,
} from "../../../store/files/selectors";
const StyledFileRow = styled(Row)`
margin: 0 16px;
width: calc(100% - 16px);
box-sizing: border-box;
font-weight: 600;
.download_panel-icon {
margin-left: auto;
line-height: 24px;
display: flex;
align-items: center;
flex-direction: row-reverse;
svg {
width: 16px;
height: 16px;
}
}
.__react_component_tooltip.type-light {
background-color: #f8f7bf !important;
}
.__react_component_tooltip.place-left::after {
border-left: 6px solid #f8f7bf !important;
}
.__react_component_tooltip.place-right::after {
border-right: 6px solid #f8f7bf !important;
}
.__react_component_tooltip.place-top::after {
border-top: 6px solid #f8f7bf !important;
}
.__react_component_tooltip.place-bottom::after {
border-bottom: 6px solid #f8f7bf !important;
}
`;
const checkExt = (ext) => {
const extArray = [
"avi",
"csv",
"djvu",
"doc",
"docx",
"dvd",
"ebook",
"file_archive",
"flv",
"html",
"iaf",
"image",
"m2ts",
"mkv",
"mov",
"mp4",
"mpg",
"odp",
"ods",
"odt",
"pdf",
"pps",
"ppsx",
"ppt",
"pptx",
"rtf",
"sound",
"svg",
"txt",
"xls",
"xlsx",
"xps",
];
return extArray.includes(ext);
};
const FileRow = (props) => {
const {
t,
item,
index,
archiveFormats,
imageFormats,
soundFormats,
uploaded,
onOpenSharingPanel,
cancelCurrentUpload,
mediaViewerImageFormats,
mediaViewerMediaFormats,
onMediaClick,
currentFileUploadProgress,
currentFile,
} = props;
const name = item.file.name.split(".");
let ext = name.length > 1 ? name.pop() : "";
let originalExt = null;
if (archiveFormats.includes(`.${ext}`)) {
originalExt = ext;
ext = "file_archive";
}
if (imageFormats.includes(`.${ext}`)) {
originalExt = ext;
ext = "image";
}
if (soundFormats.includes(`.${ext}`)) {
originalExt = ext;
ext = "sound";
}
const fileIcon = checkExt(ext) ? (
<img src={`images/icons/24/${ext}.svg`} alt={`${ext}`} />
) : (
<img src="images/icons/24/file.svg" alt="file" />
);
const color =
item.fileId && currentFile(item.fileId) && currentFile(item.fileId).shared
? "#657077"
: "#A3A9AE";
return (
<>
{item.cancel ? (
<></>
) : (
<StyledFileRow
className="download-row"
key={item.uniqueId}
checkbox={false}
element={fileIcon}
>
<>
{item.fileId ? (
mediaViewerImageFormats.includes(`.${ext}`) ||
mediaViewerMediaFormats.includes(`.${ext}`) ||
mediaViewerImageFormats.includes(`.${originalExt}`) ||
mediaViewerMediaFormats.includes(`.${originalExt}`) ? (
<Text
fontWeight="600"
// MediaViewer doesn't work
/*onClick={() => onMediaClick(item.fileId)}*/
>
{name}
</Text>
) : (
<Link
fontWeight="600"
href={item.fileInfo ? item.fileInfo.webUrl : ""}
target="_blank"
>
{name}
</Link>
)
) : (
<Text fontWeight="600">{name}</Text>
)}
{originalExt || ext ? (
<Text fontWeight="600" color="#A3A9AE">
.{originalExt ? originalExt : ext}
</Text>
) : (
<></>
)}
{item.fileId ? (
<IconButton
iconName="CatalogSharedIcon"
className="download_panel-icon"
color={color}
isClickable={true}
onClick={() =>
onOpenSharingPanel(item.fileInfo ? item.fileInfo : "")
}
/>
) : item.error || (!item.fileId && uploaded) ? (
<div className="download_panel-icon">
{" "}
<Icons.LoadErrorIcon
size="medium"
data-for="errorTooltip"
data-tip={item.error || t("UnknownError")}
/>
<Tooltip
id="errorTooltip"
className="tooltip-custom"
getContent={(dataTip) => (
<Text fontSize="13px">{dataTip}</Text>
)}
effect="float"
place="left"
maxWidth={320}
color="#f8f7bf"
/>
</div>
) : (
<div className="download_panel-icon">
<LoadingButton
percent={currentFileUploadProgress}
onClick={() => cancelCurrentUpload(index)}
/>
</div>
)}
</>
</StyledFileRow>
)}
</>
);
};
const mapStateToProps = (state, ownProps) => {
const loadingFile = getLoadingFile(state);
const { item } = ownProps;
const { uniqueId } = item;
return {
currentFile: (fileId) => getFileByFileId(state, fileId),
currentFileUploadProgress:
loadingFile && loadingFile.uniqueId === uniqueId
? loadingFile.percent
: null,
};
};
export default connect(mapStateToProps)(FileRow);

View File

@ -0,0 +1,91 @@
import React from "react";
import styled from "styled-components";
const backgroundColor = "none";
const color = "#2DA7DB";
const StyledCircleWrap = styled.div`
width: 16px;
height: 16px;
background: ${backgroundColor};
border-radius: 50%;
cursor: pointer;
`;
const StyledCircle = styled.div`
.circle__mask,
.circle__fill {
width: 16px;
height: 16px;
position: absolute;
border-radius: 50%;
}
.circle__mask {
clip: rect(0px, 16px, 16px, 8px);
}
.circle__fill {
animation: fill-rotate ease-in-out none;
transform: rotate(${(props) => props.percent * 1.8}deg);
}
.circle__mask .circle__fill {
clip: rect(0px, 8px, 16px, 0px);
background-color: ${color};
}
.circle__mask.circle__full {
animation: fill-rotate ease-in-out none;
transform: rotate(${(props) => props.percent * 1.8}deg);
}
@keyframes fill-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(${(props) => props.percent * 1.8}deg);
}
}
`;
const StyledLoadingButton = styled.div`
width: 12px;
height: 12px;
border-radius: 50%;
text-align: center;
line-height: 12px;
background: #fff;
position: absolute;
margin: 2px;
color: #2da7db;
font-size: 16px;
font-weight: bold;
`;
const LoadingButton = ({ id, className, style, ...rest }) => {
const { percent, onClick } = rest;
return (
<StyledCircleWrap
id={id}
className={className}
style={style}
onClick={onClick}
>
<StyledCircle percent={percent}>
<div className="circle__mask circle__full">
<div className="circle__fill"></div>
</div>
<div className="circle__mask">
<div className="circle__fill"></div>
</div>
<StyledLoadingButton>&times;</StyledLoadingButton>
</StyledCircle>
</StyledCircleWrap>
);
};
export default LoadingButton;

View File

@ -0,0 +1,245 @@
import React from "react";
import {
Backdrop,
Heading,
Aside,
IconButton,
Icons,
} from "asc-web-components";
import { connect } from "react-redux";
import { withRouter } from "react-router";
import { withTranslation } from "react-i18next";
import { utils as commonUtils, store } from "asc-web-common";
import {
setDownloadPanelVisible,
setSharingPanelVisible,
cancelUpload,
cancelCurrentUpload,
setMediaViewerData,
setSelection,
setSelected,
} from "../../../store/files/actions";
import {
getDownloadPanelVisible,
getUploadDataFiles,
getArchiveFormats,
getImageFormats,
getSoundFormats,
getSharePanelVisible,
getMediaViewerImageFormats,
getMediaViewerMediaFormats,
getSelected,
} from "../../../store/files/selectors";
import SharingPanel from "../SharingPanel";
import {
StyledAsidePanel,
StyledContent,
StyledHeaderContent,
StyledBody,
} from "../StyledPanels";
import FileRow from "./FileRow";
import { createI18N } from "../../../helpers/i18n";
const i18n = createI18N({
page: "DownloadPanel",
localesPath: "panels/DownloadPanel",
});
const { changeLanguage } = commonUtils;
const { getCurrentUserId } = store.auth.selectors;
const DownloadBodyStyle = { height: `calc(100vh - 156px)` };
class DownloadPanelComponent extends React.Component {
constructor(props) {
super(props);
changeLanguage(i18n);
this.state = {
uploadData: [],
};
this.ref = React.createRef();
this.scrollRef = React.createRef();
}
onClose = () => {
this.props.setDownloadPanelVisible(!this.props.downloadPanelVisible);
};
componentDidMount() {
document.addEventListener("keyup", this.onKeyPress);
}
componentWillUnmount() {
document.removeEventListener("keyup", this.onKeyPress);
}
componentDidUpdate(prevProps, prevState) {
const { uploadDataFiles } = this.props;
if (
prevState.uploadData !== uploadDataFiles &&
uploadDataFiles.length > 0
) {
this.setState({
uploadData: prevProps.uploadDataFiles,
});
}
}
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.onClose();
}
};
clearDownloadPanel = () => {
this.setState({
uploadData: [],
uploaded: false,
});
this.onClose();
};
cancelCurrentUpload = (index) => {
this.props.cancelCurrentUpload(index);
console.log("cancel upload ", index);
};
onOpenSharingPanel = (item) => {
console.log(item);
const {
selected,
setSelected,
setSelection,
setSharingPanelVisible,
sharingPanelVisible,
} = this.props;
selected === "close" && setSelected("none");
setSelection([item]);
setSharingPanelVisible(!sharingPanelVisible);
};
onMediaClick = (id) => {
console.log("id", id);
const item = { visible: true, id: id };
this.props.setMediaViewerData(item);
};
render() {
const {
t,
downloadPanelVisible,
sharingPanelVisible,
uploadDataFiles,
archiveFormats,
imageFormats,
soundFormats,
mediaViewerImageFormats,
mediaViewerMediaFormats,
} = this.props;
const { uploadData } = this.state;
const uploaded = uploadDataFiles.length === 0;
const visible = downloadPanelVisible;
const zIndex = 310;
return (
<StyledAsidePanel visible={visible}>
<Backdrop
onClick={this.onClose}
visible={visible}
zIndex={zIndex}
isAside={true}
/>
<Aside className="header_aside-panel" visible={visible}>
<StyledContent>
<StyledHeaderContent>
<Heading className="download_panel-header" size="medium" truncate>
{t("Uploads")}
</Heading>
<div className="download_panel-icons-container">
<div className="download_panel-remove-icon">
{uploaded ? (
<IconButton
size="20"
iconName="ClearActiveIcon"
color="#A3A9AE"
isClickable={true}
onClick={this.clearDownloadPanel}
/>
) : (
<IconButton
size="20"
iconName="ButtonCancelIcon"
color="#A3A9AE"
isClickable={true}
onClick={this.props.cancelUpload}
/>
)}
</div>
{/*<div className="download_panel-vertical-dots-icon">
<IconButton
size="20"
iconName="VerticalDotsIcon"
color="#A3A9AE"
/>
</div>*/}
</div>
</StyledHeaderContent>
<StyledBody stype="mediumBlack" style={DownloadBodyStyle}>
{uploadData.map((item, index) => (
<FileRow
t={t}
item={item}
key={index}
index={index}
archiveFormats={archiveFormats}
imageFormats={imageFormats}
soundFormats={soundFormats}
uploaded={uploaded}
cancelCurrentUpload={this.cancelCurrentUpload}
onOpenSharingPanel={this.onOpenSharingPanel}
mediaViewerImageFormats={mediaViewerImageFormats}
mediaViewerMediaFormats={mediaViewerMediaFormats}
onMediaClick={this.onMediaClick}
/>
))}
</StyledBody>
</StyledContent>
</Aside>
{sharingPanelVisible && <SharingPanel />}
</StyledAsidePanel>
);
}
}
const DownloadPanelContainerTranslated = withTranslation()(
DownloadPanelComponent
);
const DownloadPanel = (props) => (
<DownloadPanelContainerTranslated i18n={i18n} {...props} />
);
const mapStateToProps = (state) => {
return {
isMyId: getCurrentUserId(state),
downloadPanelVisible: getDownloadPanelVisible(state),
uploadDataFiles: getUploadDataFiles(state),
archiveFormats: getArchiveFormats(state),
imageFormats: getImageFormats(state),
soundFormats: getSoundFormats(state),
sharingPanelVisible: getSharePanelVisible(state),
mediaViewerImageFormats: getMediaViewerImageFormats(state),
mediaViewerMediaFormats: getMediaViewerMediaFormats(state),
selected: getSelected(state),
};
};
export default connect(mapStateToProps, {
setDownloadPanelVisible,
setSharingPanelVisible,
cancelUpload,
cancelCurrentUpload,
setMediaViewerData,
setSelection,
setSelected,
})(withRouter(DownloadPanel));

View File

@ -0,0 +1,5 @@
{
"Uploads":"Uploads",
"UnknownError ":"Unknown Error "
}

View File

@ -0,0 +1,5 @@
{
"Uploads":"Загрузки",
"UnknownError ":"Неопределенная ошибка"
}

View File

@ -6,6 +6,7 @@ import OperationsPanel from "./OperationsPanel";
import NewFilesPanel from "./NewFilesPanel";
import VersionHistoryPanel from "./VersionHistoryPanel";
import ChangeOwnerPanel from "./ChangeOwnerPanel";
import DownloadPanel from "./DownloadPanel";
export {
SharingPanel,
@ -16,4 +17,5 @@ export {
NewFilesPanel,
VersionHistoryPanel,
ChangeOwnerPanel,
DownloadPanel,
};