Web: Files: added new DownloadDialog, refactoring
This commit is contained in:
parent
294045b788
commit
9e99fed6b5
3
products/ASC.Files/Client/public/images/arrow.react.svg
Normal file
3
products/ASC.Files/Client/public/images/arrow.react.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.58586 6.00008L3.29297 1.70718L4.70718 0.292969L9.70718 5.29297C10.0977 5.68349 10.0977 6.31666 9.70718 6.70718L4.70718 11.7072L3.29297 10.293L7.58586 6.00008Z" fill="#657077"/>
|
||||
</svg>
|
After Width: | Height: | Size: 332 B |
@ -1,58 +1,26 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import Row from "@appserver/components/row";
|
||||
import RowContent from "@appserver/components/row-content";
|
||||
import RowContainer from "@appserver/components/row-container";
|
||||
import React, { useState } from "react";
|
||||
import Text from "@appserver/components/text";
|
||||
import LinkWithDropdown from "@appserver/components/link-with-dropdown";
|
||||
import styled, { css } from "styled-components";
|
||||
import { tablet } from "@appserver/components/utils/device";
|
||||
|
||||
const MobileStyles = css`
|
||||
.row-content_tablet-side-info {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
.download-dialog-link {
|
||||
text-decoration: underline dashed;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDownloadContent = styled.div`
|
||||
.row_content,
|
||||
.row-content_tablet-side-info {
|
||||
overflow: unset;
|
||||
}
|
||||
|
||||
.download-dialog_row-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
${isMobile && MobileStyles}
|
||||
|
||||
@media ${tablet} {
|
||||
${MobileStyles}
|
||||
}
|
||||
`;
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import ArrowIcon from "../../../../public/images/arrow.react.svg";
|
||||
import { StyledDownloadContent } from "./StyledDownloadDialog";
|
||||
import DownloadRow from "./DownloadRow";
|
||||
|
||||
const DownloadContent = (props) => {
|
||||
const {
|
||||
t,
|
||||
checkedTitle,
|
||||
indeterminateTitle,
|
||||
items,
|
||||
onSelectFormat,
|
||||
onRowSelect,
|
||||
getItemIcon,
|
||||
titleFormat,
|
||||
type,
|
||||
extsConvertible,
|
||||
title,
|
||||
isChecked,
|
||||
isIndeterminate,
|
||||
showHeader,
|
||||
} = props;
|
||||
|
||||
const [isScrolling, setIsScrolling] = useState(null);
|
||||
const [isOpen, setIsOpen] = useState(null);
|
||||
|
||||
const getTitleExtensions = () => {
|
||||
let arr = [];
|
||||
for (let item of items) {
|
||||
@ -95,21 +63,6 @@ const DownloadContent = (props) => {
|
||||
return formats;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isScrolling) {
|
||||
setIsOpen(false);
|
||||
const id = setTimeout(() => setIsScrolling(false), 500);
|
||||
return () => {
|
||||
clearTimeout(id);
|
||||
setIsOpen(null);
|
||||
};
|
||||
}
|
||||
}, [isScrolling]);
|
||||
|
||||
const onScroll = () => {
|
||||
setIsScrolling(true);
|
||||
};
|
||||
|
||||
const getFormats = (item) => {
|
||||
const arrayFormats = item ? extsConvertible[item.fileExst] : [];
|
||||
const formats = [
|
||||
@ -134,122 +87,84 @@ const DownloadContent = (props) => {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case "document":
|
||||
case "documents":
|
||||
return formats;
|
||||
case "spreadsheet":
|
||||
case "spreadsheets":
|
||||
return formats;
|
||||
case "presentation":
|
||||
case "presentations":
|
||||
return formats;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const length = items.length;
|
||||
const minHeight = length > 2 ? 110 : length * 50;
|
||||
const showTitle = length > 1;
|
||||
const isOther = type === "other";
|
||||
|
||||
const titleData = getTitleExtensions();
|
||||
const titleData = !isOther && getTitleExtensions();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const onOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledDownloadContent>
|
||||
{showTitle && (
|
||||
<Row
|
||||
key={"title"}
|
||||
onSelect={onRowSelect.bind(this, "All", type)}
|
||||
checked={checkedTitle}
|
||||
indeterminate={indeterminateTitle}
|
||||
>
|
||||
<RowContent convertSideInfo={false}>
|
||||
<Text truncate type="page" title={title} fontSize="14px">
|
||||
<StyledDownloadContent isOpen={showHeader ? isOpen : true}>
|
||||
{showHeader && (
|
||||
<div className="download-dialog_content-wrapper">
|
||||
<Checkbox
|
||||
data-item-id="All"
|
||||
data-type={type}
|
||||
isChecked={isChecked}
|
||||
isIndeterminate={isIndeterminate}
|
||||
onChange={onRowSelect}
|
||||
className="download-dialog-checkbox"
|
||||
/>
|
||||
<div
|
||||
onClick={onOpen}
|
||||
className="download-dialog-heading download-dialog_row-text"
|
||||
>
|
||||
<Text noSelect fontSize="16px" fontWeight={600}>
|
||||
{title}
|
||||
</Text>
|
||||
<></>
|
||||
<Text fontSize="12px" containerMinWidth="fit-content">
|
||||
{(checkedTitle || indeterminateTitle) && t("ConvertInto")}
|
||||
</Text>
|
||||
{checkedTitle || indeterminateTitle ? (
|
||||
<LinkWithDropdown
|
||||
className="download-dialog-link"
|
||||
containerMinWidth="fit-content"
|
||||
data={titleData}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
dropdownType="appearDashedAfterHover"
|
||||
fontSize="12px"
|
||||
>
|
||||
{titleFormat}
|
||||
</LinkWithDropdown>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</RowContent>
|
||||
</Row>
|
||||
)}
|
||||
<ArrowIcon className="download-dialog-icon" />
|
||||
</div>
|
||||
|
||||
<RowContainer
|
||||
useReactWindow={length > 2}
|
||||
style={{ minHeight: minHeight, padding: "8px 0" }}
|
||||
itemHeight={50}
|
||||
onScroll={onScroll}
|
||||
>
|
||||
{items.map((file) => {
|
||||
const element = getItemIcon(file);
|
||||
let dropdownItems = getFormats(file);
|
||||
dropdownItems = dropdownItems.filter(
|
||||
(x) => x.label !== file.fileExst
|
||||
);
|
||||
return (
|
||||
<Row
|
||||
key={file.id}
|
||||
onSelect={onRowSelect.bind(this, file, type)}
|
||||
checked={file.checked}
|
||||
element={element}
|
||||
{(isChecked || isIndeterminate) && !isOther && (
|
||||
<LinkWithDropdown
|
||||
containerMinWidth="fit-content"
|
||||
data={titleData}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
dropdownType="alwaysDashed"
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
>
|
||||
<RowContent convertSideInfo={false}>
|
||||
<Text
|
||||
truncate
|
||||
type="page"
|
||||
title={file.title}
|
||||
fontSize="14px"
|
||||
noSelect
|
||||
>
|
||||
{file.title}
|
||||
</Text>
|
||||
<></>
|
||||
{file.checked && (
|
||||
<Text
|
||||
fontSize="12px"
|
||||
containerMinWidth="fit-content"
|
||||
noSelect
|
||||
>
|
||||
{t("ConvertInto")}
|
||||
</Text>
|
||||
)}
|
||||
{titleFormat}
|
||||
</LinkWithDropdown>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="download-dialog_hidden-items">
|
||||
{items.map((file) => {
|
||||
const dropdownItems =
|
||||
!isOther &&
|
||||
getFormats(file).filter((x) => x.label !== file.fileExst);
|
||||
|
||||
{file.checked ? (
|
||||
<LinkWithDropdown
|
||||
className="download-dialog-link"
|
||||
isOpen={isOpen}
|
||||
dropdownType={
|
||||
isMobile ? "alwaysDashed" : "appearDashedAfterHover"
|
||||
}
|
||||
containerMinWidth="fit-content"
|
||||
data={dropdownItems}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
fontSize="12px"
|
||||
>
|
||||
{file.format || t("OriginalFormat")}
|
||||
</LinkWithDropdown>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</RowContent>
|
||||
</Row>
|
||||
return (
|
||||
<DownloadRow
|
||||
t={t}
|
||||
key={file.id}
|
||||
file={file}
|
||||
isChecked={file.checked}
|
||||
onRowSelect={onRowSelect}
|
||||
type={type}
|
||||
isOther={isOther}
|
||||
dropdownItems={dropdownItems}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
</div>
|
||||
</StyledDownloadContent>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,104 @@
|
||||
import React, { useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import Text from "@appserver/components/text";
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import LinkWithDropdown from "@appserver/components/link-with-dropdown";
|
||||
|
||||
const DownloadRow = (props) => {
|
||||
const {
|
||||
t,
|
||||
file,
|
||||
onRowSelect,
|
||||
type,
|
||||
dropdownItems,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
isOther,
|
||||
isChecked,
|
||||
} = props;
|
||||
|
||||
//console.log("DownloadRow render");
|
||||
|
||||
const [dropDownIsOpen, setDropDownIsOpen] = useState(false);
|
||||
|
||||
const getItemIcon = (item) => {
|
||||
const extension = item.fileExst;
|
||||
const icon = extension
|
||||
? getIcon(32, extension)
|
||||
: getFolderIcon(item.providerKey, 32);
|
||||
|
||||
return (
|
||||
<ReactSVG
|
||||
beforeInjection={(svg) => {
|
||||
svg.setAttribute("style", "margin-top: 4px; margin-right: 12px;");
|
||||
}}
|
||||
src={icon}
|
||||
loading={() => <div style={{ width: "96px" }} />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const element = getItemIcon(file);
|
||||
|
||||
return (
|
||||
<div className="download-dialog_row">
|
||||
<Checkbox
|
||||
className="download-dialog-checkbox"
|
||||
data-item-id={file.id}
|
||||
data-type={type}
|
||||
onChange={onRowSelect}
|
||||
isChecked={isChecked}
|
||||
/>
|
||||
{element}
|
||||
<Text
|
||||
className="download-dialog_row-text"
|
||||
truncate
|
||||
type="page"
|
||||
title={file.title}
|
||||
fontSize="14px"
|
||||
fontWeight={600}
|
||||
noSelect
|
||||
>
|
||||
{file.title}
|
||||
</Text>
|
||||
{file.checked && !isOther && (
|
||||
<LinkWithDropdown
|
||||
className="download-dialog-link"
|
||||
isOpen={dropDownIsOpen}
|
||||
dropdownType="alwaysDashed"
|
||||
containerMinWidth="fit-content"
|
||||
data={dropdownItems}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
>
|
||||
{file.format || t("OriginalFormat")}
|
||||
</LinkWithDropdown>
|
||||
)}
|
||||
{isOther && file.fileExst && (
|
||||
<Text
|
||||
className="download-dialog-other-text"
|
||||
truncate
|
||||
type="page"
|
||||
title={file.title}
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
noSelect
|
||||
>
|
||||
{t("OriginalFormat")}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ settingsStore }) => {
|
||||
const { getIcon, getFolderIcon } = settingsStore;
|
||||
|
||||
return {
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
};
|
||||
})(observer(DownloadRow));
|
@ -0,0 +1,72 @@
|
||||
import styled from "styled-components";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
|
||||
const StyledDownloadDialog = styled(ModalDialog)`
|
||||
.modal-dialog-content {
|
||||
padding: 0 0 0 16px;
|
||||
}
|
||||
|
||||
.download-dialog-description {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.modal-dialog-aside-footer {
|
||||
display: flex;
|
||||
padding-right: 32px;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDownloadContent = styled.div`
|
||||
.download-dialog_row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
|
||||
.download-dialog-other-text {
|
||||
min-width: 141px;
|
||||
}
|
||||
}
|
||||
|
||||
.download-dialog-checkbox {
|
||||
padding: 8px 6px 8px 8px;
|
||||
}
|
||||
|
||||
.download-dialog_row-text {
|
||||
width: 100%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.download-dialog-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.download-dialog_content-wrapper {
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.download-dialog-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
transform: ${({ isOpen }) =>
|
||||
isOpen ? "rotate(270deg)" : "rotate(90deg)"};
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.download-dialog_hidden-items {
|
||||
display: ${({ isOpen }) => (isOpen ? "block" : "none")};
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledDownloadDialog, StyledDownloadContent };
|
@ -1,85 +1,88 @@
|
||||
import React from "react";
|
||||
import { withRouter } from "react-router";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { StyledDownloadDialog } from "./StyledDownloadDialog";
|
||||
import ModalDialog from "@appserver/components/modal-dialog";
|
||||
import Button from "@appserver/components/button";
|
||||
import Text from "@appserver/components/text";
|
||||
import LinkWithDropdown from "@appserver/components/link-with-dropdown";
|
||||
import Row from "@appserver/components/row";
|
||||
import RowContent from "@appserver/components/row-content";
|
||||
import RowContainer from "@appserver/components/row-container";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import DownloadContent from "./DownloadContent";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
class DownloadDialogComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { sortedFiles, t } = this.props;
|
||||
const {
|
||||
documents,
|
||||
spreadsheets,
|
||||
presentations,
|
||||
other,
|
||||
} = this.props.sortedFiles;
|
||||
|
||||
this.state = {
|
||||
documents: sortedFiles.documents,
|
||||
spreadsheets: sortedFiles.spreadsheets,
|
||||
presentations: sortedFiles.presentations,
|
||||
other: sortedFiles.other,
|
||||
|
||||
documentsTitleFormat: null,
|
||||
spreadsheetsTitleFormat: null,
|
||||
presentationsTitleFormat: null,
|
||||
|
||||
checkedDocTitle: true,
|
||||
checkedSpreadsheetTitle: true,
|
||||
checkedPresentationTitle: true,
|
||||
checkedOtherTitle: true,
|
||||
|
||||
indeterminateDocTitle: false,
|
||||
indeterminateSpreadsheetTitle: false,
|
||||
indeterminatePresentationTitle: false,
|
||||
indeterminateOtherTitle: false,
|
||||
documents: {
|
||||
isChecked: true, //checkedDocTitle
|
||||
isIndeterminate: false, //indeterminateDocTitle
|
||||
format: null, //documentsTitleFormat
|
||||
files: documents,
|
||||
},
|
||||
spreadsheets: {
|
||||
isChecked: true, //checkedSpreadsheetTitle
|
||||
isIndeterminate: false, //isIndeterminateSpreadsheetTitle
|
||||
format: null, //spreadsheetsTitleFormat
|
||||
files: spreadsheets,
|
||||
},
|
||||
presentations: {
|
||||
isChecked: true, //checkedPresentationTitle
|
||||
isIndeterminate: false, //indeterminatePresentationTitle
|
||||
format: null, //presentationsTitleFormat
|
||||
files: presentations,
|
||||
},
|
||||
other: {
|
||||
isChecked: true, //checkedOtherTitle
|
||||
isIndeterminate: false, //indeterminateOtherTitle
|
||||
files: other,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
onClose = () => this.props.setDownloadDialogVisible(false);
|
||||
|
||||
getDownloadItems = () => {
|
||||
const { documents, spreadsheets, presentations, other } = this.state;
|
||||
const itemList = [
|
||||
...this.state.documents.files,
|
||||
...this.state.spreadsheets.files,
|
||||
...this.state.presentations.files,
|
||||
...this.state.other.files,
|
||||
];
|
||||
|
||||
const files = [];
|
||||
const folders = [];
|
||||
let singleFileUrl = null;
|
||||
|
||||
const collectItems = (itemList) => {
|
||||
for (let item of itemList) {
|
||||
if (item.checked) {
|
||||
if (item.fileExst) {
|
||||
const format =
|
||||
!item.format || item.format === this.props.t("OriginalFormat")
|
||||
? item.fileExst
|
||||
: item.format;
|
||||
if (!singleFileUrl) {
|
||||
singleFileUrl = item.viewUrl;
|
||||
}
|
||||
files.push({ key: item.id, value: format });
|
||||
} else {
|
||||
folders.push(item.id);
|
||||
for (let item of itemList) {
|
||||
if (item.checked) {
|
||||
if (!!item.fileExst || item.contentLength) {
|
||||
const format =
|
||||
!item.format || item.format === this.props.t("OriginalFormat")
|
||||
? item.fileExst
|
||||
: item.format;
|
||||
if (!singleFileUrl) {
|
||||
singleFileUrl = item.viewUrl;
|
||||
}
|
||||
files.push({ key: item.id, value: format });
|
||||
} else {
|
||||
folders.push(item.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
collectItems(documents);
|
||||
collectItems(spreadsheets);
|
||||
collectItems(presentations);
|
||||
collectItems(other);
|
||||
}
|
||||
|
||||
return [files, folders, singleFileUrl];
|
||||
};
|
||||
|
||||
onDownload = () => {
|
||||
const { t, downloadFiles } = this.props;
|
||||
|
||||
const [fileConvertIds, folderIds, singleFileUrl] = this.getDownloadItems();
|
||||
|
||||
if (fileConvertIds.length === 1 && folderIds.length === 0) {
|
||||
// Single file download as
|
||||
const file = fileConvertIds[0];
|
||||
@ -94,23 +97,6 @@ class DownloadDialogComponent extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
getItemIcon = (item) => {
|
||||
const extension = item.fileExst;
|
||||
const icon = extension
|
||||
? this.props.getIcon(24, extension)
|
||||
: this.props.getFolderIcon(item.providerKey, 24);
|
||||
|
||||
return (
|
||||
<ReactSVG
|
||||
beforeInjection={(svg) => {
|
||||
svg.setAttribute("style", "margin-top: 4px");
|
||||
}}
|
||||
src={icon}
|
||||
loading={this.svgLoader}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
getNewArrayFiles = (fileId, array, format) => {
|
||||
//Set all documents format
|
||||
if (!fileId) {
|
||||
@ -134,210 +120,108 @@ class DownloadDialogComponent extends React.Component {
|
||||
|
||||
onSelectFormat = (e) => {
|
||||
const { format, type, fileId } = e.target.dataset;
|
||||
const { documents, spreadsheets, presentations } = this.state;
|
||||
const { t } = this.props;
|
||||
const files = this.state[type].files;
|
||||
|
||||
const newDocuments = documents.slice();
|
||||
const newSpreadsheets = spreadsheets.slice();
|
||||
const newPresentations = presentations.slice();
|
||||
this.setState((prevState) => {
|
||||
const newState = { ...prevState };
|
||||
newState[type].files = this.getNewArrayFiles(fileId, files, format);
|
||||
newState[type].format = !fileId ? format : this.props.t("CustomFormat");
|
||||
|
||||
if (type === "document") {
|
||||
const documents = this.getNewArrayFiles(fileId, newDocuments, format);
|
||||
this.setState({
|
||||
documents,
|
||||
documentsTitleFormat: !fileId ? format : t("CustomFormat"),
|
||||
return { ...prevState, ...newState };
|
||||
});
|
||||
};
|
||||
|
||||
updateDocsState = (fieldStateName, itemId) => {
|
||||
const { isChecked, isIndeterminate, files } = this.state[fieldStateName];
|
||||
|
||||
if (itemId === "All") {
|
||||
const checked = isIndeterminate ? false : !isChecked;
|
||||
for (let file of files) {
|
||||
file.checked = checked;
|
||||
}
|
||||
|
||||
this.setState((prevState) => {
|
||||
const newState = { ...prevState };
|
||||
|
||||
newState[fieldStateName].files = files;
|
||||
newState[fieldStateName].isIndeterminate = false;
|
||||
newState[fieldStateName].isChecked = checked;
|
||||
|
||||
return { ...prevState, ...newState };
|
||||
});
|
||||
} else if (type === "spreadsheet") {
|
||||
const spreadsheets = this.getNewArrayFiles(
|
||||
fileId,
|
||||
newSpreadsheets,
|
||||
format
|
||||
);
|
||||
this.setState({
|
||||
spreadsheets,
|
||||
spreadsheetsTitleFormat: !fileId ? format : t("CustomFormat"),
|
||||
});
|
||||
} else if (type === "presentation") {
|
||||
const presentations = this.getNewArrayFiles(
|
||||
fileId,
|
||||
newPresentations,
|
||||
format
|
||||
);
|
||||
this.setState({
|
||||
presentations,
|
||||
presentationsTitleFormat: !fileId ? format : t("CustomFormat"),
|
||||
} else {
|
||||
const file = files.find((x) => x.id == itemId);
|
||||
file.checked = !file.checked;
|
||||
|
||||
const disableFiles = files.find((x) => x.checked === false);
|
||||
const activeFiles = files.find((x) => x.checked === true);
|
||||
const isIndeterminate = !activeFiles ? false : !!disableFiles;
|
||||
const isChecked = disableFiles ? false : true;
|
||||
|
||||
this.setState((prevState) => {
|
||||
const newState = { ...prevState };
|
||||
|
||||
newState[fieldStateName].files = files;
|
||||
newState[fieldStateName].isIndeterminate = isIndeterminate;
|
||||
newState[fieldStateName].isChecked = isChecked;
|
||||
|
||||
return { ...prevState, ...newState };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onRowSelect = (item, type) => {
|
||||
const {
|
||||
documents,
|
||||
spreadsheets,
|
||||
presentations,
|
||||
other,
|
||||
checkedDocTitle,
|
||||
checkedSpreadsheetTitle,
|
||||
checkedPresentationTitle,
|
||||
checkedOtherTitle,
|
||||
indeterminateDocTitle,
|
||||
indeterminateSpreadsheetTitle,
|
||||
indeterminatePresentationTitle,
|
||||
indeterminateOtherTitle,
|
||||
} = this.state;
|
||||
onRowSelect = (e) => {
|
||||
const { itemId, type } = e.currentTarget.dataset;
|
||||
|
||||
const newDocuments = documents;
|
||||
const newSpreadsheets = spreadsheets;
|
||||
const newPresentations = presentations;
|
||||
const newOthers = other;
|
||||
switch (type) {
|
||||
case "documents":
|
||||
this.updateDocsState("documents", itemId);
|
||||
|
||||
if (type === "document") {
|
||||
//Select all documents
|
||||
if (item === "All") {
|
||||
const checked = indeterminateDocTitle ? false : !checkedDocTitle;
|
||||
for (let file of newDocuments) {
|
||||
file.checked = checked;
|
||||
}
|
||||
this.setState({
|
||||
documents: newDocuments,
|
||||
indeterminateDocTitle: false,
|
||||
checkedDocTitle: checked,
|
||||
});
|
||||
} else {
|
||||
//Select single document
|
||||
const newDoc = newDocuments.find((x) => x.id === item.id);
|
||||
newDoc.checked = !newDoc.checked;
|
||||
break;
|
||||
case "spreadsheets":
|
||||
this.updateDocsState("spreadsheets", itemId);
|
||||
break;
|
||||
case "presentations":
|
||||
this.updateDocsState("presentations", itemId);
|
||||
break;
|
||||
case "other":
|
||||
this.updateDocsState("other", itemId);
|
||||
break;
|
||||
|
||||
const disableFiles = newDocuments.find((x) => x.checked === false);
|
||||
const activeFiles = newDocuments.find((x) => x.checked === true);
|
||||
const indeterminate = !activeFiles ? false : !!disableFiles;
|
||||
const title = disableFiles ? false : true;
|
||||
this.setState({
|
||||
documents: newDocuments,
|
||||
indeterminateDocTitle: indeterminate,
|
||||
checkedDocTitle: title,
|
||||
});
|
||||
}
|
||||
} else if (type === "spreadsheet") {
|
||||
if (item === "All") {
|
||||
//Select all spreadsheets
|
||||
const checked = indeterminateSpreadsheetTitle
|
||||
? false
|
||||
: !checkedSpreadsheetTitle;
|
||||
for (let spreadsheet of newSpreadsheets) {
|
||||
spreadsheet.checked = checked;
|
||||
}
|
||||
this.setState({
|
||||
spreadsheets: newSpreadsheets,
|
||||
indeterminateSpreadsheetTitle: false,
|
||||
checkedSpreadsheetTitle: checked,
|
||||
});
|
||||
} else {
|
||||
//Select single spreadsheet
|
||||
const newSpreadsheet = newSpreadsheets.find((x) => x.id === item.id);
|
||||
newSpreadsheet.checked = !newSpreadsheet.checked;
|
||||
|
||||
const disableSpreadsheet = newSpreadsheets.find(
|
||||
(x) => x.checked === false
|
||||
);
|
||||
const activeSpreadsheet = newSpreadsheets.find(
|
||||
(x) => x.checked === true
|
||||
);
|
||||
const indeterminate = !activeSpreadsheet ? false : !!disableSpreadsheet;
|
||||
const title = disableSpreadsheet ? false : true;
|
||||
this.setState({
|
||||
spreadsheets: newSpreadsheets,
|
||||
indeterminateSpreadsheetTitle: indeterminate,
|
||||
checkedSpreadsheetTitle: title,
|
||||
});
|
||||
}
|
||||
} else if (type === "presentation") {
|
||||
if (item === "All") {
|
||||
//Select all presentations
|
||||
const checked = indeterminatePresentationTitle
|
||||
? false
|
||||
: !checkedPresentationTitle;
|
||||
for (let presentation of newPresentations) {
|
||||
presentation.checked = checked;
|
||||
}
|
||||
this.setState({
|
||||
presentations: newPresentations,
|
||||
indeterminatePresentationTitle: false,
|
||||
checkedPresentationTitle: checked,
|
||||
});
|
||||
} else {
|
||||
//Select single presentation
|
||||
const newPresentation = newPresentations.find((x) => x.id === item.id);
|
||||
newPresentation.checked = !newPresentation.checked;
|
||||
|
||||
const disablePresentation = newPresentations.find(
|
||||
(x) => x.checked === false
|
||||
);
|
||||
const activePresentation = newPresentations.find(
|
||||
(x) => x.checked === true
|
||||
);
|
||||
const indeterminate = !activePresentation
|
||||
? false
|
||||
: !!disablePresentation;
|
||||
const title = disablePresentation ? false : true;
|
||||
this.setState({
|
||||
presentations: newPresentations,
|
||||
indeterminatePresentationTitle: indeterminate,
|
||||
checkedPresentationTitle: title,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (item === "All") {
|
||||
const checked = indeterminateOtherTitle ? false : !checkedOtherTitle;
|
||||
for (let folder of newOthers) {
|
||||
folder.checked = checked;
|
||||
}
|
||||
this.setState({
|
||||
other: newOthers,
|
||||
indeterminateOtherTitle: false,
|
||||
checkedOtherTitle: checked,
|
||||
});
|
||||
} else {
|
||||
const newOther = newOthers.find((x) => x.id === item.id);
|
||||
newOther.checked = !newOther.checked;
|
||||
|
||||
const disableFolders = newOthers.find((x) => x.checked === false);
|
||||
const activeFolders = newOthers.find((x) => x.checked === true);
|
||||
|
||||
const indeterminate = !activeFolders ? false : !!disableFolders;
|
||||
const title = disableFolders ? false : true;
|
||||
this.setState({
|
||||
other: newOthers,
|
||||
indeterminateOtherTitle: indeterminate,
|
||||
checkedOtherTitle: title,
|
||||
});
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { visible, t, tReady, extsConvertible } = this.props;
|
||||
const {
|
||||
documentsTitleFormat,
|
||||
spreadsheetsTitleFormat,
|
||||
presentationsTitleFormat,
|
||||
documents,
|
||||
other,
|
||||
spreadsheets,
|
||||
presentations,
|
||||
checkedDocTitle,
|
||||
checkedSpreadsheetTitle,
|
||||
checkedPresentationTitle,
|
||||
checkedOtherTitle,
|
||||
indeterminateDocTitle,
|
||||
indeterminateSpreadsheetTitle,
|
||||
indeterminatePresentationTitle,
|
||||
indeterminateOtherTitle,
|
||||
} = this.state;
|
||||
const { t, tReady, visible, extsConvertible } = this.props;
|
||||
|
||||
const otherLength = other.length;
|
||||
const showOther = otherLength > 1;
|
||||
const minHeight = otherLength > 2 ? 110 : otherLength * 50;
|
||||
const {
|
||||
files: documents,
|
||||
isChecked: checkedDocTitle,
|
||||
isIndeterminate: indeterminateDocTitle,
|
||||
format: documentsTitleFormat,
|
||||
} = this.state.documents;
|
||||
|
||||
const {
|
||||
files: spreadsheets,
|
||||
isChecked: checkedSpreadsheetTitle,
|
||||
isIndeterminate: isIndeterminateSpreadsheetTitle,
|
||||
format: spreadsheetsTitleFormat,
|
||||
} = this.state.spreadsheets;
|
||||
|
||||
const {
|
||||
files: presentations,
|
||||
isChecked: checkedPresentationTitle,
|
||||
isIndeterminate: indeterminatePresentationTitle,
|
||||
format: presentationsTitleFormat,
|
||||
} = this.state.presentations;
|
||||
|
||||
const {
|
||||
files: other,
|
||||
isChecked: checkedOtherTitle,
|
||||
isIndeterminate: indeterminateOtherTitle,
|
||||
} = this.state.other;
|
||||
|
||||
const isSingleFile =
|
||||
documents.filter((f) => f.checked).length +
|
||||
@ -346,152 +230,102 @@ class DownloadDialogComponent extends React.Component {
|
||||
other.filter((f) => f.checked).length <=
|
||||
1;
|
||||
|
||||
const showHeader =
|
||||
documents.length +
|
||||
spreadsheets.length +
|
||||
presentations.length +
|
||||
other.length >
|
||||
1;
|
||||
|
||||
const downloadContentProps = {
|
||||
t,
|
||||
extsConvertible,
|
||||
onSelectFormat: this.onSelectFormat,
|
||||
onRowSelect: this.onRowSelect,
|
||||
getItemIcon: this.getItemIcon,
|
||||
showHeader,
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
isLoading={!tReady}
|
||||
<StyledDownloadDialog
|
||||
visible={visible}
|
||||
displayType="aside"
|
||||
onClose={this.onClose}
|
||||
isLoading={!tReady}
|
||||
>
|
||||
<ModalDialog.Header>{t("Translations:DownloadAs")}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
<Text noSelect>{t("ChooseFormatText")}</Text>
|
||||
<div className="download-dialog-description">
|
||||
<Text noSelect>{t("ChooseFormatText")}.</Text>
|
||||
{!isSingleFile && <Text noSelect>{t("ConvertToZip")}</Text>}
|
||||
</div>
|
||||
{documents.length > 0 && (
|
||||
<DownloadContent
|
||||
t={t}
|
||||
extsConvertible={extsConvertible}
|
||||
checkedTitle={checkedDocTitle}
|
||||
indeterminateTitle={indeterminateDocTitle}
|
||||
{...downloadContentProps}
|
||||
isChecked={checkedDocTitle}
|
||||
isIndeterminate={indeterminateDocTitle}
|
||||
items={documents}
|
||||
onSelectFormat={this.onSelectFormat}
|
||||
onRowSelect={this.onRowSelect}
|
||||
getItemIcon={this.getItemIcon}
|
||||
titleFormat={documentsTitleFormat || t("OriginalFormat")}
|
||||
type="document"
|
||||
type="documents"
|
||||
title={t("Common:Documents")}
|
||||
/>
|
||||
)}
|
||||
|
||||
{spreadsheets.length > 0 && (
|
||||
<DownloadContent
|
||||
t={t}
|
||||
extsConvertible={extsConvertible}
|
||||
checkedTitle={checkedSpreadsheetTitle}
|
||||
indeterminateTitle={indeterminateSpreadsheetTitle}
|
||||
{...downloadContentProps}
|
||||
isChecked={checkedSpreadsheetTitle}
|
||||
isIndeterminate={isIndeterminateSpreadsheetTitle}
|
||||
items={spreadsheets}
|
||||
onSelectFormat={this.onSelectFormat}
|
||||
onRowSelect={this.onRowSelect}
|
||||
getItemIcon={this.getItemIcon}
|
||||
titleFormat={spreadsheetsTitleFormat || t("OriginalFormat")}
|
||||
type="spreadsheet"
|
||||
type="spreadsheets"
|
||||
title={t("Translations:Spreadsheets")}
|
||||
/>
|
||||
)}
|
||||
|
||||
{presentations.length > 0 && (
|
||||
<DownloadContent
|
||||
t={t}
|
||||
extsConvertible={extsConvertible}
|
||||
checkedTitle={checkedPresentationTitle}
|
||||
indeterminateTitle={indeterminatePresentationTitle}
|
||||
{...downloadContentProps}
|
||||
isChecked={checkedPresentationTitle}
|
||||
isIndeterminate={indeterminatePresentationTitle}
|
||||
items={presentations}
|
||||
onSelectFormat={this.onSelectFormat}
|
||||
onRowSelect={this.onRowSelect}
|
||||
getItemIcon={this.getItemIcon}
|
||||
titleFormat={presentationsTitleFormat || t("OriginalFormat")}
|
||||
type="presentation"
|
||||
type="presentations"
|
||||
title={t("Translations:Presentations")}
|
||||
/>
|
||||
)}
|
||||
|
||||
{otherLength > 0 && (
|
||||
<>
|
||||
{showOther && (
|
||||
<Row
|
||||
key="title2"
|
||||
onSelect={this.onRowSelect.bind(this, "All", "other")}
|
||||
checked={checkedOtherTitle}
|
||||
indeterminate={indeterminateOtherTitle}
|
||||
>
|
||||
<RowContent>
|
||||
<Text
|
||||
truncate
|
||||
type="page"
|
||||
title={"Other"}
|
||||
fontSize="14px"
|
||||
noSelect
|
||||
>
|
||||
{t("Other")}
|
||||
</Text>
|
||||
<></>
|
||||
</RowContent>
|
||||
</Row>
|
||||
)}
|
||||
|
||||
<RowContainer
|
||||
useReactWindow
|
||||
style={{ minHeight: minHeight, padding: "8px 0" }}
|
||||
itemHeight={50}
|
||||
>
|
||||
{other.map((folder) => {
|
||||
const element = this.getItemIcon(folder);
|
||||
return (
|
||||
<Row
|
||||
key={folder.id}
|
||||
onSelect={this.onRowSelect.bind(this, folder, "other")}
|
||||
checked={folder.checked}
|
||||
element={element}
|
||||
>
|
||||
<RowContent>
|
||||
<Text
|
||||
truncate
|
||||
type="page"
|
||||
title={folder.title}
|
||||
fontSize="14px"
|
||||
noSelect
|
||||
>
|
||||
{folder.title}
|
||||
</Text>
|
||||
<></>
|
||||
<LinkWithDropdown
|
||||
className="link-other-formats download-dialog-link"
|
||||
containerMinWidth="fit-content"
|
||||
data={[]}
|
||||
directionX="left"
|
||||
directionY="bottom"
|
||||
dropdownType="appearDashedAfterHover"
|
||||
fontSize="12px"
|
||||
>
|
||||
{folder.fileExst && t("OriginalFormat")}
|
||||
</LinkWithDropdown>
|
||||
</RowContent>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</RowContainer>
|
||||
</>
|
||||
{other.length > 0 && (
|
||||
<DownloadContent
|
||||
{...downloadContentProps}
|
||||
isChecked={checkedOtherTitle}
|
||||
isIndeterminate={indeterminateOtherTitle}
|
||||
items={other}
|
||||
type="other"
|
||||
title={t("Other")}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isSingleFile && <Text>{t("ConvertToZip")}</Text>}
|
||||
<Text noSelect>{t("ConvertMessage")}</Text>
|
||||
</ModalDialog.Body>
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
className="button-dialog-accept"
|
||||
key="DownloadButton"
|
||||
label={t("Common:Download")}
|
||||
size="small"
|
||||
size="normalTouchscreen"
|
||||
primary
|
||||
onClick={this.onDownload}
|
||||
scale
|
||||
/>
|
||||
<Button
|
||||
className="button-dialog"
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size="small"
|
||||
size="normalTouchscreen"
|
||||
onClick={this.onClose}
|
||||
scale
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialogContainer>
|
||||
</StyledDownloadDialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -505,7 +339,7 @@ const DownloadDialog = withTranslation([
|
||||
export default inject(
|
||||
({ filesStore, dialogsStore, filesActionsStore, settingsStore }) => {
|
||||
const { sortedFiles } = filesStore;
|
||||
const { extsConvertible, getIcon, getFolderIcon } = settingsStore;
|
||||
const { extsConvertible } = settingsStore;
|
||||
|
||||
const {
|
||||
downloadDialogVisible: visible,
|
||||
@ -519,8 +353,6 @@ export default inject(
|
||||
visible,
|
||||
extsConvertible,
|
||||
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
setDownloadDialogVisible,
|
||||
downloadFiles,
|
||||
};
|
||||
|
@ -1736,12 +1736,14 @@ class FilesStore {
|
||||
other: [],
|
||||
};
|
||||
|
||||
const selection = this.selection.length
|
||||
let selection = this.selection.length
|
||||
? this.selection
|
||||
: this.bufferSelection
|
||||
? [this.bufferSelection]
|
||||
: [];
|
||||
|
||||
selection = JSON.parse(JSON.stringify(selection));
|
||||
|
||||
for (let item of selection) {
|
||||
item.checked = true;
|
||||
item.format = null;
|
||||
|
Loading…
Reference in New Issue
Block a user